自定义工具类:数据统计处理四分位数据,日期工具类

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);// 均值
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值