在 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 时区。)看看这个奇怪的时区。
当我尝试将其转换回 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();
实际上我有一个针对我的特定程序的解决方法:现在对我有用的是我在导入 xml 时没有设置时区。 Date
然后在内部携带错误的时区,即 9 分钟。然后,当我最终想将 Date
导出回 xml 时,我将 xml 公历上的时区设置为 0,这神奇地修复了它并再次导出正确的 xml 格式。
但实际上,我想知道对于这种疯狂行为是否有任何好的解释。
最佳答案
我对日历历史和官方计时知之甚少,所以我通过首先确保我使用的是您的时区来测试它:
int offset = (int) TimeUnit.HOURS.toMillis(1);
String[] ids = TimeZone.getAvailableIDs(offset);
TimeZone cet = Arrays.stream(ids).map(TimeZone::getTimeZone)
.filter(tz -> tz.getDisplayName(false, TimeZone.SHORT).equals("CET"))
.findFirst().orElseThrow(
() -> new RuntimeException("No CET timezone found"));
TimeZone.setDefault(cet);
然后我检查了那个时区的一些内部运作。特别是,我打印出了它的历史时间转换:
System.out.println("Transitions:");
cet.toZoneId().getRules().getTransitions().forEach(
t -> System.out.println(" " + 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 过渡的历史原因。我认为这只是科学 catch 来的问题,因为天文测量变得更加准确。
关于java - 魔法 00 :09 timezone with DatatypeFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52370153/