Simple conversion between java.util.Date and XMLGregorianCalendar
我正在寻找一种在java.util.date和javax.xml.datatype.xmlGregorianCalendar之间进行双向转换的简单方法。
下面是我现在使用的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import java.util.GregorianCalendar; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; /** * Utility class for converting between XMLGregorianCalendar and java.util.Date */ public class XMLGregorianCalendarConverter { /** * Needed to create XMLGregorianCalendar instances */ private static DatatypeFactory df = null; static { try { df = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException dce) { throw new IllegalStateException( "Exception while obtaining DatatypeFactory instance", dce); } } /** * Converts a java.util.Date into an instance of XMLGregorianCalendar * * @param date Instance of java.util.Date or a null reference * @return XMLGregorianCalendar instance whose value is based upon the * value in the date parameter. If the date parameter is null then * this method will simply return null. */ public static XMLGregorianCalendar asXMLGregorianCalendar(java.util.Date date) { if (date == null) { return null; } else { GregorianCalendar gc = new GregorianCalendar(); gc.setTimeInMillis(date.getTime()); return df.newXMLGregorianCalendar(gc); } } /** * Converts an XMLGregorianCalendar to an instance of java.util.Date * * @param xgc Instance of XMLGregorianCalendar or a null reference * @return java.util.Date instance whose value is based upon the * value in the xgc parameter. If the xgc parameter is null then * this method will simply return null. */ public static java.util.Date asDate(XMLGregorianCalendar xgc) { if (xgc == null) { return null; } else { return xgc.toGregorianCalendar().getTime(); } } } |
有没有更简单的,比如我忽略的一些API调用?
在标准XML日期/时间和Java日期对象之间转换似乎是一个非常常规的任务,我很惊讶我不得不编写这个代码。
有什么建议吗?
笔记:我的JAXB类是从模式自动生成的。我的项目上的构建过程不允许我手动更改生成的类。xjc将xs:datetime元素作为xmlGregorianCalendar在jaxb类中生成。该模式是定期扩展和调整的,因此允许我对模式xsd文件进行有限的更改。
解决方案更新:Blaise提出的解决方案允许我将xmlGregorianCalendar从组合中去掉,转而处理java.util.calendar对象。通过在我的模式文件顶部添加一个JAXB绑定子句,XJC能够在我的JAXB类中为xs:datetime生成更合适的映射。下面是一些显示我的XSD文件中的修改的片段。
xsd文件中的根元素:
1 | <xs:schema xmlns:mydata="http://my.example.com/mydata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://my.example.com/mydata" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="0.2" xml:lang="en" jaxb:version="2.0"> |
号
JAXB绑定注释块,在xsd中根元素后立即插入:
1 2 3 4 5 6 7 | <xs:annotation> <xs:appinfo> <jaxb:globalBindings> <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" /> </jaxb:globalBindings> </xs:appinfo> </xs:annotation> |
因为xml xs:datetime字段也存储时区,所以我最好使用日历,而不是日期,因为日历对象有一个很好的API来处理区域设置和时区。无论如何,我更乐意处理日历对象而不是xmlGregorianCalendar。不再需要我上面列出的转换方法。我没有一路到java.util.date,但离得足够近了!
从xmlGregorianCalendar到java.util.date,您只需执行以下操作:
1 |
为什么不使用外部绑定文件来告诉XJC生成java.util.date字段而不是xmlGregorianCalendar?
另请参见如何将xs:date映射到java.util.date?博客
从java.util.date到xmlGregorianCalendar,您只需执行以下操作:
1 2 3 4 5 6 7 | import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.DatatypeFactory; import java.util.GregorianCalendar; ...... GregorianCalendar gcalendar = new GregorianCalendar(); gcalendar.setTime(yourDate); XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcalendar); |
。
在@f-puras的第一条评论之后编辑的代码,因为我犯了一个错误。
我必须做出一些改变才能使它发挥作用,因为与此同时,一些事情似乎发生了变化:
- XJC会抱怨我的适配器没有扩展XMLadapter
- 一些奇怪和不必要的导入被引入(org.w3.2001.xmlschema)
- 显然,在扩展XML适配器时,解析方法不能是静态的。
下面是一个工作示例,希望这有帮助(我使用的是jodatime,但在本例中simpledate就足够了):
ZZU1〔0〕
。
在XSD中,我遵循了上面给出的优秀引用,因此我包含了这个XML注释:
1 2 3 4 5 6 7 8 9 10 | <xsd:appinfo> <jaxb:schemaBindings> <jaxb:package name="at.mycomp.xml" /> </jaxb:schemaBindings> <jaxb:globalBindings> <jaxb:javaType name="java.util.Date" xmlType="xsd:date" parseMethod="at.mycomp.xml.DateAdapter.unmarshal" printMethod="at.mycomp.xml.DateAdapter.marshal" /> </jaxb:globalBindings> </xsd:appinfo> |
号
可以使用此自定义项将默认映射更改为java.util.date。
1 2 3 4 5 6 7 8 | <xsd:annotation> <xsd:appinfo> <jaxb:globalBindings> <jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime" parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime" printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime"/> </jaxb:globalBindings> </xsd:appinfo> |
。
我也有这种头痛。通过简单地在我的POJO中将时间字段表示为原始的long来消除它。现在,我的WS-Client代码的生成正确地处理了所有的事情,并且没有更多的XML到Java CRAP。当然,在Java方面处理MILIS是简单而无痛的。吻原则摇滚!
编组时自定义日历和日期
步骤1:为自定义属性准备JAXB绑定XML,在本例中,我为日期和日历做了准备
1 2 3 4 5 6 7 8 9 10 11 | <jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <jaxb:globalBindings generateElementProperty="false"> <jaxb:serializable uid="1" /> <jaxb:javaType name="java.util.Date" xmlType="xs:date" parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate" printMethod="com.stech.jaxb.util.CalendarTypeConverter.printDate" /> <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="com.stech.jaxb.util.CalendarTypeConverter.printCalendar" /> |
setp 2:在xsd选项下向apache或任何相关插件添加自定义JAXB绑定文件,如下所述
1 2 3 4 5 | <xsdOption> <xsd>${project.basedir}/src/main/resources/tutorial/xsd/yourxsdfile.xsd</xsd> <packagename>com.tutorial.xml.packagename</packagename> <bindingFile>${project.basedir}/src/main/resources/xsd/jaxbbindings.xml</bindingFile> </xsdOption> |
。
SETP 3:编写CalendarConverter类的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.stech.jaxb.util; import java.text.SimpleDateFormat; /** * To convert the calendar to JaxB customer format. * */ public final class CalendarTypeConverter { /** * Calendar to custom format print to XML. * * @param val * @return */ public static String printCalendar(java.util.Calendar val) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss"); return simpleDateFormat.format(val.getTime()); } /** * Date to custom format print to XML. * * @param val * @return */ public static String printDate(java.util.Date val) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); return simpleDateFormat.format(val); } } |
。
SETP 4:输出
1 2 3 4 5 |