如何指定JAXB封送xsd:dateTime时使用的日期格式?


86

当JAXB将日期对象(XMLGregorianCalendar)编组到xsd:dateTime元素中时。您如何指定生成的XML的格式?

例如:默认数据格式使用毫秒,<StartDate>2012-08-21T13:21:58.000Z</StartDate> 我需要忽略毫秒。 <StartDate>2012-08-21T13:21:58Z</StartDate>

如何指定我要使用的输出格式/日期格式?我正在使用javax.xml.datatype.DatatypeFactory创建XMLGregorianCalendar对象。

XMLGregorianCalendar xmlCal = datatypeFactory.newXMLGregorianCalendar(cal);

Answers:


126

您可以使用XmlAdapter来定制如何将日期类型写入XML。

package com.example;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date> {

    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public String marshal(Date v) throws Exception {
        synchronized (dateFormat) {
            return dateFormat.format(v);
        }
    }

    @Override
    public Date unmarshal(String v) throws Exception {
        synchronized (dateFormat) {
            return dateFormat.parse(v);
        }
    }

}

然后,您可以使用@XmlJavaTypeAdapter批注指定XmlAdapter将应用于特定的字段/属性。

@XmlElement(name = "timestamp", required = true) 
@XmlJavaTypeAdapter(DateAdapter.class)
protected Date timestamp; 

使用xjb绑定文件:

<xjc:javaType name="java.util.Date" xmlType="xs:dateTime"
        adapter="com.example.DateAdapter"/>

将产生上述注释。
(通过最终加入xjc命名空间:xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"


2
感谢您的回答!是否可以通过xsd或绑定文件添加注释?我只找到您经常引用的有关bindings.xml的博客条目,但是我认为这涵盖了其他方面。
guerda

9
如@PeterRader所述,SimpleDateFormat不是线程安全的-如果两个线程同时进入编组或解组,则可能会得到非常不可预测的结果。在正常测试中很难重现这一点,但是在负载下可能会发生,并且将非常难以诊断。最好使用封送和封送创建新的SimpleDateFormat(但如有必要,请使用静态格式字符串)。
Colselaw 2015年

1
我做到了,它几乎奏效了。但是我遇到了Class has two properties of the same name "timeSeries"错误-这是通过将注释放在getter而不是成员级别上来解决的。(感谢@megathor从stackoverflow.com/questions/6768544/...
gordon613

1
@ gordon613-本文将提供一些有关在何处放置注释的其他信息: blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
bdoughan 2015年

3
由于关键块受“同步”保护,因此没有任何问题。如果进行多次调用,将会出现(性能)问题。
Mike Argyriou

17

我使用SimpleDateFormat创建XMLGregorianCalendar,例如在以下示例中:

public static XMLGregorianCalendar getXmlDate(Date date) throws DatatypeConfigurationException {
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd").format(date));
}

public static XMLGregorianCalendar getXmlDateTime(Date date) throws DatatypeConfigurationException {
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(date));
}

第一种方法创建XMLGregorianCalendar实例,该实例由XML编组器格式化为有效的xsd:date,第二种方法产生有效的xsd:dateTime。


2

对我来说很简单。格式化XMLGregorianCalendar以在Java中进行编组。

我只是以良好的格式创建数据。在toString将被称为产生良好的效果。

public static final XMLGregorianCalendar getDate(Date d) {
    try {
        return DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd").format(d));
    } catch (DatatypeConfigurationException e) {
        return null;
    }
}

1

https://www.baeldung.com/jaxb

public class DateAdapter extends XmlAdapter<String, Date> {

    private static final ThreadLocal<DateFormat> dateFormat 
      = new ThreadLocal<DateFormat>() {

        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    }

    @Override
    public Date unmarshal(String v) throws Exception {
        return dateFormat.get().parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        return dateFormat.get().format(v);
    }
}

0

用法:

import com.company.LocalDateAdapter.yyyyMMdd;
...

@XmlElement(name = "PROC-DATE")
@XmlJavaTypeAdapter(yyyyMMdd.class)
private LocalDate processingDate;

LocalDateAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {

    public static final class yyyyMMdd extends LocalDateAdapter {
        public yyyyMMdd() {
            super("yyyyMMdd");
        }
    }

    public static final class yyyy_MM_dd extends LocalDateAdapter {
        public yyyy_MM_dd() {
            super("yyyy-MM-dd");
        }
    }

    private final DateTimeFormatter formatter;

    public LocalDateAdapter(String pattern) {
        formatter = DateTimeFormat.forPattern(pattern);
    }

    @Override
    public String marshal(LocalDate date) throws Exception {
        return formatter.print(date);
    }

    @Override
    public LocalDate unmarshal(String date) throws Exception {
        return formatter.parseLocalDate(date);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.