java - 查找下一次出现的时间,例如 TemporalAdjuster
问题描述
JSR-310 中是否有任何内容可用于查找给定时间的下一次出现?我真的在寻找与这个问题相同的东西,但时间而不是几天。
例如,从 2020 年 9 月 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,即第二天早上 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 |
----------------------------------------
解决方案
如果您只是希望它与LocalDateTime
s 和LocalTime
s 或任何其他类型的Temporal
一天 24 小时一起工作,那么逻辑非常简单:
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
具有时间分量的 s 执行此操作实际上非常困难。想想你必须做什么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 的回答。
如果你看看其他内置的时间调整器,它们都很简单,所以我猜他们只是不想加入这种复杂性。
推荐阅读
- javascript - 错误:等待仅在异步函数中有效
- html - 浏览器是否默认在后台将 HSL 转换为 RGB?
- assembly - 如何在 lldb 上打印程序集全局字符串变量
- python - 如何在python中按照确切的术语打印单词
- javascript - 条件渲染在我的功能组件中不起作用
- node.js - 所以我试图使用 discord.js V12 发出禁令命令,无论如何我总是遇到同样的错误
- r - R - 子集 - 基于列值的 grepl 选择排除行
- python - 修改多维 Numpy 数组
- python - TypeError:字符串索引必须是整数 Json.py
- typescript - 如何在 TS 中为具有原型方法的类编写接口?