使用 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