【发布时间】:2017-01-04 10:32:04
【问题描述】:
首先,“发生在午夜”的定义是当任务运行时,new DateTime() 或类似的将在转换为人类可读格式时显示 00:00:00 或更晚的时间部分。重要的一点是它不能显示前一天的 23:59:59。
实现此目的的常用方法是计算从现在到所需时间点的毫秒数,然后使用ScheduledExecutorService 在正确的时间执行任务。但是,当插入闰秒时,这将导致任务提前一秒运行(或提前几毫秒,具体取决于闰秒的“涂抹”方式以及您安排任务的时间):
Runnable task = ...
long numberOfMillisUntilMidnight = ...
ScheduledExecutorService executor = ...
// task runs too early when leap seconds are inserted
executor.schedule(task, numberOfMillisUntilMidnight, TimeUnit.MILLISECONDS);
原因是executor.schedule() 基于System.nanoTime() 显然忽略了闰秒。我想我需要的是一些基于“此时运行”而不是“在这段时间后运行”的调度程序。
对于那些感兴趣的人来说,任务必须在午夜运行的原因与我系统中的所有事件必须根据它们发生的日期分类这一事实有关,并且尽可能地,这需要与另一个系统同步。当然,如果其他系统在每个事件上都标上今天的日期会更好,但我们不在那里。
【问题讨论】:
-
以一种方式或另一种方式运行第二次真的很重要吗?
-
关于它是否真的很重要,从业务角度来看,是的,但从技术角度来看,不是,因为我可以编写代码说“如果还不是午夜,只需重新安排任务即可执行它”。但这似乎不优雅。关于 Crowder 的建议,这是可行的,但它似乎又不优雅,如果我的应用程序有事件发生在 00:00:00 和 00:00:01 之间,那么这些事件将被错误地报告为发生在错误的日期,这将导致 24 小时内 2 个系统之间出现协调问题,必须手动查看。
-
任务可以在运行时检查小时是否为 0,否则休眠一秒钟。
-
但是基本要求是什么,它必须/应该/应该是午夜的真正原因是什么?请提供更多背景信息。
-
你为什么说
System.nanoTime()忽略闰秒?我认为恰恰相反,因为它只计算经过的秒数(因此也是经过的 SI 秒)。另一件事是你如何显示它。这里 Java-8 不支持闰秒,而是盲目地依赖操作系统时钟(通常忽略闰秒)。顺便说一句:表达式System.currentTimeMillis()比System.nanoTime()更容易受到时钟变化的影响。
标签: java time leap-second