【问题标题】:How to get next MonthDay (next Christmas) with java 8 time API?如何使用 java 8 time API 获取下个月日(下一个圣诞节)?
【发布时间】:2015-05-13 13:08:59
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • ZonedDateTime 不是解决您问题的正确数据类型。请改用LocalDate
  • @MenoHochschild 只是评论还是会有帮助?
  • 这也将有所帮助,因为它是一个强大的简化。对于LocalDate,@assylias 的建议是 100% 安全且有效。使用ZonedDateTime,您还必须深入考虑与时区相关的内容。您的问题的性质不需要超过日期精度。让事情变得过于复杂只是资源的腰部。
  • @MenoHochschild 你想发布一个简化的答案吗?我无法理解它如何帮助代码变得更简单。
  • 但是@assylias 已经发布了使用LocalDate 的解决方案,甚至展示了如何在LocalDate 的实例上应用自定义调整器的示例。您当然也可以在LocalDate.now(timezone) 上应用他的调节器。我会接受他的回答,然后你就可以摆脱任何时区的东西(除了得到 now()-instance of LocalDate)。

标签: time java-8 java-time


【解决方案1】:

我认为没有内置的时间调整器可以转到下一个“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);
}

【讨论】:

  • 我担心plus 一年会增加 365 天,但我检查了一下,事实并非如此,所以您的调节器应该可以工作。谢谢
  • @user270349 是的,它应该妥善处理闰年。除了主要的 2 个示例之外,我没有对其进行过测试,因此您可能需要在使用它之前运行一些测试。
  • 这就是 java.time 没有这个的问题,你必须测试你的代码。我也制作了自己的 TemporalAdjuster。
【解决方案2】:

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

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);
}

【讨论】:

    【解决方案3】:

    这是一种在给定 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);
            }
        };
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      相关资源
      最近更新 更多