使用 java.time.temporal.ChronoUnit 枚举或 Period 类可快速计算日期差。例如:
package com.hxstrive.java_date_time.calculate; import java.time.LocalDate; import java.time.Period; import java.time.temporal.ChronoUnit; public class DateDifference { public static void main(String[] args) { LocalDate start = LocalDate.of(2023, 1, 15); LocalDate end = LocalDate.of(2024, 3, 20); // 1. 使用 ChronoUnit 直接计算单个单位差值 long days = ChronoUnit.DAYS.between(start, end); long months = ChronoUnit.MONTHS.between(start, end); long years = ChronoUnit.YEARS.between(start, end); System.out.println("相差天数: " + days); System.out.println("相差月数: " + months); System.out.println("相差年数: " + years); // 2. 使用 Period 获取完整的年月日差值 Period period = Period.between(start, end); System.out.printf("相差 %d年%d月%d天%n", period.getYears(), period.getMonths(), period.getDays()); } }
运行结果:
相差天数: 430 相差月数: 14 相差年数: 1 相差 1年2月5天
注意:
ChronoUnit 计算的是两个日期之间的完整单位数(如月份差会忽略不足一个月的天数)
Period 会拆分出完整的年、月、日差值(更贴近人类对时间差的理解)
利用 TemporalAdjusters 工具类可快速定位特殊日期。例如:
package com.hxstrive.java_date_time.calculate; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; public class BoundaryDates { public static void main(String[] args) { LocalDate today = LocalDate.of(2023, 10, 5); // 当月第一天 LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 当月最后一天 LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 当年第一天 LocalDate firstDayOfYear = today.with(TemporalAdjusters.firstDayOfYear()); // 当年最后一天 LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear()); System.out.println("当月第一天: " + firstDayOfMonth); // 2023-10-01 System.out.println("当月最后一天: " + lastDayOfMonth); // 2023-10-31 System.out.println("当年第一天: " + firstDayOfYear); // 2023-01-01 System.out.println("当年最后一天: " + lastDayOfYear); // 2023-12-31 } }
运行结果:
当月第一天: 2023-10-01 当月最后一天: 2023-10-31 当年第一天: 2023-01-01 当年最后一天: 2023-12-31
注意,还可通过 firstDayOfNextMonth() 获取下月第一天,通过 dayOfWeekInMonth(n, DayOfWeek.MONDAY) 获取当月第 n 个周一。
需要自定义排除周六、周日及法定节假日的逻辑。例如:
package com.hxstrive.java_date_time.calculate; import java.time.DayOfWeek; import java.time.LocalDate; import java.util.HashSet; import java.util.Set; public class WorkingDayCalculator { // 模拟节假日(实际应用中可从配置或数据库加载) private static final Set<LocalDate> HOLIDAYS; static { HOLIDAYS = new HashSet<>(); HOLIDAYS.add(LocalDate.of(2023, 10, 1)); // 国庆节 HOLIDAYS.add(LocalDate.of(2023, 10, 2)); HOLIDAYS.add(LocalDate.of(2023, 10, 3)); } /** * 获取指定日期之后的第一个工作日 * @param date 基准日期 * @return 第一个工作日 */ public static LocalDate getFirstWorkingDayAfter(LocalDate date) { LocalDate candidate = date.plusDays(1); // 从第二天开始检查 while (true) { // 检查是否为周末 DayOfWeek dayOfWeek = candidate.getDayOfWeek(); if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) { candidate = candidate.plusDays(1); continue; } // 检查是否为节假日 if (HOLIDAYS.contains(candidate)) { candidate = candidate.plusDays(1); continue; } // 既不是周末也不是节假日,返回 return candidate; } } public static void main(String[] args) { LocalDate testDate1 = LocalDate.of(2023, 9, 29); // 周五 LocalDate testDate2 = LocalDate.of(2023, 10, 3); // 国庆假期中 LocalDate testDate3 = LocalDate.of(2023, 10, 7); // 周六 System.out.println("9月29日后的第一个工作日: " + getFirstWorkingDayAfter(testDate1)); // 10-04 System.out.println("10月3日后的第一个工作日: " + getFirstWorkingDayAfter(testDate2)); // 10-04 System.out.println("10月7日后的第一个工作日: " + getFirstWorkingDayAfter(testDate3)); // 10-09 } }
运行结果:
9月29日后的第一个工作日: 2023-10-04 10月3日后的第一个工作日: 2023-10-04 10月7日后的第一个工作日: 2023-10-09