在java.util.Date和java.time.Instant之间转换古代日期时的差异 [英] Discrepancy when converting ancient dates between java.util.Date and java.time.Instant

查看:2293
本文介绍了在java.util.Date和java.time.Instant之间转换古代日期时的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have legacy code that uses java.util.Date creating an ancient date (30 Nov 0002). I'm trying to update what code I can, but that's necessitating converting between Date and LocalDate, etc. I can't completely get rid of the use of Date or the ancient date choice.

我发现在日期和瞬间之间在这个古老的日期之间来回转换时出现了什么错误,并且希望有人可以解释发生了什么。

I'm finding what appears to be an error when converting back and forth between Date and Instant with this ancient date, and was hoping someone could explain what is going on.

以下是一个示例:

    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

因此,如果我在11月30日创建一个Instant,然后转换为Date,则日期是12月1日。如果我在11月30日开始日期,则Instant是11月28日2.我知道日期和即时存储时区信息都没有,但为什么这个时代根据我是从一个日期还是一个瞬间开始而如此不同?无论如何我可以解决这个问题吗?我需要能够以Date或Instant开头,并以相同的纪元值结束。也很高兴知道为什么默认的toString()在给定相同的纪元时显示这样的不同日期。

So if I create an Instant at 30 Nov 2, then convert to a Date, the Date is 1 Dec 2. If I start with a Date at 30 Nov 2, the Instant is 28 Nov 2. I'm aware that neither Date nor Instant store timezone information, but why are the epochs so different based on whether I started with a Date vs. an Instant? Is there anyway I can work around that? I need to be able to start with either a Date or an Instant, and end up with the same epoch value. It would also be nice to know why the default toString() shows such different dates given the same epoch.

推荐答案

差异存在在 Date Instant 的实现如何相互作用与其实现相互作用,使用Date使用Gregorian / Julian日历和Instant使用ISO标准的日期,遵循Julian日历切换之前修改过的公历。

The discrepancy resides in how the implementations of Date and Instant interact with each other in relation to their implementations, with Date using Gregorian/Julian calendars and Instant using ISO standard for Date, which follow a modified Gregorian calendar prior to the Julian calendar switchover.

GregorianCalendar 实施有一个特别说明:

The GregorianCalendar implementation has a special note:


在Gregorian切换之前,GregorianCalendar实现了Julian日历。格里高利历和儒略历之间的唯一区别是闰年规则。朱利安历法规定了每四年一次的闰年,而格里高利历则省略了不能被400整除的世纪年。

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.

嗯,是的从技术上讲。但是对于这个问题,我们不会完全遇到这个。

Well, yes, technically speaking. But for this issue, we don't quite encounter this.

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

这将产生1582年10月4日的预期日期。

This yields a date, as expected, of October 4, 1582.

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

这会产生10月 15 ,1582的日期。

This yields a date, of October 15, 1582.

这是什么魔法,蝙蝠侠?

WHAT MAGIC IS THIS, BATMAN?

嗯,这不是编码错误,它实际上是GregorianCalendar的一个实现。

Well, this isn't a coding error, it's actually an implementation of GregorianCalendar.


然而,今年看到了公历日历的开始,当时被称为Inter gravissimas的教皇公牛引入了公历,采用了由西班牙,葡萄牙,波兰立陶宛联邦和大多数现今的意大利从一开始。在这些国家,这一年继续正常,直到 10月4日星期四。然而,第二天成为10月15日星期五(就像从星期五开始的常年),

来自维基百科1582

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

When we examine October 4, 1582, the following happens:


日期: 1582-Oct-04 00:00:00

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

即时:1582-10-14T00:00:00Z

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

此处存在10天的差距,并且技术上不存在的日期中的瞬间存在的原因由 ISO即时日期

There is a 10-day gap here, and the reason the instant exists on a "technically non-existent date" is accounted for by the definition of ISO instant dates.


标准声明每个日期必须连续,因此使用Julian日历会违反标准(因为在转换日期,日期不会连续)。

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时间,但发生在现实世界的10月根据朱利安历法,4,1582年。

SO, whereas October 14, 1582 never existed in reality, it exists in ISO time by definition, but occurs on the real world's October 4, 1582 according to Julian Calendar.

由于我假设是第一段的额外闰年漂移,其中朱利安世纪1500,1400,1300,1100,1000 ,900,700,600,500,300,200,100在格里高利历中没有计算额外的闰日,我们慢慢地从+10偏移到-1偏移。这可以通过以+100为增量调整年份来验证。

Due to what I assume are additional leap year drifts from the first paragraph, where Julian centuries 1500, 1400, 1300, 1100, 1000, 900, 700, 600, 500, 300, 200, 100 have extra leap days not accounted for in the Gregorian calendar, we slowly shift back from a +10 to a -1 offset. This can be verified by adjusting the year in +100 increments.

如果您显示历史事件日期,您最好使用日期 JulianCalendar DateFormatter显示正确的历史日期,因为它实际上发生在历史记录中。打印历史时段的ISO时间可能看似荒谬或不准确,但以此格式存储时间仍然有效。

If you are displaying historical event dates, you will be better off using a Date or JulianCalendar DateFormatter to display the correct correct historical date, as it actually occurred in history. Printing out the ISO time for historical periods may appear nonsensical or inaccurate, but storing the time in this format is still valid.

这篇关于在java.util.Date和java.time.Instant之间转换古代日期时的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆