public class Tools {
public static final double oneDayLong = 24 * 60 * 60 * 1000;// 一天时间
public static final double oneWeekLong = 7 * oneDayLong;// 一周的时间
public static final Supplier<DateFormat> dfSupplier = () -> {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
return df;
};
public static final DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
private static final String midTime = " 12:00:00";
private static final String belongWeekStartTime = "-01-01 08:30:00";
private static final String lastCalendarDayOfYearSuffix = "-12-31 23:59:59";
private static final String lastBelongCalendarDayOfYearSuffix = "-01-01 08:29:59";
/**
* 转成BigDecimal类型
*
* @param strNum
* @return bigDecimal
*/
public static BigDecimal toBigDecimal(Object strNum) {
BigDecimal bd = new BigDecimal(String.valueOf(strNum));
bd = bd.setScale(4, BigDecimal.ROUND_HALF_UP);
return bd;
}
/**
* 根据时间获取归属日
*
* @param time 时间
* @return 归属日
*/
public static String getBelongDayByDate(String time) throws ParseException {
Calendar calendar = getCalendarByTimeForBelongDay(time);
return df1.format(calendar.getTime());
}
/**
* 根据时间获取上一个归属日
*
* @param time 时间
* @return 归属日
*/
public static String getLastBelongDayByDate(String time) throws ParseException {
Calendar calendar = getCalendarByTimeForBelongDay(time);
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);// 上一个归属日
return df1.format(calendar.getTime());
}
/**
* 根据归属日获取是归属第几周
*
* @param belongDay 归属日
* @return 归属第几周
*/
public static Integer getBelongWeekByBelongDay(String belongDay) throws ParseException {
// 例如1号,1号的范围 2020-01-01 08:30:00-2020-01-02 08:30左闭右开
return getBelongWeekByDate(belongDay + midTime);
}
/**
* 根据归属日获取是自然第几周
*
* @param belongDay 归属日
* @return 自然第几周
*/
public static Integer getNormalWeekByBelongDay(String belongDay) throws ParseException {
// 例如1号,1号的范围 2020-01-01 00:00:00-2020-01-02 00:30左闭右开
return getNormalWeekByDate(belongDay + midTime);
}
/**
* 根据归属日获取是归属第几月
*
* @param belongDay 归属日
* @return 归属第几月
*/
public static Integer getBelongMonthByBelongDay(String belongDay) throws ParseException {
// 例如1号,1号的范围 2020-01-01 08:30:00-2020-01-02 08:30左闭右开
return getBelongMonthByTime(belongDay + midTime);
}
/**
* 根据归属日获取是归属第几年
*
* @param belongDay 归属日
* @return 归属第几年
*/
public static Integer getBelongYearByBelongDay(String belongDay) throws ParseException {
// 例如1号,1号的范围 2020-01-01 08:30:00-2020-01-02 08:30左闭右开
return getBelongYearByTime(belongDay + midTime);
}
/**
* 根据时间获取归属第几周,周六的8点半开始
* 从一年的起始向前凑 如果1月1号是周六 那么 这周六8点30算 第一天,
* 如果不是则向上一年找周六 8点30作为一年的起点 7天作为第一周 有可能跟自然周不一样
*
* @param time 时间
* @return 归属周 归属周
*/
public static Integer getBelongWeekByDate(String time) throws ParseException {
DateFormat df = dfSupplier.get();
Calendar timeCalendar = getCalendarByDate(time);
//Integer normalYear = timeCalendar.get(Calendar.YEAR);// 正常的年
Integer timeYear = getBelongYearByTime(time);// 归属的年
// 现在时间和这年第一周的第一天的时间差值
double timeDiff = getDateDiff(df.format(timeCalendar.getTime()),
df.format(getFirstWeekStartCalendarByYear(timeYear).getTime()));
double weekDiffFloat = timeDiff / oneWeekLong;
int week = (int) Math.floor(weekDiffFloat) + 1;
return week;
}
/**
* 根据时间获取正常第几周 周一的0点
*
* @param time 时间
* @return 正常周 正常周有可能不够7天
*/
public static Integer getNormalWeekByDate(String time) throws ParseException {
// 正常周的计算
Calendar timeCalendar = getCalendarByDate(time);
timeCalendar.setFirstDayOfWeek(Calendar.MONDAY);// 周一计算
int normalWeek = timeCalendar.get(Calendar.WEEK_OF_YEAR);
return normalWeek;
}
/**
* 获取某年的第一周起始日历
*
* @param year 年份
* @return 起始日期
*/
public static Calendar getFirstWeekStartCalendarByYear(Integer year) throws ParseException {
Calendar firstWeekCalendar;
Calendar normalFirstDayCalendar = getCalendarByDate(year + belongWeekStartTime);// 一年起始的第一天的8点30
int dayOfWeek = normalFirstDayCalendar.get(Calendar.DAY_OF_WEEK);// [1-7] 对应周日到周六
if (dayOfWeek == 5) {// 如果是周六,1月1号刚好就是 这year年 第一周的起始日期
firstWeekCalendar = normalFirstDayCalendar;
} else {// 如果dayOfWeek是4,即星期3 ,就应该向前推4天 就是上年的最后一个周六,即这年year 第一周的起始日期
normalFirstDayCalendar.set(Calendar.DATE, Calendar.DATE - dayOfWeek);
// normalFirstDayCalendar.add(Calendar.DATE, -dayOfWeek);
firstWeekCalendar = normalFirstDayCalendar;
}
return firstWeekCalendar;
}
/**
* 根据时间获取归属月[1-12]
*
* @param time 时间
* @return 归属月
*/
public static Integer getBelongMonthByTime(String time) throws ParseException {
Calendar timeCalendar = getCalendarByDate(time);
int month = timeCalendar.get(Calendar.MONTH);// [0-11]
if (timeCalendar.before(getFistDayOfMonthForBelongMonth(time))) {// 当月第一天的起始日期
month = month - 1;
}
return month + 1;
}
/**
* 根据时间获取归属年
*
* @param time 时间
* @return 归属年
*/
public static Integer getBelongYearByTime(String time) throws ParseException {
Calendar timeCalendar = getCalendarByDate(time);
int year = timeCalendar.get(Calendar.YEAR);
if (timeCalendar.before(getFistDayOfYearForBelongYear(time))) {// 当月第一天的8点30起始日期
year = year - 1;
}
return year;
}
/**
* 根据时间获取归属日日历
*
* @param time 时间
* @return 归属日日期
* @throws ParseException
*/
private static Calendar getCalendarByTimeForBelongDay(String time) throws ParseException {
Calendar calendar = getCalendarByDate(time);
int day = calendar.get(Calendar.DATE);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
if (hour < 8 || (hour == 8 && minutes < 30)) {// 小于8点半,算前一天
calendar.set(Calendar.DATE, day - 1);
}
return calendar;
}
/**
* 根据时间获取日历
*
* @param time 时间
* @return 日历
*/
public static Calendar getCalendarByDate(String time) throws ParseException {
DateFormat df = dfSupplier.get();
Date d = df.parse(time);
Calendar calendar = df.getCalendar();
calendar.clear();
calendar.setTime(d);
return calendar;
}
/**
* 归属月计算:当月第一天 8点半为起始日期
*
* @param time 时间
* @return 当月第一天
* @throws ParseException
*/
public static Calendar getFistDayOfMonthForBelongMonth(String time) throws ParseException {
//创建日历
Calendar ca = getCalendarByDate(time);
//将日历时间调整到1号0时0分0秒
ca.set(Calendar.DAY_OF_MONTH, 1);
ca.set(Calendar.HOUR_OF_DAY, 8);
ca.set(Calendar.MINUTE, 30);
ca.set(Calendar.SECOND, 0);
ca.set(Calendar.MILLISECOND, 0);
//返回结果
return ca;
}
/**
* 归属年计算:当年第一天的8点半为起始日期
*
* @param time 时间
* @return 当年第一天
* @throws ParseException
*/
public static Calendar getFistDayOfYearForBelongYear(String time) throws ParseException {
//创建日历
Calendar ca = getCalendarByDate(time);
ca.clear();
ca.set(Calendar.YEAR, 1);
ca.set(Calendar.HOUR_OF_DAY, 8);
ca.set(Calendar.MINUTE, 30);
ca.set(Calendar.SECOND, 0);
ca.set(Calendar.MILLISECOND, 0);
//返回结果
return ca;
}
/**
* 获取两个时间之差
*
* @param d1 d1
* @param d2 d2
* @return 日期之差
*/
public static Long getDateDiff(String d1, String d2) {
DateFormat df = dfSupplier.get();
Long diff = null;
try {
Date d11 = df.parse(d1);
Date d22 = df.parse(d2);
diff = d11.getTime() - d22.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return diff;
}
/**
* 自然月:获取上月最后一天
*
* @param time 日期
* @return
*/
public static Date getLastDayOfMonth(String time) throws ParseException {
DateFormat df = dfSupplier.get();
Calendar calendar = df.getCalendar();
calendar.clear();
//设置时间
calendar.setTime(df.parse(time));
//将日历时间调整到上月最后一天
calendar.set(Calendar.DAY_OF_MONTH, 0);
//将日历时间加一个月
calendar.add(Calendar.MONTH, 1);
//将日历时间调整到0时0分0秒
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
//返回结果
return calendar.getTime();
}
/**
* 获取某月所有日期
*
* @param time
* @return 日期集合
*/
public static List<Date> monthToDates(String time) throws ParseException {
DateFormat df = dfSupplier.get();
Calendar calendar = df.getCalendar();
calendar.clear();
//创建list列表
List<Date> dts = new ArrayList<Date>();
//设置时间
calendar.setTime(df.parse(time));
//将时间调整到当前日历月份最后一天
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, 0);
//获取当前日历月份的实际总天数
int dayNumOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
//将日历时间指向当前日历月份的一号
calendar.set(Calendar.DAY_OF_MONTH, 1);
for (int i = 0; i < dayNumOfMonth; i++, calendar.add(Calendar.DATE, 1)) {
//设置为0时0分0秒0毫秒
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
//将Calendar日期对象转换为Date时间对象,保存到提前创建的列表中
Date d = calendar.getTime();
dts.add(d);
}
return dts;
}
/**
* 获取一年有多少周
*
* @param time 时间
* @return 多少周
* @throws ParseException
*/
public Integer getNormalWeeksOfYear(String time) throws ParseException {
DateFormat df = dfSupplier.get();
Calendar calendar = df.getCalendar();
calendar.clear();
calendar.setTime(df.parse(time));
return calendar.getWeeksInWeekYear();
}
/**
* 归属周:获取一年有多少归属周
*
* @param time 时间
* @return 多少周
* @throws ParseException
*/
public Integer getBelongWeeksOfYear(String time) throws ParseException {
Integer belongYear = getBelongYearByTime(time);
String lastBelongDayOfYearTime = belongYear + lastBelongCalendarDayOfYearSuffix;
return getBelongWeekByBelongDay(lastBelongDayOfYearTime);
}
/**
* 求解四分位
*
* @param data 数据
* @return 四分位
*/
public static BigDecimal[] fourDivsion(BigDecimal[] data) {
if (data == null || (data != null && data.length < 4)) return null;
int len = data.length;// 数组长度
Arrays.sort(data); // 数组排序,从小到大
BigDecimal q1; // 第一四分位
BigDecimal q2; // 第二四分位
BigDecimal q3; // 第三四分位
int index = 0; // 记录下标
// n代表项数,因为下标是从0开始所以这里理解为:len = n+1
if (len % 2 == 0) { // 偶数
index = new BigDecimal(len).divide(new BigDecimal("4")).intValue();
q1 = data[index - 1].multiply(new BigDecimal("0.25")).add(data[index].multiply(new BigDecimal("0.75")));
q2 = data[len / 2].add(data[len / 2 - 1]).divide(new BigDecimal("2"));
index = new BigDecimal(3 * (len + 1)).divide(new BigDecimal("4")).intValue();
q3 = data[index - 1].multiply(new BigDecimal("0.75")).add(data[index].multiply(new BigDecimal("0.25")));
} else { // 奇数
q1 = data[new BigDecimal(len).multiply(new BigDecimal("0.25")).intValue()];
q2 = data[new BigDecimal(len).multiply(new BigDecimal("0.5")).intValue()];
q3 = data[new BigDecimal(len).multiply(new BigDecimal("0.75")).intValue()];
}
BigDecimal[] bigDecimals = {q1, q2, q3};
return bigDecimals;
}
/**
* 根据箱线图求解正常数据
*
* @param data 数据
* @return 四分位
*/
public static void setNormalDataByFourDivision(List<BigDecimal> data) {
if (data == null || (data != null && data.size() < 4)) return;
BigDecimal[] bigDecimals = fourDivsion(MyListUtil.asArray(data, BigDecimal.class));
double avg = getAvgByFourDivision(data);// 均值
if (V.notEmpty(bigDecimals)) {
int index = 0;
for (BigDecimal value : data) {
if (value.compareTo(BigDecimal.valueOf(avg).multiply(BigDecimal.valueOf(3))) > 0) {// 很大的数据
data.set(index, BigDecimal.valueOf(avg));
}
index++;
}
}
}
/**
* 根据箱线图求解正常数据
*
* @param data 数据
* @return 四分位
*/
public static double getSumByFourDivision(List<BigDecimal> data) {
setNormalDataByFourDivision(data);
return data.stream().mapToDouble(x -> Double.valueOf(String.valueOf(x))).sum();
}
/**
* 根据箱线图求均值
*
* @param data 数据
* @return 四分位
*/
public static double getAvgByFourDivision(List<BigDecimal> data) {
double avg = 0.0;
if (data == null || (data != null && data.size() < 4)) return avg;
BigDecimal[] bigDecimals = fourDivsion(MyListUtil.asArray(data, BigDecimal.class));
if (V.notEmpty(bigDecimals)) {
int num = 0;
for (BigDecimal value : data) {
if (value.compareTo(bigDecimals[2]) > 0 || value.compareTo(bigDecimals[0]) < 0) {// 很大的数据或很小的数据舍弃
continue;
}
avg = avg + Double.valueOf(String.valueOf(value));
num++;
}
avg = avg / num;
}
return avg;
}
/**
* 求均值
*
* @param data 数据
* @return 均值
*/
public static double calAvg(List<BigDecimal> data) {
return data.stream().mapToDouble(x -> Double.valueOf(String.valueOf(x))).average().orElse(0);// 均值
}
}
自定义工具类:数据统计处理四分位数据,日期工具类
最新推荐文章于 2024-09-03 17:50:14 发布