Java 2015年6月30日闰秒期间在Amazon linux AMI上运行的日历操作
环境:AmazonLinuxAMI上的Java7(已修补)。请注意,此环境中使用NTP 我们代码的一部分定期执行预定任务。一般来说,执行的确切时间并不特别重要。但是,我们有类似的逻辑,用于计算报告间隔。报告期预计将精确到小时界限 示例代码:Java 2015年6月30日闰秒期间在Amazon linux AMI上运行的日历操作,java,amazon-web-services,calendar,leap-second,Java,Amazon Web Services,Calendar,Leap Second,环境:AmazonLinuxAMI上的Java7(已修补)。请注意,此环境中使用NTP 我们代码的一部分定期执行预定任务。一般来说,执行的确切时间并不特别重要。但是,我们有类似的逻辑,用于计算报告间隔。报告期预计将精确到小时界限 示例代码: protected Calendar increment(ScheduledPeriodEnum scheduledPeriod, Calendar date) { Calendar next = CalendarUtils.getCalendar(
protected Calendar increment(ScheduledPeriodEnum scheduledPeriod, Calendar date) {
Calendar next = CalendarUtils.getCalendar();
next.setTimeInMillis(date.getTimeInMillis());
switch (scheduledPeriod) {
case ONE_DAY:
next.add(Calendar.DAY_OF_MONTH, 1);
break;
case ONE_HOUR:
next.add(Calendar.HOUR_OF_DAY, 1);
break;
case FIFTEEN_MINUTE:
next.add(Calendar.MINUTE, 15);
break;
case ONE_MONTH:
next.add(Calendar.MONTH, 1);
break;
default:
throw new RuntimeException("Unhandled case: " + scheduledPeriod);
}
return next;
}
我们将时间持久化为unix时间戳(long)值。日历
实例都位于UTC时区
我们的理解是,Java7的日历实现没有考虑闰秒。我们还相信NTP将更新操作系统时钟
我们知道亚马逊2012年的闰秒崩溃。我们正在与他们直接沟通,以了解他们的作战准备情况
具体问题:
increment
一个在闰秒前一小时边界上的日历,它会在闰秒后一小时边界上吗?还是在一小时前一秒钟我不会太担心2015年的下一个闰秒,并且假设Linux团队在此期间已经做了很多工作来解决闰秒处理代码的任何问题,另请参见本次有趣的采访。如果linux软件再次出错,那么除了重新启动Java程序(这里Java只是后端)之外,您不能做更多的事情 现在让我们考虑一下可能会发生什么。关于完全不知道任何闰秒的代码,如
java.util.Date
和java.util.Calendar
,请记住,这些代码只看到操作系统时钟提供的内容。大多数操作系统只提供UNIX时间戳。如果它们与NTP同步,那么还要记住,NTP时间戳不计算NTP协议中指定的闰秒。他们只是重复相同的时间戳。Windows可能会在以后的任何时候触发时钟跳转,而Linux内核则会尝试更精确地应用一些闰秒处理代码并立即操纵系统时钟。无论如何,这两个操作系统都只提供类似POSIX的时间戳。Java只是看到。。。没什么
这也回答了您的第一个具体问题:Agregoriacalendar
-对象在添加一小时后将保留在小时边界上。
关于第二个问题:
这里讨论的只是一秒钟。但可能更麻烦的是,本地时钟甚至可能在几分钟内出错(然后在与NTP时钟同步后突然跳转)。后一种行为随时都可能发生,而不仅仅是在2015-06-30年底。所以我认为你真正的问题是时钟的单调性。这通常表明,任何测试都应该使用类似可注入时钟机制的东西。例如,您可以编写一个TimeSource
-接口,该接口通过方法public long currentTime()
生成任何unix时间戳(甚至可以通过计时器创建模拟跳转),然后在JUnit测试类中使用该接口提供(假)时间并观察代码的行为
大多数人只会使用一个不知道任何闰秒的库,因为POSIX很容易理解和计算(尽管对于这些特殊的秒是不正确的)。如果没有leap second处理代码,那么这些标准库中就很难直接产生问题。否则,如果您不想对用户隐藏闰秒,那么您也可以在本文中参考我的答案
无论您的决定是什么,闰秒对于选择合适的库/实现来说确实不够重要(线程安全、国际化等其他主题更为重要)。关于这些标准,旧的日历
-内容非常糟糕。