用于统计的折线图点类NumberVO
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="数据统计类")
public class NumberVO {
@ApiModelProperty(value = "统计属性的名称,如镇名、举报来源")
private String name;
@ApiModelProperty(value = "统计数量")
private Integer number;
@ApiModelProperty(value = "占总体比例")
private Double rate;
}
/**
* 根据传入的类型处理表格数据,填补数据量为零的天数、月份统计点,以便前端做折线图展现
*
* @param data
* @param startTime
* @param endTime
* @param type
* @return List<NumberVO>
*/
private List<NumberVO> toChart(List<NumberVO> data, String startTime, String endTime, int type) {
LocalDate start = LocalDate.of(Integer.parseInt(startTime.substring(0, 4)), Integer.parseInt(startTime.substring(5, 7)), Integer.parseInt(startTime.substring(8, 10)));
LocalDate end = LocalDate.of(Integer.parseInt(endTime.substring(0, 4)), Integer.parseInt(endTime.substring(5, 7)), Integer.parseInt(endTime.substring(8, 10)));
//data里有不连续的天数,月份统计值等
if (type == 1) {
int startDayOfYear = start.getDayOfYear();
int endDayOfYear = end.getDayOfYear();
//计算时间段内一共有多少天
int days = endDayOfYear - startDayOfYear + 1;
//折线图的下标用具体天数
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
List<NumberVO> result = new ArrayList<>(days);
LocalDate temp = start;
//为每一天生成统计对象,如果没有统计值则为0,以生成连续的天数数组用于绘图
for (int i = 0; i < days; i++) {
NumberVO item = new NumberVO();
int theDay = temp.getDayOfMonth();
item.setName(dateTimeFormatter.format(temp));
item.setNumber(0);
//遍历统计值数组取到对应天的统计值
for (NumberVO numberVO : data) {
if (Integer.parseInt(numberVO.getName()) == theDay) {
item.setNumber(numberVO.getNumber());
break;
}
}
result.add(item);
//转到下一天
temp = temp.plusDays(1);
}
//返回连续天数的统计结果
return result;
}
if (type == 2) {
//按周统计时时间跨度不能过大,此处是小于等于六个月
int startWeek = getWeekNumber(start);
int endWeek = getWeekNumber(end);
int weeks;
if (endWeek > startWeek) {
weeks = endWeek - startWeek + 1;
} else {
weeks = endWeek + 52 - startWeek + 1;
}
List<NumberVO> result = new ArrayList<>(weeks);
int temp = startWeek;
for (int i = 0; i < weeks; i++) {
NumberVO item = new NumberVO();
item.setName(temp + "");
item.setNumber(0);
//遍历统计值数组取到对应天的统计值
for (NumberVO numberVO : data) {
if (Integer.parseInt(numberVO.getName()) == temp) {
item.setNumber(numberVO.getNumber());
break;
}
}
result.add(item);
//转到下一周
temp++;
if (temp > 52) {
temp = temp - 52;
}
}
//返回连续周数
return result;
}
if (type == 3) {
//折线图的下标用具体月份
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
List<NumberVO> result = new ArrayList<>();
int months = 0;
LocalDate temp = start;
//为每月生成统计对象,如果没有统计值则为0,以生成连续的月份数组用于绘图
while (true) {
NumberVO item = new NumberVO();
int theMonth = temp.getMonth().getValue();
int theYear = temp.getYear();
item.setName(dateTimeFormatter.format(temp));
//先默认为0
item.setNumber(0);
//去匹配数据库统计数据
for (NumberVO numberVO : data) {
//按月统计时,NumberVO里的rate是借用该属性从数据库带出来的年份值
int itemYear = Integer.parseInt(String.valueOf(numberVO.getRate()).substring(0, 4));
//年份月份一样,说明是当前月的数据
if (Integer.parseInt(numberVO.getName()) == theMonth && itemYear == theYear) {
//如有统计值,替换默认值
item.setNumber(numberVO.getNumber());
// 取到此条数据后,跳出取数循环
break;
}
}
result.add(item);
if (temp.getMonth().equals(end.getMonth()) && temp.getYear() == end.getYear()) {
//跳出条件1,当刚刚处理的月份已经达结束月份时,结束循环
break;
}
//开始处理下一个月
temp = temp.plusMonths(1);
months++;
if (months > 36) {
//跳出条件2,预防死循环,最多统计三年时长
break;
}
}
//返回连续月份的统计结果
return result;
}
return null;
}
用于计算周数的方法
private int getWeekNumber(LocalDate localDate) {
//获取当前时间第X周
/*
public static WeekFields of(DayOfWeek firstDayOfWeek, int minimalDaysInFirstWeek)
从第一天和最小日期获得WeekFields的实例。
第一天的每周定义ISO DayOfWeek ,即一周中的第一天。 第一周的最小天数定义一个月或一年中必须存在的天数,从第一天开始,在将一周计算为第一周之前。 值1将计算作为第一周的一部分的月或年的第一天,而值7将要求整个七天在新的月或年中。
WeekFields实例是单例; 对于firstDayOfWeek和minimalDaysInFirstWeek的每个唯一组合,将返回相同的实例。
参数
firstDayOfWeek - 一周的第一天,不是null
minimalDaysInFirstWeek - 第一周的最小天数,从1到7
*/
WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 4);
int weekNumber = localDate.get(weekFields.weekOfYear());
return weekNumber;
}