「下一个工作日」「每月最后一个星期五」这类规则,TemporalAdjuster 可以把它们变成一个可复用、可测试的值。这篇逐个验证内置调整器的边界,写一个自己的调整器并逐天比对,并看它能用在哪些时间类型上。
[builtin]
基准日期 2026-10-04 SUNDAY
firstDayOfMonth() → 2026-10-01 THURSDAY
lastDayOfMonth() → 2026-10-31 SATURDAY
firstDayOfNextMonth() → 2026-11-01 SUNDAY
firstDayOfYear() → 2026-01-01 THURSDAY
lastDayOfYear() → 2026-12-31 THURSDAY
firstDayOfNextYear() → 2027-01-01 FRIDAY
next(SUNDAY) → 2026-10-11 SUNDAY
nextOrSame(SUNDAY) → 2026-10-04 SUNDAY
previous(SUNDAY) → 2026-09-27 SUNDAY
previousOrSame(SUNDAY) → 2026-10-04 SUNDAY
firstInMonth(MONDAY) → 2026-10-05 MONDAY
lastInMonth(FRIDAY) → 2026-10-30 FRIDAY
原对象不变(不可变):d = 2026-10-04 [dowim]
2026-10 有 5 个星期五;2026-02 有 4 个星期五
dayOfWeekInMonth( 1, FRIDAY):2026-10 → 2026-10-02;2026-02 → 2026-02-06
dayOfWeekInMonth( 2, FRIDAY):2026-10 → 2026-10-09;2026-02 → 2026-02-13
dayOfWeekInMonth( 4, FRIDAY):2026-10 → 2026-10-23;2026-02 → 2026-02-27
dayOfWeekInMonth( 5, FRIDAY):2026-10 → 2026-10-30;2026-02 → 2026-03-06
dayOfWeekInMonth( 0, FRIDAY):2026-10 → 2026-09-25;2026-02 → 2026-01-30
dayOfWeekInMonth(-1, FRIDAY):2026-10 → 2026-10-30;2026-02 → 2026-02-27
dayOfWeekInMonth(-2, FRIDAY):2026-10 → 2026-10-23;2026-02 → 2026-02-20
dayOfWeekInMonth(-5, FRIDAY):2026-10 → 2026-10-02;2026-02 → 2026-01-30
dayOfWeekInMonth(-6, FRIDAY):2026-10 → 2026-09-25;2026-02 → 2026-01-23
lastInMonth(FRIDAY) 与 dayOfWeekInMonth(-1, FRIDAY) 相同:true [custom]
假期:国庆 2026-10-01、10-02、10-05、10-06、10-07(周末 10-03、10-04 照常休息)
2026-09-30 WEDNESDAY → NEXT_WORKING_DAY = 2026-10-08 THURSDAY
2026-10-01 THURSDAY → NEXT_WORKING_DAY = 2026-10-08 THURSDAY
2026-10-04 SUNDAY → NEXT_WORKING_DAY = 2026-10-08 THURSDAY
2026-10-07 WEDNESDAY → NEXT_WORKING_DAY = 2026-10-08 THURSDAY
2026-10-08 THURSDAY → NEXT_WORKING_DAY = 2026-10-09 FRIDAY
2026-10-09 FRIDAY → NEXT_WORKING_DAY = 2026-10-12 MONDAY
与手写 while 循环对比:2020-01-01 ~ 2030-12-31 共 4018 天,不一致 0 天
d.with(adj) 与 adj.adjustInto(d) 相同:true [types]
LocalDate 2026-10-04 with(NEXT_WORKING_DAY) → 2026-10-08
LocalDateTime 2026-10-04T15:30 with(NEXT_WORKING_DAY) → 2026-10-08T15:30
ZonedDateTime 2026-10-04T15:30+08:00[Asia/Shanghai] with(NEXT_WORKING_DAY) → 2026-10-08T15:30+08:00[Asia/Shanghai]
OffsetDateTime 2026-10-04T15:30+08:00 with(NEXT_WORKING_DAY) → 2026-10-08T15:30+08:00
YearMonth 2026-10 → DateTimeException: Unable to obtain LocalDate from TemporalAccessor: 2026-10 of type java.time.YearMonth
LocalTime 15:30 → DateTimeException: Unable to obtain LocalDate from TemporalAccessor: 15:30 of type java.time.LocalTime
Instant 2026-10-04T07:30:00Z → DateTimeException: Unable to obtain LocalDate from TemporalAccessor: 2026-10-04T07:30:00Z of type java.time.Instant
ThaiBuddhistDate ThaiBuddhist BE 2569-10-04 with(NEXT_WORKING_DAY) → ThaiBuddhist BE 2569-10-08
JapaneseDate Japanese Reiwa 8-10-04 with(NEXT_WORKING_DAY) → Japanese Reiwa 8-10-08
MinguoDate Minguo ROC 115-10-04 with(NEXT_WORKING_DAY) → Minguo ROC 115-10-08
同样的 lastDayOfMonth():
LocalDate → 2026-10-31
LocalDateTime → 2026-10-31T15:30
ZonedDateTime → 2026-10-31T15:30+08:00[Asia/Shanghai]
OffsetDateTime → 2026-10-31T15:30+08:00
YearMonth → UnsupportedTemporalTypeException: Unsupported field: DayOfMonth
LocalTime → UnsupportedTemporalTypeException: Unsupported field: DayOfMonth
Instant → UnsupportedTemporalTypeException: Unsupported field: DayOfMonth
ThaiBuddhistDate → ThaiBuddhist BE 2569-10-31
JapaneseDate → Japanese Reiwa 8-10-31
MinguoDate → Minguo ROC 115-10-31 [dst]
起点 2026-03-06T02:30-05:00[America/New_York](周FRIDAY)
with(nextOrSame(SUNDAY)) → 2026-03-08T03:30-04:00[America/New_York](03-08 的 02:30 在纽约不存在,被顺延)
with(firstDayOfNextMonth()) → 2026-04-01T02:30-04:00[America/New_York]
起点 2026-10-30T01:30-04:00[America/New_York] → with(nextOrSame(SUNDAY)) = 2026-11-01T01:30-04:00[America/New_York](重叠的 11-01 01:30 取较早偏移)
同一个起点 plusDays(2) = 2026-03-08T03:30-04:00[America/New_York](与 with(nextOrSame(SUNDAY)) 结果相同) [chain]
8 月最后一个工作日:2026-08-31 MONDAY(月末 2026-08-31 MONDAY)
9 月最后一个工作日:2026-09-30 WEDNESDAY(月末 2026-09-30 WEDNESDAY)
10 月最后一个工作日:2026-10-30 FRIDAY(月末 2026-10-31 SATURDAY)
11 月最后一个工作日:2026-11-30 MONDAY(月末 2026-11-30 MONDAY)
每月 25 号发薪,遇非工作日提前:
2026-09-25 FRIDAY → 2026-09-25 FRIDAY
2026-10-25 SUNDAY → 2026-10-23 FRIDAY
2026-11-25 WEDNESDAY → 2026-11-25 WEDNESDAY
2026-12-25 FRIDAY → 2026-12-25 FRIDAY