2010-09-09 77 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> 
    

    相關問題