这是有效的日期格式吗 - 2007-12-13+01:00?

Is this a valid date format - 2007-12-13+01:00?

我们的情况很奇怪。 我们期望来自 Web 服务的一些数据 然后我们在 java 代码中处理它。突然,它开始失败了。

我们发现,我们收到的日期格式如下:2007-12-13+01:00 并抛出异常:java.lang.NumberFormatException:无效date/time。我们使用 JAXB 来编组响应并期望日期为 java.util.Date。到目前为止,我没有找到任何处理日期的代码行,没有修剪、转换或任何东西。只是编组。

现在对于这个格式是对是错,是谁造成的,存在争议。有趣的是,最近 java 代码没有任何变化,唯一的区别在于构建的计算机。

这可能是由于 java 版本、ANT 配置不同造成的?您有什么建议会导致此类问题吗?如果您有任何问题,请询问。可以的话我会尽量回答的。

LOG

我不认为它是一种有效的 ISO-8601(或 RFC 3339)格式,这是通常用于 Web 服务的格式 - 它似乎只在指定时间时包含时区偏移量.

但是,如评论中所述,它 有效的 XML schema 表示:

The lexical space of date consists of finite-length sequences of characters of the form: '-'? yyyy '-' mm '-' dd zzzzzz? where the date and optional timezone are represented exactly the same way as they are for dateTime. The first moment of the interval is that represented by: '-' yyyy '-' mm '-' dd 'T00:00:00' zzzzzz? and the least upper bound of the interval is the timeline point represented (noncanonically) by: '-' yyyy '-' mm '-' dd 'T24:00:00' zzzzzz?.

如果您想表示特定时区的一整天,这有点有意义 - 虽然因为它只指定偏移量而不是时区 ID,它会在 23 或 25 小时的日子里用夏令时转换失败: (

我不能说我个人曾经见过它在野外使用,也没有在 date/time API 中建模。

官方ISO 8601论文说(不能link,因为它需要你购买):

The zone designator is empty if use is made of local time in accordance with 4.2.2.2 through 4.2.2.4, it is the UTC designator [Z] if use is made of UTC of day in accordance with 4.2.4 and it is the difference-component if use is made of local time and the difference from UTC in accordance with 4.2.5.2.

我以某种方式解释此声明,好像区域指示符仅在任何时间组件的上下文中才有意义。所以答案是:

您的输入字符串并不真正 ISO 8601 兼容,但是 XML-schema 兼容 您应该期待使用 JAXB 的 Web 服务。请参阅好兄弟答案中的引文, 和 Jon Skeet 的

所以是的,您必须考虑到与 XML 兼容的 Web 服务将提供此类数据的可能性(尽管非常可疑,但更有可能的是 Web 服务只是未能提供完整的数据)由于内部错误导致的日期时间)。

如何解释日期和偏移量的组合是另一个好问题。 XML-schema 将解释解释为一个时间间隔(一整天),但此时间间隔不可映射 1:1 到一个时间点(您的 java.util.Date 结果)。也许您应该简单地假设午夜并使用偏移量将结果映射到 java.util.Date。或者更好:您应该询问 Web 服务背后的负责人,他们为什么提供此类数据以及如何解释这些数据。

顺便说一句,我记得java.time (built into Java 8) originally planned to introduce the type OffsetDate in analogy to OffsetDateTime,但终于放弃了。

这是有效的日期格式吗 - 2007-12-13+01:00?

是的,格式的官方描述见下面的link:


你的错误

We found out, that we receive the date in such format: 2007-12-13+01:00 and it throws out an exception: java.lang.NumberFormatException: Invalid date/time

java.lang.NumberFormatException: Invalid date/time
    at org.apache.axis.encoding.ser.SimpleDeserializer.onEndElement(SimpleDeserializer.java:180)
    at org.apache.axis.encoding.DeserializerImpl.endElement(DeserializerImpl.java:502)
    at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
    at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:171)
    at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
    at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:236)
    at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
    at org.apache.axis.client.Call.invoke(Call.java:2467)
    at org.apache.axis.client.Call.invoke(Call.java:2366)
    at org.apache.axis.client.Call.invoke(Call.java:1812)

这似乎是 Axis 而不是 JAXB 中的错误。


在 JAXB 中处理此格式

下面是在 JAXB 中使用此格式的示例。

Java 型号

在此示例中,我们将使用 DateCalendarXMLGregorianCalendar 来处理日期:

import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.datatype.XMLGregorianCalendar;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

    private Date date;
    private Calendar cal;
    private XMLGregorianCalendar xgc;

}

演示代码

input.xml

下面是我们将解组的 XML 文档,请注意所有日期值与您问题中的相同。

<?xml version="1.0" encoding="UTF-8"?>
<foo>
    <date>2007-12-13+01:00</date>
    <cal>2007-12-13+01:00</cal>
    <xgc>2007-12-13+01:00</xgc>
</foo>

演示

下面是一些演示代码,我们将在其中解组 XML 文档以填充每个日期字段,然后将对象编组回 XML。

import javax.xml.bind.*;
import java.io.File;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("input.xml");
        Foo foo = (Foo) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }

}

输出

下面是 运行 演示代码的输出,我们看到所有值都已正确转换。请注意,DateCalendar 值默认为默认的日期时间表示形式。您可以使用 @XmlSchemaType 注释来控制它。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo>
    <date>2007-12-12T18:00:00-05:00</date>
    <cal>2007-12-13T00:00:00+01:00</cal>
    <xgc>2007-12-13+01:00</xgc>
</foo>