package com.southern.power.grid.utils; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; /** * 时间工具类 * * @author: junzhangfm * @date: 2026/3/14 **/ public class TimeUtil { // 完整格式:年月日 时分 private static final DateTimeFormatter FULL = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); private static final DateTimeFormatter FULL_HOUR = DateTimeFormatter.ofPattern("yyyy/MM/dd HH时"); // 仅小时格式 private static final DateTimeFormatter HOUR = DateTimeFormatter.ofPattern("dd日HH时"); // 三个区间常量 public static final int BEFORE_8 = 1; // 小于当天早8点 public static final int BETWEEN_8_20 = 2; // 早8点 ~ 晚8点(不含) public static final int AFTER_20 = 3; // 晚8点及以后 /** * 获取开始时间到结束时间的小时数组,仅当天的第一条数据会展示年月日 * 比如[2026/03/13/22, 13/23, 2026/03/14/00, 14/01] * * @param startTime 开始时间 * @param endTime 结束时间 * @return 结果 */ public static List generateHourList(String startTime, String endTime) { LocalDateTime start = LocalDateTime.parse(startTime, FULL); LocalDateTime end = LocalDateTime.parse(endTime, FULL); if (start.isAfter(end)) { throw new RuntimeException("generateHourList error! The endTime comes before the startTime."); } List result = new ArrayList<>(); LocalDateTime current = start; LocalDateTime preDate = null; while (!current.isAfter(end)) { // 第一次 或 日期发生变化(跨天0点)→ 显示完整年月日 if (preDate == null || !current.toLocalDate().equals(preDate.toLocalDate())) { result.add(current.format(FULL_HOUR)); } else { // 同一天 → 只显示小时 result.add(current.format(HOUR)); } preDate = current; current = current.plusHours(1); } return result; } /** * 获取开始时间到结束时间的小时数组,比如[2026-03-13 23:00, 2026-03-14 00:00, 2026-03-14 01:00] * * @param startTime 开始时间 * @param endTime 结束时间 * @return 结果 */ public static List generateHourListAll(String startTime, String endTime) { LocalDateTime start = LocalDateTime.parse(startTime, FULL); LocalDateTime end = LocalDateTime.parse(endTime, FULL); if (start.isAfter(end)) { throw new RuntimeException("generateHourList error! The endTime comes before the startTime."); } List result = new ArrayList<>(); LocalDateTime current = start; while (!current.isAfter(end)) { // 第一次 或 日期发生变化(跨天0点)→ 显示完整年月日 result.add(current.format(FULL)); current = current.plusHours(1); } return result; } /** * 获取开始日期到结束日期之间的所有日期(包含首尾) */ public static List getBetweenDates(String startDate, String endDate) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); List dateList = new ArrayList<>(); // 字符串转日期 LocalDate start = LocalDate.parse(startDate, formatter); LocalDate end = LocalDate.parse(endDate, formatter); // 循环遍历每一天 LocalDate current = start; while (!current.isAfter(end)) { dateList.add(current.format(formatter)); current = current.plusDays(1); } return dateList; } /** * 获取指定日期 往前推n天 的日期 * * @param dateStr 传入日期字符串 yyyy-MM-dd * @param num 前n天 * @return 前n天日期字符串 */ public static String getBeforeNumDays(String dateStr, int num) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 字符串转日期 LocalDate date = LocalDate.parse(dateStr, formatter); // 减去n天 LocalDate beforeDay = date.minusDays(num); // 转回字符串 return beforeDay.format(formatter); } /** * 获取前n个小时的时间 * * @param dateTime 指定时间 * @param beforeHourNum 前n小时,比如2 * @param formatter 返回格式 比如yyyy-MM-dd HH:00 * @return 前n小时的时间,比如2026-03-17 09:00 */ public static String getBeforeHourTime(LocalDateTime dateTime, int beforeHourNum, DateTimeFormatter formatter) { // 2. 减去 n 小时(核心方法) LocalDateTime beforeHour = dateTime.minusHours(beforeHourNum); // 3. 格式化返回(精确到小时,分钟固定 00) return beforeHour.format(formatter); } /** * 获取前n天的时间 * * @param dayTime 指定时间,比如2026-03-17 * @param beforeDayNum 前n天,比如2 * @return 前n天的日期,比如2026-03-15 */ public static String getBeforeDate(String dayTime, int beforeDayNum) { return LocalDate.parse(dayTime).minusDays(beforeDayNum).toString(); } private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static LocalDateTime parseToLocalDateTime(String dateTimeStr) { if (dateTimeStr == null || dateTimeStr.isEmpty()) { return null; } try { return LocalDateTime.parse(dateTimeStr, DEFAULT_FORMATTER); } catch (DateTimeParseException e) { return null; } } /** * 判断【当前时间 + X小时】落在哪个时间段 * @param hoursToAdd 要加的小时数 X * @return 1=早8点前, 2=8点~20点, 3=20点后 */ public static int getTargetTimeRange(long hoursToAdd) { LocalDateTime now = LocalDateTime.now(); // 当前时间 + X小时 LocalDateTime targetTime = now.plusHours(hoursToAdd); // 当天 08:00 LocalDateTime eightClock = targetTime.toLocalDate().atTime(LocalTime.of(8, 0)); // 当天 20:00 LocalDateTime twentyClock = targetTime.toLocalDate().atTime(LocalTime.of(20, 0)); if (targetTime.isBefore(eightClock)) { return BEFORE_8; } else if (targetTime.isBefore(twentyClock)) { return BETWEEN_8_20; } else { return AFTER_20; } } }