2010-09-09 79 views
106

我正在寻找一个简单的方法在两个方向之间转换java.util.Date和javax.xml.datatype.XMLGregorianCalendar。简单转换java.util.Date和XMLGregorianCalendar

这里是我现在使用代码:

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类是从模式自动生成的。我的项目上的构建过程不允许我手动更改生成的类。 xj:dateTime元素由XJC生成为JAXB类中的XMLGregorianCalendar。该模式是定期扩展和调整的,因此我可以对模式XSD文件进行有限的更改。

UPDATE ON SOLUTION: 布莱斯提出的解决方案允许我采取的XMLGregorianCalendar出混合和处理的java.util.Calendar对象,而不是。通过在模式文件顶部添加一个JAXB绑定子句,XJC能够为我的JAXB类中的xs:dateTime生成更合适的映射。这里有一些片段显示了我的XSD文件中的修改。

在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绑定注释块,在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> 

由于XML的xs:日期时间字段也存储时区,因此我可以使用Calendar而不是Date来处理日历,因为Calendar对象具有用于处理语言环境和时区的相当不错的API。无论如何,我很乐意处理日历对象而不是XMLGregorianCalendar。不需要我上面列出的转换方法了。我没有完全掌握java.util.Date,但足够接近!

+0

排序的一边,但为什么你必须在第一时间处理XMLGregorianCalendar对象?他们有点恼人。如果他们来自jaxb,可以使用@XMLTypeAdapter直接绑定到java.util.Date。当然,如果您是从模式自动生成的,那么在重新生成时更改对象可能同样令人讨厌。 – Affe 2010-09-09 18:19:13

+0

@Affe我自动生成一个模式,所以我不能对生成的JAXB类进行任何手动更改 – 2010-09-09 18:22:17

+0

这与http://stackoverflow.com/questions/835889/java-util-date-to -xmlgregoriancalendar? – 2010-09-09 18:24:12

回答

44

为什么不使用外部绑定文件来告诉XJC生成java.util.Date字段而不是XMLGregorianCalendar?

另见: - http://weblogs.java.net/blog/kohsuke/archive/2006/03/how_do_i_map_xs.html

+0

我会研究这个。谢谢。 – 2010-09-09 18:54:05

+0

没问题。 JAXB可以处理java.util.Date类型,你只需要在你的模型中生成它。这可能会很棘手。 – 2010-09-09 19:13:10

+0

这对我来说很成功。有关我所做的详细信息,请参阅上面我的问题的编辑。 – 2010-09-10 13:05:40

5

我不得不做出一些改变,使其工作,因为有些东西似乎在此期间已经改变:

  • XJC会抱怨我的适配器不扩展XmlAdapter
  • 一些奇怪和不必要的进口是在(org.w3._2001。XML模式)扩展XmlAdapter时,显然

这里的工作示例

  • 解析方法不能是静态的,希望这有助于(我使用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(); 
        } 
    } 
    

    在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> 
    
  • +1

    我已经成为一个自从我提出这个问题以来,乔达时代迷。比Java SE日期和时间类更好。真棒处理时区! – 2012-08-17 16:08:26

    1

    我也有这种头痛。 通过在我的POJO中将时间字段简单地表示为原始长度而消除了它。 现在,我的WS客户端代码的生成正确地处理了一切,没有更多的XML到Java的废话。当然,在Java方面处理millis是简单而无痛的。 KISS原理岩石!

    79

    从的XMLGregorianCalendar到java.util.Date,你可以简单地做:

    java.util.Date dt = xmlGregorianCalendarInstance.toGregorianCalendar().getTime(); 
    
    +0

    谢谢...我正在寻找一种方法来将XMLGregorianCalendar转换为毫秒级的时间。 – Andez 2012-11-09 11:02:15

    6

    从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); 
    

    代码@ f-puras,因为我犯了一个错误。

    +1

    不按照您编写它的方式工作:GregorianCalendar.setTime()不会返回任何内容。 – 2014-09-12 08:56:49

    0

    定制日历和日期而编组

    步骤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 :在xsd选项中添加自定义jaxb绑定文件到Apache或任何相关插件,如下所述

    <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> 
    

    第三步将:写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代码:输出

    <xmlHeader> 
        <creationTime>2014-09-25T07:23:05</creationTime> Calendar class formatted 
    
        <fileDate>2014-09-25</fileDate> - Date class formatted 
    </xmlHeader> 
    
    1

    您可以使用此自定义更改默认映射到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> 
    

    相关问题