java - 在 java.util.Date 和 java.time.Instant 之间转换古代日期时出现差异

标签 java date java-8

我有使用 java.util.Date 创建一个古老日期(0002 年 11 月 30 日)的遗留代码。我正在尝试更新我能更新的代码,但这需要在 Date 和 LocalDate 等之间进行转换。我无法完全摆脱对 Date 或古老日期选择的使用。

我发现在使用这个古老的日期在 Date 和 Instant 之间来回转换时似乎出现了错误,并希望有人能解释发生了什么。

这是一个示例:

    Date date = new Date();
    Instant instant = date.toInstant();
    System.out.println("Current:");
    System.out.println("Date: "+date);
    System.out.println("Instant: "+instant);
    System.out.println("Date epoch:    "+date.getTime());
    System.out.println("Instant epoch: "+instant.getEpochSecond()*1000);

    System.out.println("\nAncient from Date:");
    Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("MST"));
    cal.set(2, Calendar.NOVEMBER, 30, 0, 0, 0);
    date = cal.getTime();
    instant = date.toInstant();
    System.out.println("Date: "+date);
    System.out.println("Instant: "+instant);
    System.out.println("Date epoch:    "+date.getTime());
    System.out.println("Instant epoch: "+instant.getEpochSecond()*1000);

    System.out.println("\nAncient from Instant:");
    instant = Instant.parse("0002-11-30T00:00:00Z");
    date = Date.from(instant);
    System.out.println("Date: "+date);
    System.out.println("Instant: "+instant);
    System.out.println("Date epoch:    "+date.getTime());
    System.out.println("Instant epoch: "+instant.getEpochSecond()*1000);

打印以下内容:

Current:
Date: Tue Sep 18 12:34:27 MST 2018
Instant: 2018-09-18T19:34:27.177Z
Date epoch:    1537299267177
Instant epoch: 1537299267000

Ancient from Date:
Date: Thu Nov 30 00:00:00 MST 2
Instant: 0002-11-28T07:00:00.247Z
Date epoch:    -62075437199753
Instant epoch: -62075437200000

Ancient from Instant:
Date: Fri Dec 01 17:00:00 MST 2
Instant: 0002-11-30T00:00:00Z
Date epoch:    -62075289600000
Instant epoch: -62075289600000

因此,如果我在 2 日 11 月 30 日创建一个 Instant,然后转换为日期,则日期为 2 日 12 月 1 日。如果我从 2 日 11 月 30 日的日期开始,则 Instant 为 2 日 11 月 28 日。我知道Date 和 Instant 都不存储时区信息,但为什么根据我是从 Date 还是 Instant 开始,纪元如此不同?无论如何我可以解决这个问题吗?我需要能够从 Date 或 Instant 开始,并以相同的纪元值结束。如果知道为什么默认的 toString() 在给定相同纪元的情况下会显示如此不同的日期,那就太好了。

最佳答案

差异在于 DateInstant 的实现如何就其实现相互交互,Date 使用 Gregorian/Julian 日历,Instant 使用 ISO 标准对于 Date,在 Julian 日历转换之前遵循修改后的 Gregorian 日历。

公历 implementation有特别说明:

Before the Gregorian cutover, GregorianCalendar implements the Julian calendar. The only difference between the Gregorian and the Julian calendar is the leap year rule. The Julian calendar specifies leap years every four years, whereas the Gregorian calendar omits century years which are not divisible by 400.

嗯,是的,从技术上讲。但是对于这个问题,我们并不遇到这种情况。

cal.set(1582, Calendar.OCTOBER, 4, 0, 0, 0);

如预期的那样,这会产生一个日期,即 1582 年 10 月 4 日。

cal.set(1582, Calendar.OCTOBER, 5, 0, 0, 0);

这会产生一个日期,即 1582 年 10 月 15

这是什么魔法, bat 侠?

好吧,这不是编码错误,它实际上是 GregorianCalendar 的实现。

However, this year saw the beginning of the Gregorian Calendar switch, when the Papal bull known as Inter gravissimas introduced the Gregorian calendar, adopted by Spain, Portugal, the Polish–Lithuanian Commonwealth and most of present-day Italy from the start. In these countries, the year continued as normal until Thursday, October 4. However, the next day became Friday, October 15 (like a common year starting on Friday),

来自 Wikipedia on 1582

当我们检查 1582 年 10 月 4 日时,会发生以下情况:

Date: 1582-Oct-04 00:00:00

Instant: 1582-10-14T00:00:00Z

这里有 10 天的间隔,并且瞬间存在于“技术上不存在的日期”的原因由 ISO instant dates 的定义解释。 .

The standard states that every date must be consecutive, so usage of the Julian calendar would be contrary to the standard (because at the switchover date, the dates would not be consecutive).

SO,虽然 1582 年 10 月 14 日在现实中从未存在过,但根据定义,它存在于 ISO 时间中,但根据儒略历,它发生在现实世界的 1582 年 10 月 4 日。

由于我假设第一段有额外的闰年漂移,其中儒略世纪 1500、1400、1300、1100、1000、900、700、600、500、300、200、100 有额外的闰日未计算在内因为在公历中,我们慢慢地从 +10 偏移回 -1。这可以通过以 +100 为增量调整年份来验证。

如果您要显示历史事件日期,最好使用DateJulianCalendar DateFormatter 来显示正确的历史日期,因为它确实发生在历史上。打印出历史时期的 ISO 时间可能显得荒谬或不准确,但以这种格式存储时间仍然有效。

关于java - 在 java.util.Date 和 java.time.Instant 之间转换古代日期时出现差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52393619/

相关文章:

java - Weblogic 11g,在托管服务器上部署了ear,无法访问

java - Java中的Object类是什么?

java - 在Linux服务器上哪里可以找到 "full path to java binary"?

java - 来自 php/ruby/python 的人玩框架的优势

java - Spring MVC 无效日期格式错误消息未显示

java - 将 SimpleDateFormatter 与时区一起使用时出现意外结果

java - 结合两个流 Java 8

java - 以最后一个元素排序

date - Grails Date变量将不会设置时间

java - Java排序时如何考虑末尾空格