java.util.Date 和 XMLGregorianCalendar 之间的简单转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3679266/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple conversion between java.util.Date and XMLGregorianCalendar
提问by Jim Tough
I'm looking for a simple method of converting between java.util.Date and javax.xml.datatype.XMLGregorianCalendar in both directions.
我正在寻找一种在 java.util.Date 和 javax.xml.datatype.XMLGregorianCalendar 之间双向转换的简单方法。
Here is the code that I'm using now:
这是我现在使用的代码:
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();
}
}
}
Is there anything simpler, like some API call that I have overlooked?
有没有更简单的东西,比如我忽略的一些 API 调用?
Converting between a standard XML date/time and a Java date object seems like a pretty routine task and I'm surprised that I have to write this code at all.
在标准的 XML 日期/时间和 Java 日期对象之间进行转换似乎是一项非常常规的任务,我很惊讶我必须编写这段代码。
Any suggestions?
有什么建议?
NOTES:My JAXB classes are autogenerated from a schema. The build process on my project does not allow for me to make manual changes to the generated classes. The xs:dateTime elements are being generated by XJC as XMLGregorianCalendar in the JAXB classes. The schema is extended and tweaked periodically, so I am allowed to make limited changes to the schema XSD file.
注意:我的 JAXB 类是从模式自动生成的。我的项目的构建过程不允许我对生成的类进行手动更改。xs:dateTime 元素由 XJC 在 JAXB 类中作为 XMLGregorianCalendar 生成。模式会定期扩展和调整,因此我可以对模式 XSD 文件进行有限的更改。
UPDATE ON SOLUTION:The solution proposed by Blaise has allowed me to take XMLGregorianCalendar out of the mix and deal with java.util.Calendar objects instead. By adding a JAXB binding clause at the top of my schema file, XJC is able to generate more appropriate mappings for xs:dateTime in my JAXB classes. Here are some snippets that show the modifications in my XSD file.
解决方案更新:Blaise 提出的解决方案允许我将 XMLGregorianCalendar 排除在外,而是处理 java.util.Calendar 对象。通过在我的模式文件顶部添加 JAXB 绑定子句,XJC 能够为我的 JAXB 类中的 xs:dateTime 生成更合适的映射。以下是一些片段,显示了我的 XSD 文件中的修改。
The root element in the XSD file:
XSD 文件中的根元素:
<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 binding annotation block, inserted immediately after root element in XSD:
JAXB 绑定注释块,在 XSD 中的根元素之后立即插入:
<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>
Since the XML xs:dateTime field also stores timezone, it might be better for me to work with Calendar instead of Date anyway since Calendar objects have a pretty good API for working with locales and timezones. In any case, I'm much happier to deal with Calendar objects instead of XMLGregorianCalendar. No need for the conversion methods that I listed above anymore. I didn't get all the way to java.util.Date, but close enough!
由于 XML xs:dateTime 字段也存储时区,因此我最好使用 Calendar 而不是 Date ,因为 Calendar 对象具有用于处理语言环境和时区的非常好的 API。无论如何,我更愿意处理 Calendar 对象而不是 XMLGregorianCalendar。不再需要我上面列出的转换方法。我没有完全了解 java.util.Date,但足够接近了!
采纳答案by bdoughan
Why not use an external binding file to tell XJC to generate java.util.Date fields instead of XMLGregorianCalendar?
为什么不使用外部绑定文件告诉 XJC 生成 java.util.Date 字段而不是 XMLGregorianCalendar?
回答by Gregor
I had to make some changes to make it work, as some things seem to have changed in the meantime:
我不得不进行一些更改以使其正常工作,因为在此期间有些事情似乎发生了变化:
- xjc would complain that my adapter does not extend XmlAdapter
- some bizarre and unneeded imports were drawn in (org.w3._2001.xmlschema)
- the parsing methods must not be static when extending the XmlAdapter, obviously
- xjc 会抱怨我的适配器没有扩展 XmlAdapter
- 一些奇怪的和不需要的导入被引入(org.w3._2001.xmlschema)
- 显然,扩展 XmlAdapter 时解析方法不能是静态的
Here's a working example, hope this helps (I'm using JodaTime but in this case SimpleDate would be sufficient):
这是一个工作示例,希望这会有所帮助(我使用的是 JodaTime,但在这种情况下 SimpleDate 就足够了):
import java.util.Date;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.DateTime;
public class DateAdapter extends XmlAdapter<Object, Object> {
@Override
public Object marshal(Object dt) throws Exception {
return new DateTime((Date) dt).toString("YYYY-MM-dd");
}
@Override
public Object unmarshal(Object s) throws Exception {
return DatatypeConverter.parseDate((String) s).getTime();
}
}
import java.util.Date;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.DateTime;
public class DateAdapter extends XmlAdapter<Object, Object> {
@Override
public Object marshal(Object dt) throws Exception {
return new DateTime((Date) dt).toString("YYYY-MM-dd");
}
@Override
public Object unmarshal(Object s) throws Exception {
return DatatypeConverter.parseDate((String) s).getTime();
}
}
In the xsd, I have followed the excellent references given above, so I have included this xml annotation:
在 xsd 中,我遵循了上面给出的优秀参考资料,所以我包含了这个 xml 注释:
<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>
回答by Alex
I too had this kind of headache. Got rid of of it by simply representing time fields as primitive long in my POJO. Now the generation of my WS client code handle everything correctly and no more XML-to-Java crap. And of course dealing with millis on the Java side is simple and painless. KISS principle rocks!
我也有这种头痛。通过在我的 POJO 中简单地将时间字段表示为原始 long 来摆脱它。现在我的 WS 客户端代码的生成可以正确处理所有内容,不再有 XML 到 Java 的废话。当然,在 Java 端处理millis 是简单而轻松的。KISS 原则太棒了!
回答by Zé Carlos
From XMLGregorianCalendar to java.util.Date you can simply do:
从 XMLGregorianCalendar 到 java.util.Date 你可以简单地做:
java.util.Date dt = xmlGregorianCalendarInstance.toGregorianCalendar().getTime();
回答by moralejaSinCuentoNiProverbio
From java.util.Date to XMLGregorianCalendar you can simply do:
从 java.util.Date 到 XMLGregorianCalendar,您可以简单地执行以下操作:
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);
Code edited after the first comment of @f-puras, by cause i do a mistake.
在@f-puras 的第一个评论之后编辑的代码,因为我做错了。
回答by Kanthishere
Customizing the Calendar and Date while Marshaling
在编组时自定义日历和日期
Step 1 : Prepare jaxb binding xml for custom properties, In this case i prepared for date and calendar
第 1 步:为自定义属性准备 jaxb 绑定 xml,在这种情况下,我准备了日期和日历
<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 : Add custom jaxb binding file to Apache or any related plugins at xsd option like mentioned below
Setp 2:将自定义 jaxb 绑定文件添加到 Apache 或 xsd 选项中的任何相关插件,如下所述
<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 : write the code for CalendarConverter class
第 3 步:编写 CalendarConverter 类的代码
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 : Output
第 4 步:输出
<xmlHeader>
<creationTime>2014-09-25T07:23:05</creationTime> Calendar class formatted
<fileDate>2014-09-25</fileDate> - Date class formatted
</xmlHeader>
回答by Dev
You can use the this customization to change the default mapping to java.util.Date
您可以使用此自定义将默认映射更改为 java.util.Date
<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>