जवाबों:
मुझे इस 10 साल पुराने प्रश्न पर एक कदम पीछे हटना चाहिए और एक आधुनिक रूप देना चाहिए। उल्लिखित कक्षाएं, Date
और XMLGregorianCalendar
, अब पुरानी हैं। मैं उनके उपयोग को चुनौती देता हूं और विकल्प प्रस्तुत करता हूं।
Date
हमेशा खराब डिज़ाइन किया गया था और 20 साल से अधिक पुराना है। यह सरल है: इसका उपयोग न करें।XMLGregorianCalendar
पुराना भी है और एक पुराने ढंग का डिजाइन है। जैसा कि मैं इसे समझता हूं, इसका उपयोग XML दस्तावेजों के लिए XML प्रारूप में दिनांक और समय के उत्पादन के लिए किया गया था। जैसा 2009-05-07T19:05:45.678+02:00
या 2009-05-07T17:05:45.678Z
। ये प्रारूप आईएसओ 8601 के साथ पर्याप्त रूप से सहमत हैं कि java.time, आधुनिक जावा तिथि और समय एपीआई की कक्षाएं, उन्हें उत्पादन कर सकती हैं, जिसे हम पसंद करते हैं।कई (सबसे?) उद्देश्यों के लिए एक के लिए आधुनिक प्रतिस्थापन एक Date
होगा Instant
। एक Instant
समय में एक बिंदु (बस एक के रूप Date
में) है।
Instant yourInstant = // ...
System.out.println(yourInstant);
इस स्निपेट से एक उदाहरण आउटपुट:
2009-05-07T17: 05: 45.678Z
यह XMLGregorianCalendar
ऊपर के मेरे उदाहरण के तार के समान है। जैसा कि आप में से अधिकांश जानते हैं, यह Instant.toString
अंतर्निहित रूप से कहा जाता है System.out.println
। Java.time के साथ, कई मामलों में हम रूपांतरण पुराने दिनों में हम के बीच किया जाता है कि की जरूरत नहीं है Date
, Calendar
, XMLGregorianCalendar
और अन्य वर्गों (कुछ मामलों में हम जरूरत रूपांतरण कर में, हालांकि, मैं तुम्हें अगले भाग में एक जोड़े को दिखा रहा) ।
न तो एक Date
और न ही में Instant
एक समय क्षेत्र मिल गया है और न ही एक यूटीसी ऑफसेट। बेन नोलैंड द्वारा पहले स्वीकार किए गए और अभी भी सबसे अधिक वोट किए गए उत्तर का उपयोग ऑफ़सेट के चयन के लिए जेवीएम वर्तमान डिफ़ॉल्ट समय क्षेत्र का उपयोग करता है XMLGregorianCalendar
। एक आधुनिक वस्तु में एक ऑफसेट को शामिल करने के लिए हम एक का उपयोग करते हैं OffsetDateTime
। उदाहरण के लिए:
ZoneId zone = ZoneId.of("America/Asuncion");
OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
System.out.println(dateTime);
2009-05-07T13: 05: 45.678-04: 00
फिर से यह XML प्रारूप के अनुरूप है। यदि आप वर्तमान जेवीएम टाइम ज़ोन सेटिंग का फिर से उपयोग करना चाहते हैं, तो सेट zone
करें ZoneId.systemDefault()
।
में परिवर्तित Instant
करने के और भी तरीके हैं XMLGregorianCalendar
। मैं एक युगल पेश करूंगा, प्रत्येक इसके पेशेवरों और विपक्षों के साथ। सबसे पहले, जैसे XMLGregorianCalendar
एक स्ट्रिंग पैदा करता है 2009-05-07T17:05:45.678Z
, यह भी इस तरह के एक स्ट्रिंग से बनाया जा सकता है:
String dateTimeString = yourInstant.toString();
XMLGregorianCalendar date2
= DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
System.out.println(date2);
2009-05-07T17: 05: 45.678Z
प्रो: यह छोटा है और मुझे नहीं लगता कि यह कोई आश्चर्य की बात है। Con: मेरे लिए यह ऐसा लगता है जैसे अपशिष्ट एक स्ट्रिंग में तत्काल स्वरूपण करता है और इसे वापस पार्स करता है।
ZonedDateTime dateTime = yourInstant.atZone(zone);
GregorianCalendar c = GregorianCalendar.from(dateTime);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
System.out.println(date2);
2009-05-07T13: 05: 45.678-04: 00
प्रो: यह आधिकारिक रूपांतरण है। ऑफसेट को नियंत्रित करना स्वाभाविक रूप से आता है। Con: यह अधिक चरणों से गुजरता है और इसलिए अधिक लंबा है।
यदि आपको Date
विरासत एपीआई से एक पुराने जमाने की वस्तु मिली है जिसे आप अभी नहीं बदल सकते हैं, तो इसे इसमें परिवर्तित करें Instant
:
Instant i = yourDate.toInstant();
System.out.println(i);
आउटपुट पहले जैसा ही है:
2009-05-07T17: 05: 45.678Z
यदि आप ऑफ़सेट को नियंत्रित करना चाहते हैं, तो OffsetDateTime
ऊपर की तरह उसी रूप में परिवर्तित करें ।
यदि आपको एक पुराने जमाने का है Date
और आपको पुराने जमाने की जरूरत है XMLGregorianCalendar
, तो बस बेन नॉलैंड के जवाब का उपयोग करें।
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
उन है कि यहाँ खत्म हो सकता है (से विपरीत रूपांतरण की तलाश के लिए XMLGregorianCalendar
करने के लिए Date
):
XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();
यहाँ एक ग्रेगोरियन कैलेन्डर से XMLGregorianCalendar में परिवर्तित करने की एक विधि है; मैं आपके लिए एक व्यायाम के रूप में एक java.util.Date से ग्रेगोरियन कैलेन्डर में परिवर्तित होने का हिस्सा छोड़ दूंगा:
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
संपादित करें: Slooow :-)
जोडा-टाइम लाइब्रेरी का उपयोग करते हुए एक पंक्ति उदाहरण :
XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());
स्वीकार किए गए उत्तर में अपनी टिप्पणी से निकोलस मोमर्ट्स को श्रेय ।
बस मैंने सोचा कि मैं नीचे अपना समाधान जोड़ दूंगा, क्योंकि ऊपर दिए गए उत्तर मेरी सटीक जरूरतों को पूरा नहीं करते हैं। मेरे Xml स्कीमा को अलग दिनांक और समय के तत्वों की आवश्यकता है, न कि एक सिंग डेट डेट फ़ील्ड। ऊपर उपयोग किया गया मानक XMLGregorianCalendar निर्माता एक DateTime फ़ील्ड जनरेट करेगा
ध्यान दें कि गोथका के कुछ जोड़े हैं, जैसे कि महीने में एक को जोड़ना (क्योंकि जावा 0 से महीनों की गणना करता है)।
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);
मुझे उम्मीद है कि मेरी एन्कोडिंग यहाँ सही है; डी इसे और तेज़ बनाने के लिए बस निर्माता के बजाय ग्रेगोरियन कैलेन्डर के बदसूरत getInstance () कॉल का उपयोग करें:
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
// do not forget the type cast :/
GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
GregorianCalendar.getInstance()
के बराबर है Calendar.getInstance()
। Calendar.getInstance()
, यह तेजी से कर सकते हैं नहीं है क्योंकि यह एक ही उपयोग करता है new GregorianCalendar()
, लेकिन इससे पहले यह भी डिफ़ॉल्ट स्थान की जांच करता है और बदले में जापानी या Buddish कैलेंडर बना सकते हैं, इसलिए कुछ भाग्यशाली उपयोगकर्ताओं के लिए यह हो जाएगा ClassCastException
!
मान लें कि आप xml को डिकोड या एन्कोडिंग कर रहे हैं और उपयोग कर रहे हैं JAXB
, तो यह संभव है कि डेटाइम बाइंडिंग को पूरी तरह से बदल दिया जाए और स्कीमा में प्रत्येक तिथि के लिए `XMLGregorianCalendar’ के अलावा किसी अन्य चीज़ का उपयोग किया जाए।
इस तरह से आप कर सकते हैं JAXB
दोहराव वाले सामान कर सकते हैं, जबकि आप मूल्य वितरित करने वाले भयानक कोड लिखने में समय बिता सकते हैं।
उदाहरण के लिए जद्दोजहद DateTime
: (java.util.Date के साथ ऐसा करना भी काम करेगा - लेकिन कुछ सीमाओं के साथ। मैं jodatime पसंद करता हूं और इसे मेरे कोड से कॉपी किया जाता है, इसलिए मुझे पता है कि यह काम करता है ...)
<jxb:globalBindings>
<jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
parseMethod="test.util.JaxbConverter.parseDateTime"
printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
<jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
parseMethod="test.util.JaxbConverter.parseDate"
printMethod="test.util.JaxbConverter.printDate" />
<jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
parseMethod="test.util.JaxbConverter.parseTime"
printMethod="test.util.JaxbConverter.printTime" />
<jxb:serializable uid="2" />
</jxb:globalBindings>
और कनवर्टर:
public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();
public static LocalDateTime parseDateTime(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
LocalDateTime r = dtf.parseLocalDateTime(s);
return r;
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printDateTime(LocalDateTime d) {
try {
if (d == null)
return null;
return dtf.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static LocalDate parseDate(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
return df.parseLocalDate(s);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printDate(LocalDate d) {
try {
if (d == null)
return null;
return df.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printTime(LocalTime d) {
try {
if (d == null)
return null;
return tf.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static LocalTime parseTime(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
return df.parseLocalTime(s);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
यहाँ देखें: XmlGregorianCalendar को तारीख से कैसे बदलें?
यदि आप टाइमज़ोन + टाइमस्टैम्प के आधार पर सिर्फ एक मैप के लिए खुश हैं, और मूल टाइमज़ोन वास्तव में प्रासंगिक नहीं है, तो java.util.Date
शायद ठीक भी है।
इस कोड को देखें: -
/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(date);
try{
xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("XMLGregorianCalendar :- " + xmlDate);
आप यहां पूरा उदाहरण देख सकते हैं
ZonedDateTime
वर्ग, और नए रूपांतरण तरीके विरासत कक्षाओं में जोड़े गए हैं। इस उत्तर में विवरण ओले वीवी