神奇的 00:09 时区与 DatatypeFactory

在 java 中,有一个javax.xml.datatype.DatatypeFactory可用于导入和导出 xml 日期,如下所示。


  String xmlDateIn = "1900-01-01T12:00:00";

  DatatypeFactory df = DatatypeFactory.newInstance();

  XMLGregorianCalendar xmlCalendar = df.newXMLGregorianCalendar(xmlDateIn);

  String xmlDateOut = xmlCalendar.toXMLFormat();

在这个简单的情况下xmlDateIn等于xmlDateOut,正如预期的那样。但如果我想要它,java.lang.Date事情就会变得有趣。


  GregorianCalendar gregorianCalendar = xmlCalendar.toGregorianCalendar();

  Date dts = gregorianCalendar.getTime();

  System.out.println(dts);  // prints Mon Jan 01 12:00:00 CET 1900

乍一看它仍然可以正常工作,但实际上内部某些东西似乎已损坏。使用我的 IDE,我可以看到Date对象内部发生了什么。(如果你想知道,我住在 CET 时区。)看看这个奇怪的时区。

http://img1.mukewang.com/6150359a0001b49406750074.jpg

当我尝试将其转换回 XML 时,实际上也打印了 9 分钟时区。所以,这不仅仅是内部的事情。


  DatatypeFactory df2 = DatatypeFactory.newInstance();

  GregorianCalendar gc2 = new GregorianCalendar();

  gc2.setTime(dts);

  XMLGregorianCalendar xc2 = df2.newXMLGregorianCalendar(gc2);

  System.out.println(xc2.toXMLFormat()); // prints 1900-01-01T12:00:00.000+00:09 

为了修复它,如果我手动设置时区,事情会变得非常糟糕。看看这个神奇的时刻:


  String xmlDateIn = "1900-01-01T12:00:00";

  DatatypeFactory df = DatatypeFactory.newInstance();

  XMLGregorianCalendar xmlCalendar = df.newXMLGregorianCalendar(xmlDateIn);

  xmlCalendar.setTimezone(0);  // <--- ONLY CHANGE

  GregorianCalendar gregorianCalendar = xmlCalendar.toGregorianCalendar();

  Date dts = gregorianCalendar.getTime();

http://img4.mukewang.com/615035a90001c57407400079.jpg

实际上我对我的特定程序有一个解决方法:现在对我有用的是我在导入 xml 时没有设置时区。在Date随后进行了错误的时区内部,即9分钟。然后,当我最终想将其导出Date回 xml 时,我确实将 xml gregorian 日历上的时区设置为 0,这神奇地修复了它并再次导出正确的 xml 格式。

但实际上,我想知道这种疯狂的行为是否有任何好的解释。


MMTTMM
浏览 192回答 2
2回答

慕码人2483693

我对日历历史和官方计时不太了解,所以我首先确保我使用的是您的时区来测试它:int offset = (int) TimeUnit.HOURS.toMillis(1);String[] ids = TimeZone.getAvailableIDs(offset);TimeZone cet = Arrays.stream(ids).map(TimeZone::getTimeZone)&nbsp; &nbsp; .filter(tz -> tz.getDisplayName(false, TimeZone.SHORT).equals("CET"))&nbsp; &nbsp; .findFirst().orElseThrow(&nbsp; &nbsp; &nbsp; &nbsp; () -> new RuntimeException("No CET timezone found"));TimeZone.setDefault(cet);然后我检查了那个时区的一些内部运作。特别是,我打印了它的历史时间转换:System.out.println("Transitions:");cet.toZoneId().getRules().getTransitions().forEach(&nbsp; &nbsp; t -> System.out.println("&nbsp; " + t));前两个这样的转换打印为:Transition[Overlap at 1891-03-15T00:01+00:12:12 to +00:09:21]Transition[Overlap at 1911-03-11T00:00+00:09:21 to Z]随后是祖鲁语 (Z) 和 UTC+01:00 之间的各种“手动”转换。因此,1900 年的午夜实际上比 1912 年相应日期的午夜晚了 9 分 21 秒。实际上,如果将年份更改为 1912,则不会看到 9 分钟的差异:String xmlDateIn = "1912-01-01T12:00:00";我一直无法找到 12:12 或 9:21 转换的历史原因。我认为这只是一个科学追赶的问题,因为天文测量变得更加准确。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java