java - 查找下一次出现的时间,例如 TemporalAdjuster

标签 java java-time jsr310

JSR-310 中是否有用于查找给定时间的下一次出现的内容?我真的在寻找与 this question 相同的东西但时间而不是几天。

例如,从 2020-09-17 的 06:30 UTC 开始,我想找到下一次出现的 05:30:

LocalTime time = LocalTime.of(5, 30);
ZonedDateTime startDateTime = ZonedDateTime.of(2020, 9, 17, 6, 30, 0, 0, ZoneId.of("UTC"));

ZonedDateTime nextTime = startDateTime.with(TemporalAdjusters.next(time)); // This doesn't exist

在上面,我希望 nextTime 代表 2020-09-18 的 05:30 UTC,即第二天早上 05:30。

为了阐明我的期望,时间为 05:30:

----------------------------------------
| startDateTime    | expected nextTime |
| 2020-09-07 06:30 | 2020-09-08 05:30  |
| 2020-09-07 05:00 | 2020-09-07 05:30  |
| 2020-09-07 05:30 | 2020-09-08 05:30  |
----------------------------------------

最佳答案

如果您只是想让它与 LocalDateTimeLocalTime 或任何其他类型的具有 24 小时制的 Temporal 一起使用天,逻辑很简单:

public static TemporalAdjuster nextTime(LocalTime time) {
    return temporal -> {
        LocalTime lt = LocalTime.from(temporal);
        if (lt.isBefore(time)) {
            return temporal.with(time);
        } else {
            return temporal.plus(Duration.ofHours(24)).with(time);
        }
    };
}

但对所有具有时间分量的 Temporal 执行此操作实际上非常困难。想一想您必须为 ZonedDateTime 做什么。我们可能需要增加 23 或 25 小时,而不是增加 24 小时,因为 DST 转换会使“一天”变短或变长。您可以通过添加一个“日”来稍微解决这个问题:

public static TemporalAdjuster nextTime(LocalTime time) {
    return temporal -> {
        LocalTime lt = LocalTime.from(temporal);
        if (lt.isBefore(time) || !temporal.isSupported(ChronoUnit.DAYS)) {
            return temporal.with(time);
        } else {
            return temporal.plus(1, ChronoUnit.DAYS).with(time);
        }
    };
}

但是,它仍然不能总是正确地处理间隙和重叠。例如,当我们要求从 01:31 开始的下一个 01:30 时,在 02:00 有一个 1 小时的重叠过渡,即时钟在 02:00 倒退一个小时。正确答案是加上 59 分钟,但是上面的代码会给我们一个第二天的日期时间。要处理这种情况,您需要像 Andreas 的回答那样做一些复杂的事情。

如果你看看其他内置的时间调节器,它们都非常简单,所以我猜他们只是不想加入这种复杂性。

关于java - 查找下一次出现的时间,例如 TemporalAdjuster,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63934816/

相关文章:

java - 将十六进制编码的 ESCDA 私钥转换为 Java PrivateKey 接口(interface)

java - Java中的继承和重载

java - 检查本地时间与另一个时区的给定时间

java - 如何使用 Jackson 数据类型 : JSR310 Deser standalone?

Java 8 异常 : com. fastxml.jackson.datatype.jsr310.deser.InstantDeserializer 没有默认(无参数)构造函数

javax.xml.parsers.FactoryConfigurationError : Provider org. 找不到 apache.xerces.jaxp.DocumentBuilderFactoryImpl

java - 以 Java 8 风格重构 if-else if 链

bean-validation - bean-validation 的日期约束和 java.time 怎么样?

java - OffsetDateTime 与 Spring Data Couchbase

android - 使用 LocalDate 而不是日月年的 DatepickerDialog