没有时区的xsd:dateTime的语义及其转换为Date

时间:2014-03-19 21:11:39

标签: xml datetime jaxb xsd timezone

我对XML Schema的内置类型xsd:dateTime有疑问。

没有时区的xsd:dateTime的确切语义是什么?防爆。 1970-01-01T00:00:00

我已阅读了大量XML Schema规范文档,但无法了解应如何处理。

具体来说,我想了解如何正确地将xsd:dateTime转换为日期(如java.util.Date或JavaScript Date)对象。

旁注:我完全了解Java util类,如DatatypeConverterDatatypeFactory,我想找到定义如何进行转换的XML Schema规范。

Date类(在Java中以及JavaScript中)的问题是这些类确实有时区(默认为本地时区)。如果我在没有输入时区的情况下获得xsd:dateTime,那么我必须以某种方式决定,我应该假设哪个时区。否则,我无法将其转换为时间值(如Date)。

现在的问题是,我应该假设什么。我在这里看到以下选项:

  • 假设默认为UTC。
  • 假设处理器的本地时区。

我不太喜欢第二种选择。这完全是随机的!在我的机器上,如果我运行

System.out.println(DATATYPE_FACTORY
    .newXMLGregorianCalendar("1970-01-01T00:00:00")
    .toGregorianCalendar().getTime().getTime());

对于GMT + 1,GMT或GMT-1,我会得到-3600000,0,360000(甚至更多的变种取决于夏季时间。这是如此随意,我真的没有得到这个。这是否意味着我们的XML文档具有像

这样的元素
<date-time>1970-01-01T00:00:00</date-time>

我们实际上不知道,这究竟是什么时候出现的?

第一个选项(假设UTC)对我来说似乎更有效,但这显然不是(至少)Java工具正在做的事情。

所以可以请某人给我一个指针,指出某种定义无时区xsd:dateTime语义的规范?

谢谢。

更新

目前的调查结果如下:

  • 未指定的时区具有&#34;未指定的&#34;的语义。时区,也就是说,你不能盲目地假设处理器的UTC或本地时区或其他什么。这是一些当地时区,但哪一个 - 你真的不知道。
  • 这基本上意味着严格来说,您无法将xsd:dateTime转换为具有特定时区的Date对象 - 除非以某种方式做出关于缺席时区的假设。
  • 作为工具提供者,我无法真正做出明智的假设。我没有关于数据或其语义的背景知识。
  • 这使我得出结论,工具用户必须明确或隐含地提供这样的假设。

我的解决方案如下:

  • 在我的库中,我有一个所谓的context对象,它提供XML处理上下文(类似于JAXB JAXBContext)。我将使用getDefaultTimezoneOffset()setDefaultTimezoneOffset(int timezoneOffset)
  • 等方法扩展此对象
  • 默认情况下,此方法将返回一些默认值。我现在更喜欢0(UTC)。但也可以是本地时区(如Java工具)。
  • 欢迎图书馆用户提供不同的默认时区偏移,但并非严格要求(&#34;隐式&#34;假设在这里)
  • 在将xsd:dateTime解析为Date时,如果传入的值缺少时区,则会假定它是context.getDefaultTimezoneOffset()
  • 我还会在解析的Date对象中记下传入的时区(或缺少它)。例如,在像originalTimezoneOffset这样的属性中或类似的东西。这不会修改Date对象的值,但会提供一些额外的上下文信息(例如,应该再次打印值时)。
  • 当打印Date时,库会检查originalTimezoneOffset,如果提供它,请在渲染词法值时考虑它。

2 个答案:

答案 0 :(得分:4)

基本上,时区缺少信息,有很多方法可以解释缺席的信息;最后,它取决于你。可能的解释是:

  • 时区未知

  • 可以根据上下文建立时区,例如相关的地方

  • 时区为UTC

XPath / XQuery / XSLT规范系列假定了一个上下文定义的时区。此处的上下文可以是用户的区域设置,或运行软件的计算机的时区,或任何其他内容。

从某种意义上说,它与省略时间和仅给出约会没有什么不同。当你说你出生于1973年3月21日时,你究竟是什么意思?你在说什么时区?假设可能是因为没有人可能会关注这些信息。

答案 1 :(得分:2)

这就是我自己用过的东西。这一切都始于dateTime规范:

  

“本地”或未计时的时间被假定为时间   某些未指明地点的时区由适当的规定   法律权威;目前没有合法规定的时区   这是持续时间,其幅度大于14小时。该   每个数值属性(timeOnTimeline除外)的值是   限制在由...确定的区间内的最大值   下一个更高的财产。例如,日值永远不能是32,而且   02年和2002年(2002年2月)甚至不能29岁。

如果这令人困惑,请转到 3.2.7.2 dateTime上的订单关系

部分

摘录(符合此处的发布标准):

  

两个dateTimes P和Q之间的顺序由以下定义   算法[...] A.Normalize P和Q.也就是说,如果有时区   目前,但它不是Z,将其转换为Z [...]

这些是相关的:

  

C.否则,如果P包含时区而Q没有,则比较为   如下:   1.P&lt; Q如果P < (Q时区+14:00)   2.P&gt;问:如果P> (Q带时区-14:00)   3.P&lt;&gt;否则,即,(Q,时区+14:00)&lt; P&lt; (Q带时区-14:00)

     

d。否则,如果P不包含时区且Q值,则比较为   如下:   1. P < Q if(P with time zone -14:00)&lt; Q.   2.P> Q if(P with time zone +14:00)&gt; Q.   3.P&gt;否则,即,(P,时区+14:00)&lt; Q&lt; (P与时区-14:00)

“魔数”14,来自3.2.7:

  

[...]目前没有合法规定的时区   持续时间的大小超过14小时。

当然,您可以在不确定的情况下运行,即无法确定订单的位置:

  

2000-01-01T12:00:00&lt;&gt; 1999-12-31T23:00:00Z

     

2000-01-16T12:00:00&lt;&gt; 2000-01-16T12:00:00Z

     

2000-01-16T00:00:00&lt;&gt; 2000-01-16T12:00:00Z

很难说出你应该做出什么样的假设。您需要追逐并理解如何捕获该值,然后以XML格式传递给您,因为这两个假设都是错误的!如果传递这些数据,最终将其发送回与发送数据相同的系统中的系统,安全的做法是确保您始终拥有该数据的“字符串”副本。

我真的不认为你得到的东西是随机的。您只需要阅读有关这些规格的更多信息。我并不是说这很容易 - 它就是这样的;另外,这不是关于XML或XSD,而是一般的时区。