package cn.huge.module.cases.utils; import cn.huge.base.common.utils.DateUtils; import cn.huge.base.common.utils.ObjectUtils; import cn.huge.module.cases.domain.dto.CaseWorkStatisticsTimeDTO; import com.alibaba.fastjson.JSON; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.*; /** * 工作统计-时间计算类 * @author zhouxiantao * @create 2025-04-23 11:48 */ public class StatisticsTimeUtils { /** * 判断两个时间 1-按日统计,2-按月统计,3-按年统计 * */ public static String spanTime(Date startDate, Date endDate){ Integer differDay = DateUtils.getDifferDay(startDate, endDate); if(differDay <= 31){ return "1"; }else if(differDay > 31 && differDay <= 365){ return "2"; }else if(differDay > 365){ return "3"; } return null; } /** * 填补缺少的时间 * */ public static List dellStatisticsTime(List caseWorkStatisticsTimeDTOS, Date startDate, Date endDate,String type) { List resultList = new ArrayList<>(); if("1".equals(type)){ Integer differDay = DateUtils.getDifferDay(startDate, endDate); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // 生成所有在 startDate 和 endDate 范围内的日期 Set allDatesInRange = new HashSet<>(); LocalDate currentDate = startLocalDate; while (!currentDate.isAfter(endLocalDate)) { allDatesInRange.add(currentDate); currentDate = currentDate.plusDays(1); } // 将 caseWorkStatisticsTimeDTOs 中的日期转换为 LocalDate 并存储在 map 中 Map existingDatesMap = new HashMap<>(); for (CaseWorkStatisticsTimeDTO dto : caseWorkStatisticsTimeDTOS) { LocalDate date = LocalDate.parse(dto.getDayStr(), formatter); existingDatesMap.put(date, dto); } // 确保每个日期都在范围内 for (LocalDate date : allDatesInRange) { if (existingDatesMap.containsKey(date)) { CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = existingDatesMap.get(date); String[] split = caseWorkStatisticsTimeDTO.getDayStr().split("-"); caseWorkStatisticsTimeDTO.setTimeStr(split[2]+"日"); caseWorkStatisticsTimeDTO.setTimeAllStr(split[0]+"年"+split[1]+"月"+split[2]+"日"); int i = Integer.valueOf(split[1]) * 100 + Integer.valueOf(split[2]); caseWorkStatisticsTimeDTO.setSort(i); resultList.add(caseWorkStatisticsTimeDTO); } else { String format = date.format(formatter); String[] split = format.split("-"); CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = new CaseWorkStatisticsTimeDTO(); caseWorkStatisticsTimeDTO.setTimeStr(split[2]+"日"); caseWorkStatisticsTimeDTO.setTimeAllStr(split[0]+"年"+split[1]+"月"+split[2]+"日"); int i = Integer.valueOf(split[1]) * 100 + Integer.valueOf(split[2]); caseWorkStatisticsTimeDTO.setSort(i); resultList.add(caseWorkStatisticsTimeDTO); } } if(differDay <=7){ Collections.sort(resultList, (o1, o2) -> Integer.compare(o1.getSort(), o2.getSort())); return resultList; }else{ List result1List = new ArrayList<>(); Map> stringListMap = groupByWeek(caseWorkStatisticsTimeDTOS); for (String week : stringListMap.keySet()) { String[] split = week.split("="); String[] startTime = split[0].split("-"); String[] endTime = split[1].split("-"); CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = new CaseWorkStatisticsTimeDTO(); List caseWorkStatisticsTimeDTOS1 = stringListMap.get(week); for (CaseWorkStatisticsTimeDTO workStatisticsTimeDTO : caseWorkStatisticsTimeDTOS1) { caseWorkStatisticsTimeDTO.setTotalNum(caseWorkStatisticsTimeDTO.getTotalNum()+workStatisticsTimeDTO.getTotalNum()); caseWorkStatisticsTimeDTO.setProcessNum(caseWorkStatisticsTimeDTO.getProcessNum()+workStatisticsTimeDTO.getProcessNum()); caseWorkStatisticsTimeDTO.setFinishNum(caseWorkStatisticsTimeDTO.getFinishNum()+workStatisticsTimeDTO.getFinishNum()); caseWorkStatisticsTimeDTO.setRejectNum(caseWorkStatisticsTimeDTO.getRejectNum()+workStatisticsTimeDTO.getRejectNum()); caseWorkStatisticsTimeDTO.setResolveNum(caseWorkStatisticsTimeDTO.getResolveNum()+workStatisticsTimeDTO.getResolveNum()); caseWorkStatisticsTimeDTO.setUnResolveNum(caseWorkStatisticsTimeDTO.getUnResolveNum()+workStatisticsTimeDTO.getUnResolveNum()); caseWorkStatisticsTimeDTO.setResolveingNum(caseWorkStatisticsTimeDTO.getResolveingNum()+workStatisticsTimeDTO.getResolveingNum()); } caseWorkStatisticsTimeDTO.setTimeStr(startTime[2]+"-"+endTime[2]+"日"); caseWorkStatisticsTimeDTO.setTimeAllStr(startTime[0]+"年"+startTime[1]+"月"+startTime[2]+"-"+endTime[2]+"日"); int i = Integer.valueOf(startTime[1]) * 100 + Integer.valueOf(startTime[2]); caseWorkStatisticsTimeDTO.setSort(i); result1List.add(caseWorkStatisticsTimeDTO); } Collections.sort(result1List, (o1, o2) -> Integer.compare(o1.getSort(), o2.getSort())); return result1List; } }else if("2".equals(type)){ int startYear = DateUtils.getYear(startDate); int endYear = DateUtils.getYear(endDate); int startMonth = DateUtils.getMonth(startDate); int endMonth = DateUtils.getMonth(endDate); Integer minMonth = startYear * 100 + startMonth; Integer maxMonth = endYear * 100 + endMonth; List monthList = new ArrayList<>(); Map existingDatesMap = new HashMap<>(); for (CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO : caseWorkStatisticsTimeDTOS) { existingDatesMap.put(caseWorkStatisticsTimeDTO.getMonthStr(), caseWorkStatisticsTimeDTO); monthList.add(caseWorkStatisticsTimeDTO.getMonthStr()); } for (int i = minMonth; i <= maxMonth; i++){ Integer year = i / 100; Integer month = i % 100; if(month == 0 || month > 12){ continue; } String timeStr = year+"-"+month; if(!monthList.contains(timeStr)){ CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = new CaseWorkStatisticsTimeDTO(); caseWorkStatisticsTimeDTO.setTimeStr(month+"月"); caseWorkStatisticsTimeDTO.setTimeAllStr(year+"年"+month+"月"); caseWorkStatisticsTimeDTO.setSort(i); resultList.add(caseWorkStatisticsTimeDTO); }else{ CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = existingDatesMap.get(timeStr); caseWorkStatisticsTimeDTO.setTimeStr(month+"月"); caseWorkStatisticsTimeDTO.setTimeAllStr(year+"年"+month+"月"); caseWorkStatisticsTimeDTO.setSort(i); resultList.add(caseWorkStatisticsTimeDTO); } } }else { int minYear = DateUtils.getYear(startDate); int maxYear = DateUtils.getYear(endDate); List yearList = new ArrayList<>(); Map existingDatesMap = new HashMap<>(); for (CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO : caseWorkStatisticsTimeDTOS) { caseWorkStatisticsTimeDTO.setTimeStr(caseWorkStatisticsTimeDTO.getYearStr()); existingDatesMap.put(caseWorkStatisticsTimeDTO.getYearStr(), caseWorkStatisticsTimeDTO); yearList.add(caseWorkStatisticsTimeDTO.getYearStr()); } for (int i = minYear; i <= maxYear; i++){ String timeStr = String.valueOf(i); if(!yearList.contains(timeStr)){ CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = new CaseWorkStatisticsTimeDTO(); caseWorkStatisticsTimeDTO.setTimeStr(timeStr+"年"); caseWorkStatisticsTimeDTO.setTimeAllStr(timeStr+"年"); caseWorkStatisticsTimeDTO.setSort(i); resultList.add(caseWorkStatisticsTimeDTO); }else{ CaseWorkStatisticsTimeDTO caseWorkStatisticsTimeDTO = existingDatesMap.get(timeStr); caseWorkStatisticsTimeDTO.setTimeStr(timeStr+"年"); caseWorkStatisticsTimeDTO.setTimeAllStr(timeStr+"年"); caseWorkStatisticsTimeDTO.setSort(i); resultList.add(caseWorkStatisticsTimeDTO); } } } Collections.sort(resultList, (o1, o2) -> Integer.compare(o1.getSort(), o2.getSort())); return resultList; } /** * 按周进行分组 * */ public static Map> groupByWeek(List caseWorkStatisticsTimeDTOs) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); Map> weeklyGroups = new HashMap<>(); for (CaseWorkStatisticsTimeDTO dto : caseWorkStatisticsTimeDTOs) { LocalDate date = LocalDate.parse(dto.getDayStr(), formatter); LocalDate startOfWeek = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); LocalDate endOfWeek = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); String weekKey = startOfWeek.format(formatter) + "=" + endOfWeek.format(formatter); weeklyGroups.computeIfAbsent(weekKey, k -> new ArrayList<>()).add(dto); } // 对每个周组内的记录按时间从小到大排序 for (List group : weeklyGroups.values()) { group.sort(Comparator.comparing(CaseWorkStatisticsTimeDTO::getDayStr)); } System.out.println(JSON.toJSONString(weeklyGroups)); return weeklyGroups; } public static boolean isStartAndEndOfYear(Date startDate, Date endDate) { LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // 判断 startDate 是否是某一年的第一天 boolean isStartDateFirstDay = startLocalDate.equals(startLocalDate.with(TemporalAdjusters.firstDayOfYear())); // 判断 endDate 是否是某一年的最后一天 boolean isEndDateLastDay = endLocalDate.equals(endLocalDate.with(TemporalAdjusters.lastDayOfYear())); return isStartDateFirstDay && isEndDateLastDay && startLocalDate.getYear() == endLocalDate.getYear(); } public static boolean isStartAndEndOfMonth(Date startDate, Date endDate) { LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // 判断 startDate 是否是某个月的第一天 boolean isStartDateFirstDay = startLocalDate.equals(startLocalDate.with(TemporalAdjusters.firstDayOfMonth())); // 判断 endDate 是否是某个月的最后一天 boolean isEndDateLastDay = endLocalDate.equals(endLocalDate.with(TemporalAdjusters.lastDayOfMonth())); return isStartDateFirstDay && isEndDateLastDay && startLocalDate.getMonthValue() == endLocalDate.getMonthValue() && startLocalDate.getYear() == endLocalDate.getYear(); } /** * 获取时间的上个月开始时间 * */ public static String getMomStartDate(Date startDate) { LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); YearMonth lastMonth = YearMonth.from(startLocalDate).minusMonths(1); LocalDate firstDayOfLastMonth = lastMonth.atDay(1); Date from = Date.from(firstDayOfLastMonth.atStartOfDay(ZoneId.systemDefault()).toInstant()); String time = DateUtils.DateToString(from, DateUtils.YYYY_MM_DD); return time; } /** * 获取时间的上个月结束时间 * */ public static String getMomEndDate(Date startDate) { LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); YearMonth lastMonth = YearMonth.from(startLocalDate).minusMonths(1); LocalDate lastDayOfLastMonth = lastMonth.atEndOfMonth(); Date from = Date.from(lastDayOfLastMonth.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()); String time = DateUtils.DateToString(from, DateUtils.YYYY_MM_DD); return time; } /** * 获取时间的去年的时间 * */ public static String getYoyDate(Date startDate) { LocalDateTime startDateTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); LocalDateTime lastYearSameDateTime = startDateTime.minusYears(1); Date from = Date.from(lastYearSameDateTime.atZone(ZoneId.systemDefault()).toInstant()); String time = DateUtils.DateToString(from, DateUtils.YYYY_MM_DD); return time; } public static String calculateMomGrowthRate(int currentMonthValue, int previousMonthValue) { if (previousMonthValue == 0) { return "0"; } double rate = ((double) (currentMonthValue - previousMonthValue) / previousMonthValue) * 100; return String.format("%.1f", rate); } public static String calculateMomGrowthRate(String currentStr, String previousStr) { if(ObjectUtils.isEmpty(currentStr)){ return "0"; } double previousMonthValue = 0; if(ObjectUtils.isNotEmpty(previousStr) && !"null".equals(previousStr)){ previousMonthValue = Double.valueOf(previousStr); } double currentMonthValue = Double.valueOf(currentStr); if(currentMonthValue == 0){ return "0"; } double rate = ((double) (currentMonthValue - previousMonthValue) / previousMonthValue) * 100; return String.format("%.1f", rate); } }