如何在Spring MVC和JAXB编组的日期时间结束时正确添加“Z”?

时间:2014-10-17 21:38:54

标签: java xml jaxb jodatime

我有一个DateTimeXmlAdapter,我用它来将Joda日期转换为字符串。它看起来如下:

public class DateTimeXmlAdapter extends XmlAdapter<String, DateTime> {
    private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ";
    private static final DateTimeFormatter formatter = DateTimeFormat.forPattern(PATTERN);

    @Override
    public DateTime unmarshal(String value) {
        return formatter.parseDateTime(value);
    }

    @Override
    public String marshal(DateTime value) {
        return formatter.print(value);
    }
}

这导致XML中的以下字符串:

2014-10-16T18:31:57-0400

但是,我发送的端点要求最后的'Z'而不是-0400。他们建议转换为UTC,以便不需要发送时区信息。我感觉合理。但是,除非我按字面意思说明,否则我似乎无法得到“Z”。如:

private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";

下面的讨论似乎表明不建议添加Z.

Validating Timestamp format yyyy-MM-dd'T'HH:mm:ssZ in java?

尝试将其更改为以下内容,但这会导致日期为“Z”。

public class DateTimeXmlAdapter extends XmlAdapter<String, DateTime> {
    private static final DateTimeFormatter formatter = ISODateTimeFormat.dateHourMinuteSecond().withZoneUTC();

    @Override
    public DateTime unmarshal(String value) {
        return formatter.parseDateTime(value);
    }

    @Override
    public String marshal(DateTime value) {
        return formatter.print(value);
    }
}

输出:

2014-10-17T18:50:43

我正在谈论的端点表示他们需要'Z',因为它表示与UTC的零偏移。使用Joda Time和JAXB时,在最后添加'Z'的正确方法是什么?

谢谢,

马特

2 个答案:

答案 0 :(得分:1)

Z与没有Z的对比是已知的时区与未知时区。看到这个问题:

Semantics of the xsd:dateTime without timezone and its conversion to Date

我建议将Joda DateTime转换为String,而不是转换为XMLGregorianCalendar,这对于时区等字段更为详细。然后,JAXB将处理XMLGregorianCalendar编组(或解组)。

请参阅:

  • javax.xml.datatype.DatatypeFactory.newInstance()
  • javax.xml.datatype.DatatypeFactory.newXMLGregorianCalendar(year, month, day, hour, minute, second, millisecond, timezone) - 将最后一个设置为0
  • Z

答案 1 :(得分:1)

使用方法ISODateTimeFormat.dateHourMinuteSecond()是不合适的,因为它不输出偏移量(在您的情况下,这是Z = UTC + 00:00)。相反,您可以使用方法dateTimeNoMillis(),当然您需要将DateTime - 对象更改为UTC-offset:

public class DateTimeXmlAdapter extends XmlAdapter<String, DateTime> {
    private static final DateTimeFormatter formatter = 
        ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();

    @Override
    public DateTime unmarshal(String value) {
        return formatter.parseDateTime(value);
    }

    @Override
    public String marshal(DateTime value) {
        return formatter.print(value);
    }
}

来自文档:

  

返回一个格式化程序,它结合了没有毫秒的完整日期和时间,   用'T'分开(yyyy-MM-dd'T'HH:mm:ssZZ)。时区偏移是   'Z'表示零,'±HH:mm'表示非零。