Java.util.Date और XMLGregorianCalendar के बीच सरल रूपांतरण


110

मैं दोनों दिशाओं में java.util.Date और javax.xml.datatype.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();
        }
    }
}

क्या ऐसा कुछ सरल है, जैसे कुछ एपीआई कॉल जिन्हें मैंने अनदेखा कर दिया है?

एक मानक XML दिनांक / समय और एक जावा दिनांक ऑब्जेक्ट के बीच परिवर्तित करना एक बहुत ही नियमित कार्य लगता है और मुझे आश्चर्य है कि मुझे इस कोड को बिल्कुल लिखना होगा।

कोई सुझाव?

नोट: मेरे JAXB वर्गों को एक स्कीमा से स्वचालित किया गया है। मेरी परियोजना की निर्माण प्रक्रिया मुझे उत्पन्न वर्गों के लिए मैनुअल परिवर्तन करने की अनुमति नहीं देती है। Xs: डेटाइम तत्वों को XJC द्वारा JAXB कक्षाओं में XMLGregorianCalendar के रूप में उत्पन्न किया जा रहा है। स्कीमा को समय-समय पर विस्तारित और ट्विक किया जाता है, इसलिए मुझे स्कीमा एक्सएसडी फ़ाइल में सीमित बदलाव करने की अनुमति है।

समाधान पर अद्यतन: Blaise द्वारा प्रस्तावित समाधान ने मुझे XMLGregorianCalendar को मिश्रण से बाहर निकालने और java.util.Calendar ऑब्जेक्ट के बजाय सौदा करने की अनुमति दी है। मेरी स्कीमा फ़ाइल के शीर्ष पर JAXB बाइंडिंग क्लॉज़ जोड़कर, XJC मेरे JAXB क्लासेस में xs: डेटटाइम के लिए अधिक उपयुक्त मैपिंग उत्पन्न करने में सक्षम है। यहाँ कुछ स्निपेट्स हैं जो मेरी एक्सएसडी फ़ाइल में संशोधन दिखाते हैं।

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: डेटटाइम फ़ील्ड भी टाइमज़ोन को संग्रहीत करता है, इसलिए मेरे लिए कैलेंडर के साथ काम करना बेहतर हो सकता है, वैसे भी दिनांक के बजाय कैलेंडर ऑब्जेक्ट्स में स्थानों और टाइमज़ोन के साथ काम करने के लिए बहुत अच्छा एपीआई है। किसी भी मामले में, मैं XMLGregorianCalendar के बजाय कैलेंडर ऑब्जेक्ट से निपटने के लिए बहुत खुश हूं। उन रूपांतरण विधियों की कोई आवश्यकता नहीं है जो मैंने ऊपर सूचीबद्ध किए थे। मैं java.util.Date के लिए सभी तरह से नहीं मिला, लेकिन पर्याप्त पास!


मैं किसी को नहीं जानता। लेकिन तुम्हारा बहुत अच्छा लगता है - बस इसे एक utilपैकेज में रखें और इसका उपयोग करें।
बूझो

एक तरफ की तरह, लेकिन आपको पहले स्थान पर XMLGregorianCalendar वस्तुओं से क्यों निपटना है? वे एक तरह से परेशान हैं। यदि वे jaxb से आ रहे हैं तो सीधे java.util.Date को बाँधने के लिए @XMLTypeAdapter का उपयोग करना संभव है। यदि आप एक स्कीमा से अलग कर रहे हैं, तो निश्चित रूप से वस्तुओं को बदलने से आप परेशान हो सकते हैं जब आप पुन: उत्पन्न करते हैं।
Affe

@ मैं एक स्कीमा से बाहर निकल रहा हूं, इसलिए मैं जेनएक्सबी कक्षाओं में कोई भी मैन्युअल परिवर्तन नहीं कर सकता
जिम टफ


1
@ जैकब - यह नहीं है। वह पहले से ही यह पता लगा चुका है कि यह कैसे करना है, वह आश्चर्य करता है कि क्या कोई उपयोग-योग्य उपयोगिता वर्ग नहीं है।
Bozho

जवाबों:


46

XMLGregorianCalendar के बजाय java.util.Date फ़ील्ड जनरेट करने के लिए XJC को बताने के लिए बाहरी बाइंडिंग फ़ाइल का उपयोग क्यों नहीं किया जाता है?

यह भी देखें कि मैं कैसे xs: java.util.Date को मैप करूँ? ब्लॉग


मैं इस पर गौर करूंगा। धन्यवाद।
जिम टफ

कोई दिक्कत नहीं है। JAXB java.util.Date प्रकार को संभाल सकता है, आपको बस इसे अपने मॉडल में बनाने की आवश्यकता है। जो मुश्किल हो सकता है।
bdouagan

वह मेरे लिए काम कर गया। ऊपर दिए गए मेरे प्रश्न का संपादन देखें कि मैंने क्या किया।
जिम टफ

मैंने jaxb बाइंडिंग को जोड़ा लेकिन xs के ठीक नीचे: स्कीमा और मुझे निम्न त्रुटि मिलती है: com.sun.istack.SAXParseException2: कंपाइलर इस ग्लोबलबाइंडिंग अनुकूलन का सम्मान करने में असमर्थ था। यह एक गलत जगह से जुड़ा हुआ है, या अन्य बाइंडिंग के साथ असंगत है। पर com.sun.tools.xjc.ErrorReceiver.error (ErrorReceiver.java:86) पर ..
pri

@pritam - यहाँ एक और उदाहरण है जो मदद कर सकता है: blog.bdouagan.com/2011/08/xml-schema-to-java-generating.html । यह आपके द्वारा देखे जा रहे मुद्दे के लिए एक नया प्रश्न घूरने लायक हो सकता है।
20

81

XMLGregorianCalendar से java.util तक। आप बस यह कर सकते हैं:

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

धन्यवाद ... मैं मिल में XMLGregorianCalendar को समय-समय पर परिवर्तित करने का एक तरीका ढूंढ रहा था।
एंडेज नोव

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
आपके द्वारा लिखे गए तरीके से काम नहीं करता है: ग्रेगोरियन कैलेन्डर.सेटटाइम () कुछ भी वापस नहीं करेगा।
f_puras

5

मुझे इसे काम करने के लिए कुछ बदलाव करने पड़े, क्योंकि इस बीच कुछ चीजें बदल गई हैं:

  • xjc को शिकायत होगी कि मेरा एडाप्टर XmlAdapter का विस्तार नहीं करता है
  • कुछ विचित्र और अस्वाभाविक आयात किए गए थे (org.w3._2001.xmlschema)
  • पार्सिंग विधियाँ स्थिर नहीं होनी चाहिए जब 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
जब से मैंने यह सवाल उठाया है, मैं उस समय का एक जोडा टाइम फैन बन गया हूं। जावा एसई तारीख और समय वर्गों की तुलना में बहुत बेहतर है। Timezones से निपटने के लिए बहुत बढ़िया!
जिम टफ

1

मुझे भी इस तरह का सिरदर्द था। मेरे POJO में आदिम लंबे समय के रूप में समय क्षेत्र का प्रतिनिधित्व करके इससे छुटकारा पा लिया। अब मेरे WS क्लाइंट कोड की पीढ़ी सब कुछ सही ढंग से संभालती है और कोई XML-से-जावा बकवास नहीं है। और निश्चित रूप से जावा की तरफ मिलिस के साथ व्यवहार सरल और दर्द रहित है। सिद्धांत चट्टानों चुंबन!


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>


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

सेटप 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);
    }
}

सेटप 4: आउटपुट

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

   <fileDate>2014-09-25</fileDate> - Date class formatted
</xmlHeader>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.