当前位置: 首页 > 面试题库 >

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

弓举
2023-03-14
问题内容

我有使用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

因此,如果我在11月2日创建一个Instant,然后转换为Date,则该日期为12 Dec1。如果我以Date在11 Nov 2开头,则Instant为11
Nov
2。即时存储时区信息,但是根据我是从日期还是即时开始,历元为何如此不同?无论如何,我可以解决这个问题吗?我需要能够以Date或Instant开头,并以相同的纪元值结束。知道为什么默认的toString()在给定相同的纪元时会显示出如此不同的日期也将是一件很高兴的事情。


问题答案:

差异在于实现之间的实现方式Date以及Instant与实现之间的交互方式,其中使用格里高利/朱利安日历的日期和使用日期的ISO标准的即时,在儒略历转换之前遵循经过修改的格里高利日历。

GregorianCalendar
实现有一个特别说明:

在公历转换之前,GregorianCalendar会执行儒略历。阳历和儒略历之间的唯一区别是the年规则。朱利安历法指定每四年leap年,而公历忽略了不可被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 gravissimas的罗马教皇引入了公历,从一开始就被西班牙,葡萄牙,波兰-
立陶宛联邦和当今大多数意大利采用。在这些国家/地区,正常年份一直持续到
10月4日(星期四)。但是,第二天成为10月15日(星期五)(就像从星期五开始的普通年份)

摘自1582年的维基百科

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

日期:1582-十月-04 00:00:00

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

这里有10天的间隔,ISO即时日期的定义说明了即时存在于“技术上不存在的日期”的原因。

该标准规定 每个日期必须是连续的 ,因此儒略历的使用将与该标准相反(因为在转换日期,日期将不是连续的)。

因此,尽管1582年10月14日实际上并不存在,但按照定义,它存在于ISO时间中,但根据朱利安·日历,它出现在1582年10月4日的真实世界中。

由于我假设是从第一段开始的额外leap年漂移,其中朱利安世纪1500、1400、1300、1100、1000、900、700、600、500、300、200、100有额外的leap日,因此公历,我们慢慢地从+10偏移到-1。可以通过以+100为增量调整年份来验证这一点。

如果要 显示
历史事件日期,最好使用DateJulianCalendarDateFormatter来显示正确的正确历史日期,因为它实际出现在历史记录中。打印出历史时期的ISO时间可能看起来没有意义或不准确,但是以这种格式存储时间仍然有效。



 类似资料:
  • 我有使用java.util.date创建古老日期(30 nov0002)的遗留代码。我试图更新我能更新的代码,但这需要在Date和LocalDate之间转换,等等。我不能完全摆脱Date的使用或古老的日期选择。 我发现在这个古老的日期之间来回转换Date和Instant时出现了一个错误,希望有人能解释一下是怎么回事。 它打印以下内容: 所以如果我在11月30日创建一个瞬间,然后转换成一个日期,这个

  • 问题内容: Java 8具有用于日期和时间的全新API。此API中最有用的类之一是,用于保存与时区无关的date-with-time值。 为此目的,可能有数百万行代码使用遗留类。这样,在连接旧代码和新代码时,将需要在两者之间进行转换。由于似乎没有直接的方法可以完成此任务,该怎么办呢? 问题答案: 简短答案: 说明:(基于这个问题有关LocalDate) 尽管有名称,它代表时间轴上的一个瞬间,而不是

  • 问题内容: 我正在寻找在两个方向上在java.util.Date和javax.xml.datatype.XMLGregorianCalendar之间进行转换的简单方法。 这是我现在正在使用的代码 : 有没有更简单的事情,例如我忽略的一些API调用? 在标准XML日期/时间和Java日期对象之间进行转换似乎是一项非常常规的任务,令我感到惊讶的是,我完全必须编写这段代码。 有什么建议? 注意: 我的J

  • 问题内容: 我已经尝试过一百万种不同的方法,但是没有用。任何帮助将非常感激。 上面的方法不起作用。 基本上,我想做的是获取纪元时间并将其转换为澳大利亚时间。我的当地时间是+05.30,但是我当然不希望这成为促成这种转化的因素。 编辑- 当我运行您的确切代码时,输​​出 时代1318388699000 2011年10月12日星期三08:34:59 GMT + 05:30 12/10/2011 03:

  • 问题内容: Excel的日期时间值看起来像42291.60493,这意味着MySQL将其视为字符串而不是日期。是否存在可以将其转换为MySQL日期时间的MySQL代码?(即像在MS SQL中一样 ) 问题答案: 我可以想到2个解决方案: 使用excel中的text()函数将excel中的日期转换为符合mysql的日期和时间格式的格式化日期字符串。 在mysql中使用计算将数字转换为日期: (下面的

  • 我不想使用 库,因为我正在处理的项目需要文书工作来引入依赖项。如果我能在没有第三方库的情况下实现这一目标,我会更高兴。 我很难在CET和UTC之间转换日期,因为日期是夏时制。这与我预期的相差一个小时: CET比UTC提前一小时,夏季提前2小时。因此,我预计中欧在盛夏的10点30分将达到协调世界时的8点30分。 功能是: 我使用两个时区信息对象: