java - 2015 年 6 月 30 日闰秒期间在 Amazon Linux AMI 上运行的日历操作

标签 java amazon-web-services calendar leap-second

环境:Amazon Linux AMI 上的 Java 7(已修补)。请注意,在此环境中使用了 NTP。

我们的部分代码定期执行计划任务。一般来说,执行的确切时间并不是特别重要。但是,我们有类似的逻辑用于计算报告间隔。报告周期预计会在精确的时间范围内。

示例代码:

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 时间戳(长)值。 Calendar 实例均位于 UTC 时区。

据我们了解,Java 7 的日历实现不考虑闰秒。我们还相信 NTP 会更新操作系统时钟。

我们知道亚马逊 2012 年的闰秒惨败。我们正在与他们直接沟通,了解他们的运营准备情况。

具体问题:

  1. 如果我们增量位于闰秒之前的小时边界上的日历,那么它会位于闰秒之后的小时边界上吗?或者整点前一秒?

  2. 我们应该如何测试/验证这段代码如何跨闰秒边界运行?被黑的 NIST Leapfile 是个好方法吗?

  3. 是否有更合适的模式/实现可以避免闰秒问题?

最佳答案

我不会太担心 2015 年的下一个闰秒,并假设 Linux 团队在此期间已经做了很多工作来解决闰秒处理代码的任何问题,请参阅还有这个有趣的采访 Linus Torvalds 。如果linux软件再次出错,那么你只能重新启动你的Java程序(这里Java只是后端),你无能为力

现在让我们考虑一下可能会发生什么。关于完全不知道任何闰秒的代码,例如 java.util.Date 的内容和java.util.Calendar ,请记住,此类代码只能看到操作系统时钟提供的内容。大多数操作系统仅提供 UNIX 时间戳。如果它们与 NTP 同步,请记住 NTP 时间戳不计算 NTP 协议(protocol)中指定的闰秒。他们只是重复相同的时间戳。 Windows 可能会在以后的任何时间触发时钟跳跃,而 Linux 内核会尝试更精确,应用一些闰秒处理代码并立即操纵系统时钟。不管怎样,两个操作系统都只提供类似 POSIX 的时间戳。而 Java 却什么也看不到。

这也回答了您的第一个具体问题:A GregorianCalendar -添加一小时后,对象将保留在小时边界上。

关于第二个问题:

这里讨论的只是一秒钟。但可能更麻烦的是,本地时钟甚至可能会出现几分钟的错误(然后在与 NTP 时钟同步后突然发生跳跃)。后一种行为可能随时发生,而不仅仅是在 2015-06-30 年底。所以我认为你真正的问题是时钟的单调性。这通常表明任何测试都应该使用可注入(inject)时钟机制之类的东西。例如,您可以写 TimeSource -通过方法产生任何unix时间戳的接口(interface)public long currentTime() (甚至可以通过计时器创建模拟跳转),然后在 JUnit 测试类中使用此接口(interface)来提供(假)时间并观察代码的行为。

ad 3.) 大多数人只会使用一个不知道任何闰秒的库,因为 POSIX 很容易理解和计算(尽管当涉及到这些特殊秒时它是不正确的)。如果没有闰秒处理代码,那么标准库中几乎不可能出现直接根源的问题。否则,如果您不愿意向用户隐藏闰秒,那么您也可以在这个SO-post中查阅我的答案。 .

无论您的决定是什么,闰秒对于选择合适的库/实现来说确实不够重要(其他主题如线程安全、国际化等更为重要)。关于这些标准,旧的Calendar -东西很糟糕。

关于java - 2015 年 6 月 30 日闰秒期间在 Amazon Linux AMI 上运行的日历操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27911432/

相关文章:

java - 创建项目时发生错误 - Eclipse

amazon-web-services - AWS Cloudformation 创建没有容器定义的任务定义

java - 无法在 Spring Boot 应用程序中使用 AWS SDK(套接字不是由该工厂创建的)

Java日历: getting time for the timezone

iOS - 以编程方式拒绝联系人权限(在用户接受后)

java - 允许我的 Android View 嵌入到其他应用程序中

java - 如何在java中将proj_id的值设置为max(proj_id) + 1

java - preferences.xml 和扩展 DialogPreference

amazon-web-services - AWS Network负载平衡器-什么是客户端重置计数(以及为何如此之高)

java - 生成具有给定月份和年份的日历