我们有一个非常奇怪的情况。 我们期待来自Web服务的一些数据,然后我们在java代码中处理它。突然,它开始失败了。
我们发现,我们收到的日期格式为: 2007-12-13 + 01:00 ,它会抛出异常: java.lang.NumberFormatException:日期无效/时间。我们使用JAXB对响应进行Marshall并期望日期为 java.util.Date 。到目前为止,我没有找到任何处理日期,没有修剪,转换或任何东西的代码行。只是编组。
现在对这种格式是正确还是不正确以及是谁造成了这个问题存在争议。有趣的是,最近java代码没有做任何更改,唯一的区别在于构建它的计算机。
这可能是由不同的java版本,ANT配置引起的?你有什么建议可以导致这样的问题吗?如果您有任何问题,请询问。如果可能,我会尽力回答。
答案 0 :(得分:3)
我不相信它是有效的ISO-8601(或RFC 3339)格式,这是通常用于网络服务的格式 - 在指定时间时似乎只包括时区偏移。< / p>
但是,正如评论中所述, 是有效的XML schema代表:
日期的词汇空间由以下形式的有限长度字符序列组成:
'-'? yyyy '-' mm '-' dd zzzzzz?
其中日期和可选时区的表示方式与日期时间即可。区间的第一个时刻是:'-' yyyy '-' mm '-' dd 'T00:00:00' zzzzzz?
,区间的最小上限是由'-' yyyy '-' mm '-' dd 'T24:00:00' zzzzzz?
表示的(非语义)时间线点。
如果你想在特定时区代表一整天,这是有道理的 - 虽然它只指定了偏移量而不是区域ID,但它在夏令时过渡时失败了23或25小时:( < / p>
我不能说我个人见过它在野外使用过,也没有在日期/时间API中建模。
答案 1 :(得分:3)
是的,请参阅以下链接,了解格式的官方说明:
我们发现,我们以这种格式收到日期: 2007-12-13 + 01:00它抛出一个异常: java.lang.NumberFormatException:无效的日期/时间
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中使用此格式的示例。
在此示例中,我们将使用Date
,Calendar
和XMLGregorianCalendar
来处理日期:
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);
}
}
<强>输出强>
以下是运行演示代码的输出,我们看到所有值都已正确转换。请注意,Date
和Calendar
值默认为默认的dateTime表示形式。您可以使用@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>
答案 2 :(得分:1)
官方ISO 8601论文称(无法链接到它,因为它需要您购买):
如果使用当地时间,则区域指示符为空 按照4.2.2.2到4.2.2.4,它是UTC指示符[Z] 如果按照4.2.4使用UTC的日期,那就是 差异成分,如果使用当地时间和差异 来自UTC,符合4.2.5.2。
我以某种方式解释这个语句,好像区域指示符只在任何时间组件的上下文中是明智的。所以答案是:
➥您的输入字符串不符合ISO 8601,但XML-schema compliant 正如您对使用JAXB的网络服务所期望的那样。请参阅好兄弟Answers的引文,Blaise Doughan的the answer和Jon Skeet的the answer。
所以,是的,您必须考虑到兼容XML的Web服务提供此类数据的可能性(尽管非常值得怀疑,但由于以下原因,Web服务很可能无法提供完整的日期时间。内部错误)。
如何解释日期和偏移的组合是另一个好问题。 XML模式将解释称为间隔(一整天),但此间隔不能以1:1的形式映射到某个时间点(您的java.util.Date
结果)。可能你应该假设午夜并使用偏移量将结果映射到java.util.Date
。或者更好:您应该询问Web服务背后的负责人,为什么他们提供这些数据以及如何解释它。
顺便说一下,我记得java.time(内置于Java 8)最初计划将类型OffsetDate
与OffsetDateTime
类比,但最终放弃了它。< / p>