转换java.util.Date和java.time.Instant之间的古代日期时存在差异
我有使用java.util.Date创建古代日期(0002年11月30日)的遗留代码。我正在尝试更新我能更新的代码,但这需要在Date和LocalDate之间进行转换,等等。我无法完全摆脱Date的使用或古老的日期选择 我发现这个古老的日期在日期和瞬间之间来回转换时出现了一个错误,希望有人能解释发生了什么 以下是一个示例:转换java.util.Date和java.time.Instant之间的古代日期时存在差异,java,date,java-8,Java,Date,Java 8,我有使用java.util.Date创建古代日期(0002年11月30日)的遗留代码。我正在尝试更新我能更新的代码,但这需要在Date和LocalDate之间进行转换,等等。我无法完全摆脱Date的使用或古老的日期选择 我发现这个古老的日期在日期和瞬间之间来回转换时出现了一个错误,希望有人能解释发生了什么 以下是一个示例: Date date = new Date(); Instant instant = date.toInstant(); System.out.prin
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月2日30日创建一个瞬间,然后转换为一个日期,日期是12月2日。如果我以11月2日30日开始,那么这一刻就是11月2日28日。我知道日期和即时信息都不能存储时区信息,但为什么根据我是从日期开始还是从即时开始,时间会如此不同呢?有没有我可以解决的办法?我需要能够从一个日期或一个瞬间开始,并以相同的历元值结束。如果您想知道为什么默认的toString()在同一个纪元中显示了如此不同的日期,那就更好了。差异在于
日期
和即时
的实现如何相互作用,日期使用公历/儒略历,即时使用ISO日期标准,在儒略历转换之前遵循修改后的公历
gregorianalendar
有一个特别的注释:
在公历转换之前,公历实行儒略历。公历和儒略历的唯一区别是闰年规则。朱利安历法规定每四年闰年一次,而公历省略了不可被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日
这是什么魔法,蝙蝠侠
这不是一个编码错误,它实际上是GregorianCalendar的一个实现
然而,今年是公历转换的开始,被称为Inter Gravisismas的教皇公牛引入了公历,从一开始就被西班牙、葡萄牙、波兰-立陶宛联邦和当今意大利的大部分国家采用。在这些国家,这一年继续正常,直到10月4日星期四。然而,第二天变成了10月15日星期五(就像从星期五开始的普通年份),
从
当我们检查1582年10月4日时,会发生以下情况:
日期:1582-10-04 00:00:00
瞬间:1582-10-14T00:00:00Z
这里有10天的时间间隔,而瞬间存在于“技术上不存在的日期”的原因可以通过定义来解释
该标准规定,每个日期必须是连续的,因此使用儒略历与该标准相反(因为在转换日期,日期不会连续)
因此,虽然1582年10月14日在现实中从未存在过,但根据朱利安历法,它存在于ISO时间,但发生在现实世界的1582年10月4日
由于我假设第一段中有额外的闰年漂移,朱利安世纪1500、1400、1300、1100、1000、900、700、600、500、300、200、100有额外的闰日,在公历中没有计算在内,我们慢慢地从+10移回-1偏移。这可以通过以+100增量调整年份来验证
如果要显示历史事件日期,最好使用
日期
或JulianCalendar
日期格式化程序来显示正确的历史日期,因为它实际发生在历史中。打印出历史时段的ISO时间可能显得毫无意义或不准确,但以这种格式存储时间仍然有效。您遇到了舍入错误。不要使用instant.getEpochSecond()*1000
,使用instant.toEpochMilli()
。这两个框架在历史上的闰年细节上并不完全一致。因此,您需要明确您的需求。如果您有一个日期
在纪元之前的某个较大天数,您是否需要一个即时
在纪元之前的相同天数?或者,如果您的日期是11月2日30日,您是否需要在11月2日30日提供即时
?对不起,这不一样。@teppic,谢谢,我没有注意到那个方法。出于这个问题的目的,我认为毫秒值无关紧要,尽管我可以看出它是如何混淆了这个例子的。@OleV.V。我正在处理的代码是使用一个神奇的日期(让这成为你们的一个教训,孩子们),所以我想有一个即时和日期去11月2日的同一个日期,虽然我认为我可以使这些选项中的任何一个工作。诀窍是有时我从瞬间开始,有时我从约会开始。从你的评论中,我认为是闰年让我悲伤。。。