java利用Calendar类和localDateTime对于时间折线图的横坐标的一个实现工具类

2 篇文章 0 订阅

如下是给出的某个小于7天的时间段转换为一周的计算过程,这类处理通常可以用于数据图上,比如折线图类型,需要展示某个时间段内的数据,但是需要显示的是周几,而且数据库通常存储的是Date或者DateTime类型的时间格式,如果前端传入周几的话其实是基本不可能的,一旦传入时间的话,就需要用其他方法去转换他。

            String[] weekDays = {"星期日", "星期一","星期二", "星期三", "星期四", "星期五", "星期六"};

利用一个字符串数组设置一个一周的映射关系。(外国的日期是周日算起是第一天,java 里的也同样如此)

		 	Calendar c = Calendar.getInstance();
		   	c.setTime(startTime);
			c.get(Calendar.DAY_OF_WEEK) - 1

利用Calendar类得到他的实例,通过setTime()这个方法把前端传入的 开始时间和结束时间传入 ,再利用get(Calendar.DAY_OF_WEEK) - 1
我们可以看看DAY_OF_WEEK的注解

		    /**
		     * Field number for <code>get</code> and <code>set</code> indicating the day
		     * of the week.  This field takes values <code>SUNDAY</code>,
		     * <code>MONDAY</code>, <code>TUESDAY</code>, <code>WEDNESDAY</code>,
		     * <code>THURSDAY</code>, <code>FRIDAY</code>, and <code>SATURDAY</code>.
		     *
		     * @see #SUNDAY
		     * @see #MONDAY
		     * @see #TUESDAY
		     * @see #WEDNESDAY
		     * @see #THURSDAY
		     * @see #FRIDAY
		     * @see #SATURDAY
		     */
		    public final static int DAY_OF_WEEK = 7;

至于为什么-1,可以看看他上面标注的SUNDAY,MONDAY…

		java.util.Calendar public static final int SUNDAY = 1
		Value of the DAY_OF_WEEK field indicating Sunday.
		  < 1.8.0_191 >

		java.util.Calendar public static final int MONDAY = 2
		Value of the DAY_OF_WEEK field indicating Monday.
		  < 1.8.0_191 >

为了和数组下标对应上,所以我选择了减一。

            //判断总长度,比他小,就是在前面,比他大则
            int len = e > w ? Math.abs(e-w) + 1  : weekDays.length - w + e + 1;
            while(len>0){
                x.add(weekDays[w]);
                w = (w+1)%weekDays.length;
                len--;
            }

图中计算的len,就是计算他两个日期之间的跨度,为什么要先判断 e > w之间的大小呢,因为日期是可能会出现跨周的,最简单的情况,传入的开始和结束处于同一周内,且开始时间是周一之后,结束时间是周6之前,直接相减即可,其余的需要准确计算之间的跨度,可以通过用一周的长度 - 开始时间的星期 + 结束时间的星期 + 1,例如:这上周4 和这周2,则转换为公示==》 7 - 4 + 2 + 1 = 6 ,在通过while循环,从起始时间的周算起,则有 4 5 6 7 1 2,或者 这周六 到 下周三 7 - 6 + 3 + 1 = 5,则有 6 7 1 2 3 ,至于为什么这样处理,当初想的是 (开始星期 - 结束星期) 可以计算出他们相差的间隔,这个间隔其实是假设两个时间都在同一周的时间内,他们之间相差的天数,所以我们只需要用 7(一周的长短),减去这个间隔就能得到两个日期的实际间隔

            List<String> x = new ArrayList<>();
            String[] weekDays = {"星期日", "星期一","星期二", "星期三", "星期四", "星期五", "星期六"};
            Calendar c = Calendar.getInstance();
            c.setTime(startTime);
            //计算开始时间是周几
            int w = c.get(Calendar.DAY_OF_WEEK) - 1;
            if (w < 0) {
                w = 0;
            }
            c.setTime(endTime);
            int e = c.get(Calendar.DAY_OF_WEEK) - 1;
            //判断总长度,比他小,就是在前面,比他大则
            int len = e > w ? Math.abs(e-w) + 1  : weekDays.length - w + e + 1;
            while(len>0){
                x.add(weekDays[w]);
                w = (w+1)%weekDays.length;
                len--;
            }
            return x;

对应的按日期分组统计的sql是

        SELECT DATE(分组时间字段) AS timeVal,SUM(${param.groupVal}) AS floatVal FROM 表名
        WHERE 分组时间字段 BETWEEN #{param.dateStartStr} AND #{param.dateEndStr}
        GROUP BY timeVal
        ORDER BY timeVal

然后还有当天的时间点,比如14号的整体时间段,按小时拆分

        //根据timeType进行分段,得到x轴点
        if(timeType == TimeTypeConstants.DAY){
            //一个小时一次的查询
            ArrayList<String> x = new ArrayList<>();
            for(int i = 1;i<=24;i++){
                x.add(i + "点");
            }
            return x;
        }

对应的统计sql

SELECT DATE_FORMAT(分组的时间字段,'yyyy-MM-dd %H:00:00') AS timeVal,
               SUM(${param.groupVal}) AS floatVal FROM 表名
        WHERE 分组的时间字段 BETWEEN #{param.dateStartStr} AND #{param.dateEndStr}
        GROUP BY timeVal
        ORDER BY timeVal desc

还有月份的

      DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_DATE);
      ArrayList<String> x = new ArrayList<>();
      //遍历给定的日期期间的每一天
      for (int i = 0; !Duration.between(startDate.plusDays(i), endDate).isNegative(); i++) {
           //添加日期
           x.add(startDate.plusDays(i).format(formatter));
      }

接下来是日期补全的,有每个小时的也有每一天的,自动补全就简单很多了,DateTimeFormatter是jdk8推出的线程安全的日期格式工具,我认为是可以在大部分情况下把之前的SimpleDateFormat给替代了

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatStr);

由于上个SQL统计语句会有日期的缺失(比如某个时间段没有数据返回,sql就会直接不进行返回了,导致坐标不连续,需要我们循环比对,然后填充)

	//转map之后,对比缺少的日期,填充
    private <T> HashMap<String, T> getDateNumsMap(List<?> list,Class<T> t) {
        HashMap<String, T> map = new HashMap<>(16);
        list.forEach(f ->{
            try {
                Field at = f.getClass().getDeclaredField("at");
                Field val = f.getClass().getDeclaredField("val");
                map.put(at.toString(),  (T) val);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            }
        });
        return map;
    }
    //循环遍历填充日期
        public <T> List<T> completionYAxisData(List<String> xAxisData, HashMap<String,?> data,T initVal) throws InstantiationException, IllegalAccessException {
        ArrayList<T> dateList = new ArrayList<>(16);
        for(int i=0;i<xAxisData.size();i++){
            if(data == null ||data.get(xAxisData.get(i))==null){
                dateList.add(i,initVal);
            }
        }
        return dateList;
    }

然后还有X,Y坐标的返回形式

public  class TimeValChartVO<T> {

    List<String> xAxis;

    List<T> yAxis;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值