如下是给出的某个小于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;
}