Java.time.LocalDateTime और java.util.Date के बीच रूपांतरण


484

जावा 8 में तारीख और समय के लिए पूरी तरह से नया एपीआई है। इस एपीआई में सबसे उपयोगी वर्गों में से LocalDateTimeएक टाइमजोन-स्वतंत्र तिथि-समय-मान रखने के लिए है।

java.util.Dateइस उद्देश्य के लिए विरासत वर्ग का उपयोग करके कोड की शायद लाखों लाइनें हैं । जैसे, पुराने और नए कोड को इंटरफेज करते समय दोनों के बीच कंवर्ट करने की जरूरत होगी। जैसा कि इसे पूरा करने के लिए कोई प्रत्यक्ष तरीके नहीं हैं, यह कैसे किया जा सकता है?




के संभावित डुप्लिकेट Convert java.util.Date java.time.LocalDate लिए
पीटर Perháč

जवाबों:


706

संक्षिप्त जवाब:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

स्पष्टीकरण: ( इस बारे में इस सवाल पर आधारित LocalDate)

अपने नाम के बावजूद, java.util.Dateसमय-रेखा पर एक तात्कालिक का प्रतिनिधित्व करता है, न कि एक "तारीख"। ऑब्जेक्ट के भीतर संग्रहीत वास्तविक डेटा long1970-01-01T00: 00Z (1970 GMT / UTC की शुरुआत में मध्यरात्रि) के बाद से मिलीसेकंड की गणना है।

java.util.DateJSR-310 में समतुल्य वर्ग है Instant, इस प्रकार रूपांतरण और फ्रॉस्ट प्रदान करने के लिए सुविधाजनक तरीके हैं:

Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);

एक java.util.Dateउदाहरण में समय-क्षेत्र की कोई अवधारणा नहीं है। यदि आप कॉल toString()करते हैं तो यह अजीब लग सकता है java.util.Date, क्योंकि यह toStringसमय-क्षेत्र के सापेक्ष है। हालाँकि वह विधि वास्तव में स्ट्रिंग प्रदान करने के लिए मक्खी पर जावा के डिफ़ॉल्ट टाइम-ज़ोन का उपयोग करती है। समय-क्षेत्र वास्तविक स्थिति का हिस्सा नहीं है java.util.Date

एक Instantभी समय क्षेत्र के बारे में कोई जानकारी नहीं है। इस प्रकार, Instantकिसी स्थानीय दिनांक-समय से परिवर्तित करने के लिए समय-क्षेत्र निर्दिष्ट करना आवश्यक है। यह डिफ़ॉल्ट क्षेत्र हो सकता है - ZoneId.systemDefault()- या यह एक समय-क्षेत्र हो सकता है जो आपके एप्लिकेशन को नियंत्रित करता है, जैसे उपयोगकर्ता वरीयताओं से समय-क्षेत्र। LocalDateTimeएक सुविधाजनक कारखाना विधि है जो तत्काल और समय-क्षेत्र दोनों को ले जाती है:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

रिवर्स में, LocalDateTimeसमय-क्षेत्र atZone(ZoneId)विधि को कॉल करके निर्दिष्ट किया जाता है । ZonedDateTimeफिर एक के लिए सीधे परिवर्तित किया जा सकता Instant:

LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());

नोट से रूपांतरण है कि LocalDateTimeकरने के लिए ZonedDateTimeअनपेक्षित व्यवहार शुरू करने की क्षमता है। ऐसा इसलिए है क्योंकि डेलाइट सेविंग टाइम के कारण हर स्थानीय तिथि-समय मौजूद नहीं है। शरद ऋतु / गिरावट में, स्थानीय समय-रेखा में एक ओवरलैप होता है जहां एक ही स्थानीय तिथि-समय दो बार होता है। वसंत में, एक अंतराल है, जहां एक घंटे गायब हो जाता है। atZone(ZoneId)रूपांतरण क्या करेगा की अधिक परिभाषा के लिए Javadoc देखें ।

सारांश, यदि आप राउंड-ट्रिप ए java.util.Dateटू LocalDateTimeऔर बैक java.util.Dateटू यू डेलाइट सेविंग टाइम के कारण एक अलग पल के साथ समाप्त हो सकते हैं।

अतिरिक्त जानकारी: एक और अंतर है जो बहुत पुरानी तारीखों को प्रभावित करेगा। java.util.Date15 अक्टूबर 1582 को एक कैलेंडर का उपयोग करता है, इससे पहले की तारीखों के साथ जूलियन एक के बजाय जूलियन कैलेंडर का उपयोग करता है। इसके विपरीत, java.time.*हर समय के लिए आईएसओ कैलेंडर प्रणाली (ग्रेगोरियन के बराबर) का उपयोग करता है। अधिकांश उपयोग के मामलों में, आईएसओ कैलेंडर प्रणाली वही है जो आप चाहते हैं, लेकिन वर्ष 1582 से पहले की तारीखों की तुलना करते समय आपको अजीब प्रभाव दिखाई दे सकते हैं।


5
स्पष्ट स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। विशेष रूप से इसके लिए java.util.Dateटाइमज़ोन क्यों नहीं है, लेकिन इसे प्रिंट करें toString()। इवेंट ऑफिशियल डॉक्यूमेंटेशन आपके पोस्ट करते समय यह स्पष्ट रूप से नहीं बताता है।
चेरी

चेतावनी: LocalDateTime.ofInstant(date.toInstant()... कोई ऐसा व्यवहार नहीं करेगा जैसा कोई भला करेगा। उदाहरण के लिए इस दृष्टिकोण का उपयोग new Date(1111-1900,11-1,11,0,0,0);हो जाएगा 1111-11-17 23:53:28java.sql.Timestamp#toLocalDateTime()यदि आपको 1111-11-11 00:00:00पिछले उदाहरण में परिणाम की आवश्यकता है, तो कार्यान्वयन पर एक नज़र डालें ।
कुत्ता 12

2
मैंने बहुत पुरानी तारीखों (1582 से पहले) के बारे में एक खंड जोड़ा है। FWIW, आपका सुझाया गया फिक्स अच्छी तरह से गलत हो सकता है, जैसा कि java.util में 1111-11-11 है। इतिहास में वही वास्तविक दिन है जैसा कि 1111-11-18 में java.time में अलग-अलग कैलेंडर सिस्टम (6.5 मिनट के अंतर के कारण) का है। 1900 से पहले कई टाइम-ज़ोन होते हैं)
JodaStephen

2
यह भी ध्यान देने योग्य है कि java.sql.Date#toInstant फेंकता है UnsupportedOperationException। तो toInstantएक RowMapper में उपयोग न करें java.sql.ResultSet#getDate
लेज़रबास

132

यहाँ मैं क्या कर रहा हूँ (और सभी तारीखों के समय की तरह यह शायद कुछ अजीब समय-रिसाव-दिन के उजाले समायोजन के आधार पर नापसंद होने जा रहा है: डी)

राउंड-ट्रिपिंग: Date<< - >>LocalDateTime

दिया हुआ: Date date = [some date]

(१) LocalDateTime<< Instant<<Date

    Instant instant = Instant.ofEpochMilli(date.getTime());
    LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

(२) Date<< Instant<<LocalDateTime

    Instant instant = ldt.toInstant(ZoneOffset.UTC);
    Date date = Date.from(instant);

उदाहरण:

दिया हुआ:

Date date = new Date();
System.out.println(date + " long: " + date.getTime());

(1) LocalDateTime<< Instant<< Date:

बनाएं Instantसे Date:

Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);

बनाएं Dateसे Instant(आवश्यक नहीं है, लेकिन उदाहरण के लिए):

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

बनाएं LocalDateTimeसेInstant

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);

(२) Date<< Instant<<LocalDateTime

बनाएं InstantसेLocalDateTime:

instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);

सृजन करना Dateसे Instant:

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

आउटपुट है:

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

Instant from Date:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

LocalDateTime from Instant:
2013-11-01T14:13:04.574

Instant from LocalDateTime:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

2
@scottb क्या आप मुझे या उस व्यक्ति को संबोधित कर रहे हैं जिसने प्रश्न पूछा है? मेरे विचारों के लिए, ठीक है, यह अच्छा होगा कि स्पष्ट रूप से रूपांतरण 8 jdk 8 एपीआई में कहा गया है - वे कम से कम ऐसा कर सकते हैं। किसी भी मामले में, बहुत सारे पुस्तकालय हैं जिन्हें नई जावा -8 सुविधाओं को शामिल करने और यह जानना महत्वपूर्ण है कि यह कैसे करना महत्वपूर्ण है।
समन्वयक

4
@scottb 3 पार्टी मामला असामान्य क्यों होगा? इसकी लानत है आम। एक उदाहरण: जेडीबीसी 4 और कम (उम्मीद नहीं 5)।
रमन

5
एक सामान्य JSR-310 नियम के रूप में, युग-मिलिस का उपयोग करके प्रकारों के बीच परिवर्तित करने की आवश्यकता नहीं है। वस्तुओं के उपयोग से बेहतर विकल्प मौजूद हैं, नीचे मेरा पूरा जवाब देखें। UTC जैसे ज़ोन-ऑफ़सेट का उपयोग करने पर उपरोक्त उत्तर भी पूरी तरह से मान्य है - उत्तर के कुछ भाग पूरे समय-क्षेत्र जैसे अमेरिका / New_York के लिए काम नहीं करेंगे।
JodaStephen

2
इसके बजाय Instant.ofEpochMilli(date.getTime())करतेdate.toInstant()
बकरी

1
@goat toInstant()अच्छा लग रहा है, सिवाय इसके कि विफल रहता है java.sql.Date, arggggh! तो यह अंत में उपयोग करने के लिए आसान है Instant.ofEpochMilli(date.getTime())
vadipp

22

यदि आप सुनिश्चित हैं कि आपको डिफ़ॉल्ट टाइमज़ोन की आवश्यकता है तो बहुत अधिक सुविधाजनक तरीका:

Date d = java.sql.Timestamp.valueOf( myLocalDateTime );

25
ज़रूर, यह आसान है, लेकिन मुझे कम से कम IMHO के साथ साधारण तिथि से निपटने के साथ मिश्रण से संबंधित सामान पसंद नहीं है।
एनरिको ज्यूरिन

9
मुझे क्षमा करें, यह एक साधारण समस्या का एक भयानक समाधान है। यह ओलंपिक लोगो में रिंगों की संख्या के बराबर होने के लिए 5 को परिभाषित करने जैसा है।
मैडब्रेक्स

7

नए API LocalDateTime से java.util.date में कनवर्ट करते समय निम्नलिखित काम करने लगता है:

Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());

रिवर्स रूपांतरण हो सकता है (उम्मीद है) इसी तरह से हासिल किया ...

आशा है ये मदद करेगा...


5

यहाँ सब कुछ है: http://blog.progs.be/542/date-to-java-time

"राउंड-ट्रिपिंग" के साथ उत्तर सटीक नहीं है: जब आप करते हैं

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

यदि आपका सिस्टम टाइमजोन UTC / GMT नहीं है, तो आप समय बदल देते हैं!


केवल अगर आप इसे वर्ष में 1 घंटे के दौरान करते हैं, तो गिरावट में, जब LocalDateTime ओवरलैप से दो बार। स्प्रिंग फ़ॉरवर्ड चाल से कोई समस्या नहीं होती है। ज्यादातर समय दोनों दिशाओं को ठीक से बदल देगा।
डेविड


3

मुझे यकीन नहीं है कि यह सबसे सरल या सबसे अच्छा तरीका है, या यदि कोई नुकसान है, लेकिन यह काम करता है:

static public LocalDateTime toLdt(Date date) {
    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(date);
    ZonedDateTime zdt = cal.toZonedDateTime();
    return zdt.toLocalDateTime();
}

static public Date fromLdt(LocalDateTime ldt) {
    ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
    GregorianCalendar cal = GregorianCalendar.from(zdt);
    return cal.getTime();
}

3
वहाँ निश्चित रूप से एक नुकसान से जा रहा LocalDateTimeहै Date। दिन के उजाले की बचत में, LocalDateTimeगैर-मौजूद हो सकता है, या दो बार हो सकता है। आपको प्रत्येक मामले में आप क्या करना चाहते हैं, इस पर काम करने की आवश्यकता है।
जॉन स्कीट

1
BTW, GregorianCalendarपुराने अजीब एपीआई के अंतर्गत आता है जिसे java.timeबदलने के लिए नए API का उद्देश्य है
वडज़िम

3

यदि आप Android पर हैं और threetenbp का उपयोग कर रहे हैं, तो आप DateTimeUtilsइसके बजाय उपयोग कर सकते हैं ।

उदाहरण के लिए:

Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

आप इसका उपयोग नहीं कर सकते हैं Date.fromक्योंकि यह केवल एपीआई 26+ पर समर्थित है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.