springboot 工具类 日期时间列表工具类详解:高效处理日期范围的利器
日期时间列表工具类详解:高效处理日期范围的利器
在日常开发中,我们经常需要处理各种日期时间相关的业务逻辑,比如生成日期范围、计算时间差、处理闰年等。今天给大家分享一个功能强大的日期时间工具类 DateListUtil,它封装了常见的日期操作,让日期处理变得简单高效。
工具类概述
DateListUtil 是一个专门用于处理日期时间列表的工具类,主要功能包括:
- 生成日期范围内的每一天
- 生成时间范围内的小时列表
- 计算日期时间差
- 处理日期时间的加减操作
- 闰年判断和日期格式化
核心功能详解
1. 生成日期范围列表
/*** 获取两个日期之间的每一天* @param beginDate 开始日期 (格式: yyyy-MM-dd)* @param endDate 结束日期 (格式: yyyy-MM-dd)* @return 日期字符串列表*/
public static List<String> getEveryday(String beginDate, String endDate) {long days = countDay(beginDate, endDate);int[] ymd = splitYMD(beginDate);List<String> everyDays = new ArrayList();everyDays.add(beginDate);for(int i = 0; (long)i < days; ++i) {ymd = addOneDay(ymd[0], ymd[1], ymd[2]);everyDays.add(formatYear(ymd[0]) + "-" + formatMonthDay(ymd[1]) + "-" + formatMonthDay(ymd[2]));}return everyDays;
}
使用示例:
List<String> dateList = DateListUtil.getEveryday("2024-01-01", "2024-01-05");
// 返回: ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"]
2. 生成小时列表
/*** 获取两个日期时间之间的小时列表* @param beginDate 开始时间 (格式: yyyy-MM-dd HH:mm)* @param endDate 结束时间 (格式: yyyy-MM-dd HH:mm)* @return 小时字符串列表*/
public static List<String> getEveryHour(String beginDate, String endDate) {long hours = countHour(beginDate, endDate);List<String> everyHours = new ArrayList();for(int i = 0; (long)i < hours + 1L; ++i) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");LocalDateTime now = LocalDateTime.parse(beginDate, formatter);LocalDateTime oneHourLater = now.plusHours((long)i);String date = oneHourLater.format(formatter);int[] ymd = splitYMDH(date);everyHours.add(formatMonthDay(ymd[3]));}return everyHours;
}
使用示例:
List<String> hourList = DateListUtil.getEveryHour("2024-01-01 08:00", "2024-01-01 12:00");
// 返回: ["08", "09", "10", "11", "12"]
3. 时间偏移计算
/*** 获取指定时间前后的小时时间* @param beginDate 基准时间* @param hour 小时数* @param fal true:加小时, false:减小时* @return 计算后的时间字符串*/
public static String getSpecialdHour(String beginDate, Integer hour, boolean fal) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");LocalDateTime now = LocalDateTime.parse(beginDate, formatter);String date;if (fal) {LocalDateTime oneHourLater = now.plusHours((long)hour);date = oneHourLater.format(formatter);} else {LocalDateTime oneHourLater = now.minus(Duration.ofHours((long)hour));date = oneHourLater.format(formatter);}return date;
}
使用示例:
// 加3小时
String laterTime = DateListUtil.getSpecialdHour("2024-01-01 10:00", 3, true);
// 返回: "2024-01-01 13:00"// 减2小时
String earlierTime = DateListUtil.getSpecialdHour("2024-01-01 10:00", 2, false);
// 返回: "2024-01-01 08:00"
4. 时间差计算
// 计算天数差
public static long countDay(String begin, String end) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");long day = 0L;try {Date beginDate = format.parse(begin);Date endDate = format.parse(end);day = (endDate.getTime() - beginDate.getTime()) / 86400000L;} catch (ParseException var8) {var8.printStackTrace();}return day;
}// 计算小时差
public static long countHour(String begin, String end) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");long hour = 0L;try {Date beginDate = format.parse(begin);Date endDate = format.parse(end);hour = (endDate.getTime() - beginDate.getTime()) / 3600000L;} catch (ParseException var8) {var8.printStackTrace();}return hour;
}
使用示例:
long days = DateListUtil.countDay("2024-01-01", "2024-01-10"); // 返回: 9
long hours = DateListUtil.countHour("2024-01-01 08:00", "2024-01-01 18:00"); // 返回: 10
技术亮点
1. 混合使用新旧日期API
工具类巧妙地将传统的 SimpleDateFormat 与现代的 LocalDateTime 结合使用:
// 传统API - 用于简单的时间差计算
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = format.parse(begin);// 现代API - 用于复杂的时间操作
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime now = LocalDateTime.parse(beginDate, formatter);
2. 精确的闰年处理
public static boolean isLeapYear(int year) {return year >= gregorianCutoverYear ? (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) : (year % 4 == 0);
}// 闰年和平年的每月天数数组
private static final int[] DAYS_P_MONTH_LY = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private static final int[] DAYS_P_MONTH_CY = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
3. 日期分量智能处理
// 拆分年月日
public static int[] splitYMD(String date) {date = date.replace("-", "").replace(" ", "");return new int[]{Integer.parseInt(date.substring(0, 4)), // 年Integer.parseInt(date.substring(4, 6)), // 月 Integer.parseInt(date.substring(6, 8)) // 日};
}// 格式化保证两位数
public static String formatMonthDay(int decimal) {DecimalFormat df = new DecimalFormat("00");return df.format((long)decimal);
}
实际应用场景
1. 报表系统
// 生成月度报表的日期范围
public List<Report> generateMonthlyReport(String month) {String startDate = month + "-01";String endDate = month + "-31"; // 实际应该计算当月最后一天List<String> dates = DateListUtil.getEveryday(startDate, endDate);List<Report> reports = new ArrayList<>();for (String date : dates) {Report report = generateDailyReport(date);reports.add(report);}return reports;
}
2. 数据统计
// 统计每小时的访问量
public Map<String, Integer> getHourlyVisitStats(String startTime, String endTime) {List<String> hours = DateListUtil.getEveryHour(startTime, endTime);Map<String, Integer> stats = new LinkedHashMap<>();for (String hour : hours) {int count = getVisitCountByHour(hour);stats.put(hour + ":00", count);}return stats;
}
3. 任务调度
// 计算任务执行时间
public void scheduleTask(String baseTime, int delayHours) {String executeTime = DateListUtil.getSpecialdHour(baseTime, delayHours, true);// 计算任务预计完成时间(假设任务需要2小时)String estimatedEndTime = DateListUtil.getSpecialdHour(executeTime, 2, true);scheduleTaskAt(executeTime, estimatedEndTime);
}
使用注意事项
-
日期格式要求
- 日期格式必须为
yyyy-MM-dd - 日期时间格式必须为
yyyy-MM-dd HH:mm
- 日期格式必须为
-
异常处理
- 方法内部捕获了
ParseException,但生产环境建议改进异常处理 - 调用方应确保传入的日期格式正确
- 方法内部捕获了
-
性能考虑
- 对于大数据量的日期范围,建议分批处理
- 频繁调用时注意字符串操作的性能开销
-
线程安全
SimpleDateFormat不是线程安全的,需要注意使用场景
总结
DateListUtil 工具类为我们提供了一套完整的日期时间处理解决方案,具有以下优点:
- 功能全面:覆盖了日常开发中大部分的日期时间处理需求
- 使用简单:方法封装良好,调用方便
- 算法准确:正确处理了闰年、月末等边界情况
- 灵活性强:支持多种日期时间操作场景
无论是报表生成、数据分析还是任务调度,这个工具类都能大大提升开发效率。希望这个工具类能够对大家的项目开发有所帮助!
完整代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.mnsn.framework.boot.utils;import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class DateListUtil {private static transient int gregorianCutoverYear = 1582;private static final int[] DAYS_P_MONTH_LY = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};private static final int[] DAYS_P_MONTH_CY = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};public static final String SHORT_DATE_FORMAT = "yyyy-MM-dd";private static final int Y = 0;private static final int M = 1;private static final int D = 2;private static final int H = 3;public DateListUtil() {}public static List<String> getEveryday(String beginDate, String endDate) {long days = countDay(beginDate, endDate);int[] ymd = splitYMD(beginDate);List<String> everyDays = new ArrayList();everyDays.add(beginDate);for(int i = 0; (long)i < days; ++i) {ymd = addOneDay(ymd[0], ymd[1], ymd[2]);String var10001 = formatYear(ymd[0]);everyDays.add(var10001 + "-" + formatMonthDay(ymd[1]) + "-" + formatMonthDay(ymd[2]));}return everyDays;}public static List<String> getEveryHour(String beginDate, String endDate) {long hours = countHour(beginDate, endDate);List<String> everyHours = new ArrayList();for(int i = 0; (long)i < hours + 1L; ++i) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");LocalDateTime now = LocalDateTime.parse(beginDate, formatter);LocalDateTime oneHourLater = now.plusHours((long)i);String date = oneHourLater.format(formatter);int[] ymd = splitYMDH(date);everyHours.add(formatMonthDay(ymd[3]));}return everyHours;}public static String getSpecialdHour(String beginDate, Integer hour, boolean fal) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");LocalDateTime now = LocalDateTime.parse(beginDate, formatter);String date;LocalDateTime oneHourLater;if (fal) {oneHourLater = now.plusHours((long)hour);date = oneHourLater.format(formatter);} else {oneHourLater = now.minus(Duration.ofHours((long)hour));date = oneHourLater.format(formatter);}return date;}public static long countDay(String begin, String end) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");long day = 0L;try {Date beginDate = format.parse(begin);Date endDate = format.parse(end);day = (endDate.getTime() - beginDate.getTime()) / 86400000L;} catch (ParseException var8) {var8.printStackTrace();}return day;}public static long countHour(String begin, String end) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");long hour = 0L;try {Date beginDate = format.parse(begin);Date endDate = format.parse(end);hour = (endDate.getTime() - beginDate.getTime()) / 3600000L;} catch (ParseException var8) {var8.printStackTrace();}return hour;}public static int[] splitYMD(String date) {date = date.replace("-", "").replace(" ", "");int[] ymd = new int[]{Integer.parseInt(date.substring(0, 4)), Integer.parseInt(date.substring(4, 6)), Integer.parseInt(date.substring(6, 8))};return ymd;}public static int[] splitYMDH(String date) {date = date.replace("-", "").replace(" ", "");int[] ymd = new int[]{Integer.parseInt(date.substring(0, 4)), Integer.parseInt(date.substring(4, 6)), Integer.parseInt(date.substring(6, 8)), Integer.parseInt(date.substring(8, 10))};return ymd;}private static int[] addOneDay(int year, int month, int day) {if (isLeapYear(year)) {++day;if (day > DAYS_P_MONTH_LY[month - 1]) {++month;if (month > 12) {++year;month = 1;}day = 1;}} else {++day;if (day > DAYS_P_MONTH_CY[month - 1]) {++month;if (month > 12) {++year;month = 1;}day = 1;}}int[] ymd = new int[]{year, month, day};return ymd;}public static boolean isLeapYear(int year) {return year >= gregorianCutoverYear ? year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) : year % 4 == 0;}public static String formatYear(int decimal) {DecimalFormat df = new DecimalFormat("0000");return df.format((long)decimal);}public static String formatMonthDay(int decimal) {DecimalFormat df = new DecimalFormat("00");return df.format((long)decimal);}public static int convert0to24(int hour) {return hour == 0 ? 24 : hour;}
}