如何用 java 8 次 API 得到下一个 MonthDay(下一个圣诞节)?

How to get next MonthDay (next Christmas) with java 8 time API?

假设我想知道距离圣诞节还有多少天,方法适用于任何一年的任何一天,所以下一个圣诞节可能是今年或明年,我不知道它是闰年还是没有。

我可能会计算下一个圣诞节日期,然后计算从现在到那时的天数。我可以将圣诞节表示为 MonthDay.of(12, 25) 但我找不到它有什么帮助。

我发现这样计算下周一的日期很容易:

    ZonedDateTime nextMonday = ZonedDateTime.now()
            .with(TemporalAdjusters.next(DayOfWeek.MONDAY))
            .truncatedTo(ChronoUnit.DAYS);

但是我找不到任何 TemporalAdjuster 来对 MonthDay 做同样的事情。

有没有我没找到的简单方法?

我不认为有一个内置的时间调整器可以转到下一个 "MonthDay" 但你可以自己构建它:

public static void main(String[] args) {
  MonthDay XMas = MonthDay.of(DECEMBER, 25);
  System.out.println(LocalDate.of(2014, DECEMBER, 5).with(nextMonthDay(XMas)));
  System.out.println(LocalDate.of(2014, DECEMBER, 26).with(nextMonthDay(XMas)));
}

public static TemporalAdjuster nextMonthDay(MonthDay monthDay) {
  return (temporal) -> {
    int day = temporal.get(DAY_OF_MONTH);
    int month = temporal.get(MONTH_OF_YEAR);
    int targetDay = monthDay.getDayOfMonth();
    int targetMonth = monthDay.getMonthValue();
    return MonthDay.of(month, day).isBefore(monthDay)
            ? temporal.with(MONTH_OF_YEAR, targetMonth).with(DAY_OF_MONTH, targetDay)
            : temporal.with(MONTH_OF_YEAR, targetMonth).with(DAY_OF_MONTH, targetDay).plus(1, YEARS);
}

这里有一个方法,它在给定 MonthDay 的情况下创建时间调整器,就像 assylias 中的方法一样,但代码不同。我认为两者都有效。

private static TemporalAdjuster nextMonthDayAdjuster(final MonthDay md) {
    return (Temporal d) -> {
        Function<Integer, Temporal> dateOnYear = year -> md.atYear(year).adjustInto(d);
        int year = d.get(ChronoField.YEAR);
        Temporal dateThatYear = dateOnYear.apply(year);
        if (d.until(dateThatYear, ChronoUnit.NANOS) > 0L) {
            return dateThatYear;
        } else {
            return dateOnYear.apply(year + 1);
        }
    };
}

我正在使用以下时间调节器:

public static TemporalAdjuster nextOrSame(MonthDay monthDay) {
    return temporal -> monthDay.adjustInto(temporal).plus(MonthDay.from(temporal).compareTo(monthDay) > 0 ? 1 : 0, YEARS);
}

public static TemporalAdjuster previousOrSame(MonthDay monthDay) {
    return temporal -> monthDay.adjustInto(temporal).minus(MonthDay.from(temporal).compareTo(monthDay) < 0 ? 1 : 0, YEARS);
}