आईएसओ 8601-अनुरूप स्ट्रिंग को java.util.Date में परिवर्तित करना


668

मैं एक कन्वर्ट करने के लिए कोशिश कर रहा हूँ आईएसओ 8601 स्वरूपित स्ट्रिंग को एक मेंjava.util.Date

मुझे पैटर्न मिला yyyy-MM-dd'T'HH:mm:ssZ लोकेल के साथ प्रयोग किया जाता है (तुलना नमूना) तो मुझे ISO8601 के अनुरूप ।

हालाँकि, का उपयोग करते हुए java.text.SimpleDateFormat, मैं सही ढंग से स्वरूपित स्ट्रिंग को परिवर्तित नहीं कर सकता2010-01-01T12:00:00+01:00 । मुझे इसे 2010-01-01T12:00:00+0100बृहदान्त्र के बिना, पहले बदलना होगा ।

तो, वर्तमान समाधान है

SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));

जो स्पष्ट रूप से अच्छा नहीं है। क्या मुझे कुछ याद आ रहा है या कोई बेहतर उपाय है?


उत्तर

जुआनज़े की टिप्पणी के लिए धन्यवाद, मुझे जोडा-टाइम जादू मिला, यह भी यहाँ वर्णित है

तो, समाधान है

DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));

या अधिक बस, कंस्ट्रक्टर के माध्यम से डिफ़ॉल्ट पार्सर का उपयोग करें:

DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;

मेरे लिए, यह अच्छा है।


243
बहुत सारे "Use JodaTime" उत्तर प्राप्त करने के लिए तैयार रहें ...
JuanZe

3
@ Ice09: यदि DateTimeFormat के लिए एपीआई प्रलेखन सही है (जोडा दस्तावेज भ्रामक, गलत या अधूरा हो सकता है), लेकिन आपके द्वारा अपने "उत्तर" में उपयोग किया गया पैटर्न ISO8601 के साथ संगत नहीं है।
जर्नबजो

21
मुझे यकीन नहीं है कि जब इसे जोड़ा गया था, लेकिन SimpleDateFormat के भीतर 'X' इस समस्या को हल करने के लिए प्रकट होता है। पैटर्न "yyyy-MM-dd'T'HH: mm: ssX" सफलतापूर्वक प्रश्न में उदाहरण प्रस्तुत करता है।
mlohbihler

12

3
जावा 8 यह आसान बनाता है! नीचे दिए गए उत्तरों में एडम द्वारा एक छिपा हुआ मणि है: stackoverflow.com/a/27479533/1262901
फैबियन केलर

जवाबों:


477

दुर्भाग्य से, SimpleDateFormat (जावा 6 और पहले) के लिए उपलब्ध समय क्षेत्र प्रारूप आईएसओ 8601 अनुरूप नहीं हैं । SimpleDateFormat "GMT + 01: 00" या "+0100" जैसे टाइम ज़ोन स्ट्रिंग्स को समझता है, RFC # 822 के अनुसार ।

भले ही Java 7 ने ISO 8601 के अनुसार टाइम ज़ोन डिस्क्रिप्टर के लिए सपोर्ट जोड़ा हो, SimpleDateFormat अभी भी पूरी तरह से स्ट्रिंग को पार्स करने में सक्षम नहीं है, क्योंकि इसमें वैकल्पिक भागों के लिए कोई समर्थन नहीं है।

Regexp का उपयोग करके अपने इनपुट स्ट्रिंग को सुधारना निश्चित रूप से एक संभावना है, लेकिन प्रतिस्थापन नियम आपके प्रश्न में उतने सरल नहीं हैं:

  • कुछ समय क्षेत्र यूटीसी से पूरे घंटे नहीं हैं , इसलिए स्ट्रिंग जरूरी ": 00" के साथ समाप्त नहीं होती है।
  • ISO8601 केवल समय क्षेत्र में शामिल होने के लिए घंटों की संख्या की अनुमति देता है, इसलिए "+01" "+01" 00 के बराबर है
  • ISO8601 यूटीसी को "+00: 00" के बजाय "Z" के उपयोग की अनुमति देता है।

JAXB में डेटा प्रकार कनवर्टर का उपयोग करने के लिए आसान समाधान संभवतः है, क्योंकि JAXB XML स्कीमा विनिर्देश के अनुसार ISO8601 दिनांक स्ट्रिंग पार्स करने में सक्षम होना चाहिए। javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")आप एक Calendarवस्तु दे देंगे और आप बस उस पर getTime () का उपयोग कर सकते हैं, अगर आपको कोई Dateवस्तु चाहिए।

आप शायद जोडा-टाइम का भी इस्तेमाल कर सकते हैं , लेकिन मुझे नहीं पता कि आपको इससे परेशान क्यों होना चाहिए।


18
JAXB- समाधान वास्तव में रचनात्मक दृष्टिकोण है! यह भी काम करता है, मैंने अपने नमूने के साथ इसका परीक्षण किया है। हालाँकि, जो कोई भी समस्या का सामना करता है और उसे JodaTime का उपयोग करने की अनुमति है, मैं इसे उपयोग करने की सलाह दूंगा, क्योंकि यह अधिक प्राकृतिक लगता है। लेकिन आपके समाधान के लिए अतिरिक्त पुस्तकालयों की आवश्यकता नहीं है (कम से कम जावा 6 के साथ)।
आइस09

36
यहाँ उल्टा है: Calendar c = ग्रेगोरियन कैलेन्डर .getInstance (); c.setTime (aDate); वापसी javax.xml.bind.DatatypeConverter.printDateTime (c);
अलेक्जेंडर लजबर्गबर्ग

4
वास्तव में यह इतना आसान नहीं है b / c आपको jaxb datatypeConverter को इनिशियलाइज़ करना है। मैंने डेटाटाइप कॉन्ट्रैक्टरइमप्लेट के रूप में आंतरिक रूप से स्वयं डाटाटेक्टफैक्ट का उपयोग करके समाप्त किया। क्या सिरदर्द है।
21

3
@ साइमन: नहीं, टाइमजोन को नजरअंदाज नहीं किया जाता है। आप कुछ गलत कर रहे होंगे। यदि आप कुछ वर्णों से अधिक टाइप करते हैं और हमें बताएं कि आप वास्तव में क्या कर रहे हैं, तो कोई व्यक्ति आपको समझा सकता है कि क्या है।
जर्बानो

4
@ जर्नबजो आप पहले और एकमात्र व्यक्ति हैं जिनका मैंने सामना किया है, जो मानक, पूर्व 1.8, जावा तिथि वर्गों, जोडा-टाइम के ऊपर पसंद करते हैं। मुझे जॉडा-टाइम एक शाब्दिक आनंद के रूप में मिलता है, खासकर जब मानक आपी की तुलना में जो एक घृणित है।
निमचम्प्सकी

245

जिस तरह से जावा 7 प्रलेखन द्वारा धन्य है :

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String string1 = "2001-07-04T12:08:56.235-0700";
Date result1 = df1.parse(string1);

DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
String string2 = "2001-07-04T12:08:56.235-07:00";
Date result2 = df2.parse(string2);

आप SimpleDateFormat javadoc पर अनुभाग उदाहरणों में अधिक उदाहरण पा सकते हैं ।

UPD 02/13/2020: जावा 8 में ऐसा करने का एक नया तरीका है


7
आपके उत्तर ने मुझे MongoDB के ISODATE को स्थानीय तारीख में बदलने में मदद की। सादर।
ब्लू स्काई

9
@ b.long Java ने ऐसे ISO 8601 अनुरूप स्वरूपों के लिए एक स्थिरांक से अधिक जोड़ा। जावा को तिथि-समय के काम के लिए एक नया ढांचा मिला जिसमें ऐसे प्रारूपों के लिए अंतर्निहित डिफ़ॉल्ट समर्थन शामिल है। जावा 8 में नया java.timeफ्रेमवर्क देखें , जोडा-टाइम से प्रेरित है , परेशान करने वाले java.util.Date, .Calendar और SimpleDateFormat कक्षाओं को दबाकर।
बेसिल बोर्के

2
क्या इसका मतलब यह नहीं है कि आपको अग्रिम में तारीख प्रारूप जानने की आवश्यकता है? क्या आप स्वीकार करना होगा अगर string1और string2लेकिन पता नहीं है जो आप मिल जाएगा।
टिम्मम

16
'Z' को उद्धरणों में होना आवश्यक है
kervin

7
@kervin यदि Z उद्धरणों में है, तो क्या फ़ॉर्मेटर विशेष रूप से वर्ण Z की तलाश में नहीं होगा, न कि सभी ऑफ़सेट स्ट्रिंग्स जो इसे दर्शा सकते हैं? ऐसा लगता है कि Z को उद्धृत करना केवल संयोग से काम करेगा, अगर आपकी तारीख स्ट्रिंग UTC में हुई।
स्पाकार्की 21

201

ठीक है, यह सवाल पहले से ही उत्तर दिया गया है, लेकिन मैं अपना जवाब वैसे भी छोड़ दूंगा। यह किसी की मदद कर सकता है।

मैं Android (API 7) के लिए समाधान ढूंढ रहा हूं ।

  • जोडा सवाल से बाहर था - यह बहुत बड़ा है और धीमी गति से आरंभ होने से ग्रस्त है। यह उस विशेष उद्देश्य के लिए भी एक बड़ा काम था।
  • इसमें शामिल उत्तर javax.xmlAndroid API 7 पर काम नहीं करेंगे।

इस साधारण वर्ग को लागू करने का समर्थन किया। यह केवल आईएसओ 8601 स्ट्रिंग्स के सबसे सामान्य रूप को शामिल करता है , लेकिन यह कुछ मामलों में पर्याप्त होना चाहिए (जब आप यह सुनिश्चित कर लें कि इनपुट इस प्रारूप में होगा )।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Helper class for handling a most common subset of ISO 8601 strings
 * (in the following format: "2008-03-01T13:00:00+01:00"). It supports
 * parsing the "Z" timezone, but many other less-used features are
 * missing.
 */
public final class ISO8601 {
    /** Transform Calendar to ISO 8601 string. */
    public static String fromCalendar(final Calendar calendar) {
        Date date = calendar.getTime();
        String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
            .format(date);
        return formatted.substring(0, 22) + ":" + formatted.substring(22);
    }

    /** Get current date and time formatted as ISO 8601 string. */
    public static String now() {
        return fromCalendar(GregorianCalendar.getInstance());
    }

    /** Transform ISO 8601 string to Calendar. */
    public static Calendar toCalendar(final String iso8601string)
            throws ParseException {
        Calendar calendar = GregorianCalendar.getInstance();
        String s = iso8601string.replace("Z", "+00:00");
        try {
            s = s.substring(0, 22) + s.substring(23);  // to get rid of the ":"
        } catch (IndexOutOfBoundsException e) {
            throw new ParseException("Invalid length", 0);
        }
        Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s);
        calendar.setTime(date);
        return calendar;
    }
}

प्रदर्शन नोट: मैं एंड्रॉइड 2.1 में बग से बचने के लिए हर बार नए SimpleDateFormat का उपयोग करता हूं । यदि आप मेरे रूप में चकित थे, तो इस पहेली को देखें । अन्य जावा इंजन के लिए, आप एक निजी स्थिर क्षेत्र में उदाहरण को कैश कर सकते हैं (थ्रेडलोक का उपयोग करके, थ्रेड को सुरक्षित रखने के लिए)।


2
शायद यह अपने स्वयं के प्रश्न के साथ बनाया जाना चाहिए था, अपने स्वयं के उत्तर के साथ?
Thorbear

5
यह पहला पन्ना था, जब मैं जवाब की तलाश में था, तब मुझे यह लगा। अधिकांश जावा डेवलपर्स के लिए, Android बिल्कुल जावा नहीं है। हालांकि, ज्यादातर मामलों में, एक दूसरे के समान ही काम करता है, इसलिए कई एंड्रॉइड डेवलपर्स इसे ढूंढते समय "जावा" की खोज करेंगे।
wrygiel

1
ध्यान दें कि यह मिलीसेकंड रिज़ॉल्यूशन के लिए नहीं है। यह जोड़ना आसान है।
स्काई केल्सी

6
मैं जोड़ने के लिए था। आंशिक सेकंड के लिए .SS लेकिन महान thx काम करता है। आप ऐसा क्यों करते हैं s = s.substring(0, 22) + s.substring(23);- मैं इस बिंदु को नहीं देख रहा हूँ
डोरी

1
input = input.replaceAll ("[Zz]", "+0000"); काम भी करेगा और ऑप्रेटिंग ऑपरेशन से बचा जा सकता है।
जावनाटोर

115

java.time

java.time एपीआई (जावा 8 और बाद में बनाया गया), यह थोड़ा आसान बना देता है।

यदि आप जानते हैं कि इनपुट UTC में है , जैसे कि Z(ज़ुलु के लिए) अंत में, Instantवर्ग पार्स कर सकता है।

java.util.Date date = Date.from( Instant.parse( "2014-12-12T10:39:40Z" ));

यदि आपका इनपुट अंत में (ज़ुलु) द्वारा इंगित UTC के बजाय एक अन्य ऑफसेट-यू-यूटीसी मान हो सकता है , तो वर्ग को पार्स करने के लिए उपयोग करें ।ZOffsetDateTime

OffsetDateTime odt = OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" );

फिर एक निकालें Instant, और एक java.util.Dateकॉल करके परिवर्तित करें from

Instant instant = odt.toInstant();  // Instant is always in UTC.
java.util.Date date = java.util.Date.from( instant );

8
यह जवाब बहुत कठिन काम है। परिभाषा के अनुसार java.util.Date का कोई समय क्षेत्र नहीं है। तो उस समय क्षेत्र से संबंधित कोड: LocalDateTimeऔर ZoneIdऔर सभी के लिए कोई ज़रूरत नहीं है atZone। यह सरल एक-लाइनर करेगा:java.util.Date date = Date.from( ZonedDateTime.parse( "2014-12-12T10:39:40Z" ).toInstant() );
तुलसी बोर्क

5
@ बासिलबूर्क यह अनावश्यक रूप से जटिल है: Date.from(Instant.parse("2014-12-12T10:39:40Z" ));पर्याप्त है।
19

3
@assylias आप सही हैं, लेकिन यह तभी काम करेगा जब तारीख स्ट्रिंग UTC ज़ोन हो, ISO8601 किसी भी समय की अनुमति देता है ...
एडम

2
@ अदम मेरा बुरा - मुझे एहसास नहीं था कि सवाल आपके उदाहरण से अधिक सामान्य था। एक पक्ष की टिप्पणी के रूप में OffsetDateTimeISO8601 को पार्स करने के लिए पर्याप्त होगा (जिसमें समय क्षेत्र की जानकारी नहीं है, लेकिन केवल एक ऑफसेट है)।
assylias

1
@assylias Instantपार्सिंग करने देने के बारे में आपकी टिप्पणी के लिए धन्यवाद । जबकि इस विशेष प्रश्न के लिए पर्याप्त नहीं है, यह एक महत्वपूर्ण अंतर है जो इंगित करने लायक है। इसलिए मैंने कोड का दूसरा उदाहरण जोड़ा। उफ़, बस ध्यान दिया कि यह मूल रूप से मेरा उत्तर नहीं है; मुझे उम्मीद है कि आदम ने मंजूरी दी।
तुलसी बोर्क

67

जैक्सन-DataBind पुस्तकालय भी है ISO8601DateFormat वर्ग है कि (में वास्तविक क्रियान्वयन करता है ISO8601Utils

ISO8601DateFormat df = new ISO8601DateFormat();
Date d = df.parse("2010-07-28T22:25:51Z");

यह इस दिनांक को पार्स करने में विफल रहता है 2015-08-11T13:10:00:। मुझे मिलता है String index out of range: 19। कोड को देखते हुए ऐसा लगता है कि इसके लिए मिलीसेकंड निर्दिष्ट करने की आवश्यकता है, और टाइमज़ोन। वे वैकल्पिक होना चाहिए।
टिम्मम

2
प्रलेखन को उद्धृत करने के लिए, पार्स प्रारूप है [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]:। दूसरे शब्दों में, मिलीसेकंड वैकल्पिक है लेकिन समय क्षेत्र अनिवार्य है।
david_p

2
आह हाँ वास्तव में ऐसा लगता है कि आप सही हैं। फिर भी, मुझे पूरा यकीन है कि ISO8601 आपको टाइमज़ोन छोड़ने की अनुमति देता है इसलिए यह अभी भी गलत है। JodaTime हालांकि काम करता है:new DateTime("2015-08-11T13:10:00").toDate()
Timmmm

3
वह वर्ग अब पदावनत हो गया है, नया स्टैडडेटफार्म है। अन्यथा यह समान काम करता है।
जॉनएय

51

tl; डॉ

OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" )

Java.time का उपयोग करना

जावा 8 में नया java.time पैकेज और बाद में जोडा-टाइम से प्रेरित था।

OffsetDateTimeवर्ग एक साथ समय रेखा पर एक पल का प्रतिनिधित्व करता ऑफसेट-से-यूटीसी नहीं बल्कि एक समय क्षेत्र।

OffsetDateTime odt = OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" );

कॉलिंग toStringमानक ISO 8601 प्रारूप में एक स्ट्रिंग उत्पन्न करता है:

2010-01-01T12: 00 + 01: 00

यूटीसी के लेंस के माध्यम से एक ही मूल्य देखने के लिए, एक को निकालने Instantया समायोजित से ऑफसेट +01:00करने के लिए 00:00

Instant instant = odt.toInstant();  

... या ...

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );

अगर वांछित समय क्षेत्र में समायोजित करें। डे टाइम सेविंग टाइम (डीएसटी) जैसे विसंगतियों से निपटने के लिए नियमों का एक सेट के साथ एक समय क्षेत्र एक क्षेत्र के लिए ऑफसेट-यू-यूटीसी मूल्यों का इतिहास है । इसलिए जब भी संभव हो एक मात्र ऑफसेट के बजाय एक समय क्षेत्र लागू करें।

ZonedDateTime zonedDateTimeMontréal = odt.atZoneSameInstant( ZoneId.of( "America/Montreal" ) );

जावा के बारे में

Java.time ढांचे जावा 8 और बाद में बनाया गया है। इन कक्षाओं परेशानी वर्ष प्रतिस्थापित विरासत जैसे तिथि-समय कक्षाएं java.util.Date, Calendar, और SimpleDateFormat

Joda समय परियोजना, अब में रखरखाव मोड , प्रवास करने की सलाह देता java.time कक्षाएं।

अधिक जानने के लिए, Oracle ट्यूटोरियल देखें । और कई उदाहरणों और स्पष्टीकरणों के लिए ढेर अतिप्रवाह खोजें। विशिष्टता JSR 310 है

आप अपने डेटाबेस से सीधे java.time वस्तुओं का आदान-प्रदान कर सकते हैं । JDBC 4.2 या उसके बाद के JDBC ड्राइवर का अनुपालन करें । तार की कोई जरूरत नहीं, कोई जरूरत नहींjava.sql.* कक्षाओं ।

Java.time कक्षाएं कहाँ से प्राप्त करें?

ThreeTen-अतिरिक्त परियोजना अतिरिक्त कक्षाओं के साथ java.time फैली हुई है। यह परियोजना java.time के संभावित भविष्य के परिवर्धन के लिए एक साबित जमीन है। आप यहाँ कुछ उपयोगी वर्गों जैसे मिल सकता है Interval, YearWeek, YearQuarter, और अधिक



27

जावा संस्करण 7 के लिए

आप Oracle प्रलेखन का पालन कर सकते हैं: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X - का उपयोग ISO 8601 समय क्षेत्र के लिए किया जाता है

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

System.out.println(nowAsISO);

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);

System.out.println(finalResult);

इसका मतलब है कि समय क्षेत्र की आवश्यकता है । आईएसओ 8601 के अनुसार यह वैकल्पिक है। जैसे सेकंड हैं, इत्यादि तो यह केवल आईएसओ 8601 का एक विशिष्ट उप-भाग बन जाता है।
टिम्मम

1
जावा 1.8 के साथ महान काम करता है
थिएगो परेरा

20

DatatypeConverter समाधान सभी VMs में काम नहीं करता है। निम्नलिखित मेरे लिए काम करता है:

javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar("2011-01-01Z").toGregorianCalendar().getTime()

मैंने पाया है कि जोडा बॉक्स से बाहर काम नहीं करता है (विशेष रूप से उदाहरण के लिए मैंने एक तिथि पर टाइमज़ोन के साथ ऊपर दिया था, जिसकी आवश्यकता है)


15

मुझे लगता है कि हमें उपयोग करना चाहिए

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

दिनांक के लिए 2010-01-01T12:00:00Z


5
यह दूसरों की तुलना में बेहतर उत्तर क्यों है, इसमें 76 उत्तोलकों के साथ स्वीकृत उत्तर शामिल है?
एरिक रॉबर्टसन

3
@ एरिक रॉबर्टसन: यह सरल है, बॉक्स से बाहर है, लचीला है, कोई रूपांतरण नहीं है, और अधिकांश लोग समय क्षेत्र की परवाह नहीं करते हैं।
ट्वीस्टरेब

7
यदि आप टाइमज़ोन के बारे में परवाह नहीं करते हैं, तो समय के साथ काम करने के लिए बहुत ज्यादा नहीं है!
डोरी

16
इस समय को पूरी तरह से इग्नोर कर देता है। इसका उपयोग तब तक कर रहा था जब तक मुझे एहसास नहीं हुआ कि यह हो रहा है, इसलिए मैंने JodaTime पर स्विच किया।
यहोशू पिंटर

3
समय क्षेत्र को दूर फेंकने से कुछ बिंदुओं पर त्रुटियां होंगी।
बार्ट वैन कुइक

11

जावा 8 से शुरू, ऐसा करने के लिए एक पूरी तरह से नया समर्थित तरीका है:

    String s = "2020-02-13T18:51:09.840Z";
    TemporalAccessor ta = DateTimeFormatter.ISO_INSTANT.parse(s);
    Instant i = Instant.from(ta);
    Date d = Date.from(i);

2
यदि स्ट्रिंग तत्काल प्रारूप में है, Zतो ऑफसेट के रूप में अनुगामी के साथ , हमें इसे स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता नहीं है। बस Instant i = Instant.parse(s);। प्रश्न में तार था +01:00, जिस स्थिति में DateTimeFormatter.ISO_INSTANTकाम नहीं करता है (कम से कम मेरे जावा 11 पर नहीं)।
ओले वीवी

2
@ OleV.V। आप ISO_OFFSET_DATE_TIMEऑफसेट के साथ दिनांक प्रारूप करने के लिए उपयोग कर सकते हैं , जैसे +01:00( docs.oracle.com/javase/8/docs/api/java/time/format/… )
लुकास बेसकनेरो

1
यह सच है, @LasasBasquerotto। हालांकि उस फॉर्मेटर का स्पष्ट रूप से उल्लेख नहीं किया गया है, एडम और बेसिल बोर्के के जवाब पहले से ही कुछ समान हैं।
ओले वीवी

10

ISO8601 टाइमस्टैम्प को पार्स करने का एक और बहुत ही सरल तरीका है org.apache.commons.lang.time.DateUtils:

import static org.junit.Assert.assertEquals;

import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
import org.junit.Test;

public class ISO8601TimestampFormatTest {
  @Test
  public void parse() throws ParseException {
    Date date = DateUtils.parseDate("2010-01-01T12:00:00+01:00", new String[]{ "yyyy-MM-dd'T'HH:mm:ssZZ" });
    assertEquals("Fri Jan 01 12:00:00 CET 2010", date.toString());
  }
}

6

java.time

ध्यान दें कि जावा 8 में, आप java.time.ZonedDateTime वर्ग और इसकी स्थैतिक parse(CharSequence text)विधि का उपयोग कर सकते हैं ।


प्रश्न में इनपुट स्ट्रिंग्स में केवल ऑफ़सेट-यूटीसी है, न कि पूर्णकालिक क्षेत्र। तो Instantऔर ZonedDateTimeयहाँ उपयुक्त हैं, नहीं ZonedDateTime
बेसिल बॉर्क

6

Java 7+ के लिए वैकल्पिक हल SimpleDateFormat का उपयोग कर रहा है:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);

यह कोड ISO8601 प्रारूप को पार्स कर सकता है जैसे:

  • 2017-05-17T06:01:43.785Z
  • 2017-05-13T02:58:21.391+01:00

लेकिन Java6 में, चरित्र SimpleDateFormatसमझ में नहीं आता Xहै और फेंक देगा
IllegalArgumentException: Unknown pattern character 'X'
हमें Java 6 में पठनीय प्रारूप के लिए ISO8601 तिथि को सामान्य करने की आवश्यकता है SimpleDateFormat

public static Date iso8601Format(String formattedDate) throws ParseException {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
        return df.parse(formattedDate);
    } catch (IllegalArgumentException ex) {
        // error happen in Java 6: Unknown pattern character 'X'
        if (formattedDate.endsWith("Z")) formattedDate = formattedDate.replace("Z", "+0000");
        else formattedDate = formattedDate.replaceAll("([+-]\\d\\d):(\\d\\d)\\s*$", "$1$2");
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
        return df1.parse(formattedDate);
    }
}

जावा 6 में त्रुटि होने पर [ Zसाथ +0000] या [ +01:00साथ +0100] बदलने के लिए ऊपर विधि (यदि आप जावा संस्करण का पता लगा सकते हैं और यदि कथन के साथ कोशिश / कैच को बदल सकते हैं)।


नहीं, परेशान पुराने पुराने समय की कक्षाएं जैसे कि Dateऔर SimpleDateFormatखराब तरीके से डिजाइन की गई, भ्रमित करने वाली और त्रुटिपूर्ण हैं। वे अब विरासत हैं, जावा 8 और बाद में निर्मित java.time कक्षाओं द्वारा ली गई। जावा 6 और जावा 7 के लिए, थ्रीटैन-बैकपोर्ट प्रॉजेक्ट में java.time की ज्यादातर कार्यक्षमता बैक- पोर्टेड है । उन विरासत वर्गों का उपयोग करने की तुलना में उस लाइब्रेरी को अपने ऐप में जोड़ना बेहतर है। Java.time में एक-लाइन समाधान:OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" )
तुलसी बॉर्क

5

मैंने उसी समस्या का सामना किया और इसे निम्न कोड द्वारा हल किया।

 public static Calendar getCalendarFromISO(String datestring) {
    Calendar calendar = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()) ;
    SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
    try {
        Date date = dateformat.parse(datestring);
        date.setHours(date.getHours() - 1);
        calendar.setTime(date);

        String test = dateformat.format(calendar.getTime());
        Log.e("TEST_TIME", test);

    } catch (ParseException e) {
        e.printStackTrace();
    }

    return calendar;
}

पहले मैं उपयोग कर रहा था SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());

लेकिन बाद में मुझे अपवाद का मुख्य कारण मिला yyyy-MM-dd'T'HH:mm:ss.SSSZ,

तो मैंने इस्तेमाल किया

SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());

इसने मेरे लिए अच्छा काम किया ।


बस मुझे जोडा-टाइम, एक्सएमएल एपीआई या कुछ और का उपयोग किए बिना आवश्यक था। बस सही पैटर्न।
फिलिप गियोसेफी 20

4

इसके अलावा आप निम्न वर्ग का उपयोग कर सकते हैं -

org.springframework.extensions.surf.util.ISO8601DateFormat


Date date = ISO8601DateFormat.parse("date in iso8601");

जावा डॉक से लिंक - पैकेज के लिए पदानुक्रम। org.springframework.extensions.surf.maven.plugin.util


पदावनत: इसके बजाय com.fasterxml.jackson.databind.util.StdDateFormat का उपयोग करें
vesion

4

जावा के पास एक दर्जन अलग-अलग तरीके हैं, एक तिथि-समय पार्स करने के लिए, जैसा कि उत्कृष्ट उत्तर यहां प्रदर्शित करता है। लेकिन कुछ हद तक आश्चर्यजनक है कि जावा का कोई भी वर्ग पूरी तरह से आईएसओ 8601 को लागू नहीं करता है!

जावा 8 के साथ, मैं सुझाऊंगा:

ZonedDateTime zp = ZonedDateTime.parse(string);
Date date = Date.from(zp.toInstant());

यह यूटीसी में और ऑफ़सेट के साथ "2017-09-13T10: 36: 40Z" या "2017-09-13T10: 36: 40: 40 + 01: 00" जैसे उदाहरणों को संभालेगा। यह ज्यादातर उपयोग के मामलों के लिए करेगा।

लेकिन ऐसा लगता है जैसे उदाहरण संभाल लेंगे नहीं "2017-09-13T10: 36: 40 + 01" है, जो है एक मान्य ISO 8601 दिनांक समय।
यह भी केवल दिनांक को प्रबंधित नहीं करेगा, उदाहरण के लिए "2017-09-13"।

यदि आपको उन को संभालना है, तो मैं सिंटैक्स को सूँघने के लिए पहले एक रेगेक्स का उपयोग करने का सुझाव दूंगा।

कोने के बहुत से मामलों के साथ यहाँ ISO 8601 उदाहरणों की एक अच्छी सूची है: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ मैं किसी भी जावा वर्ग के बारे में पता नहीं है जो उन सभी के साथ सामना कर सकता है।


OffsetDateTimeकरेगा और वैचारिक रूप से एक बेहतर ऑफसेट के साथ एक तिथि-समय मेल खाता है।
ओले वीवी

अरे @ OleV.V सलाह के लिये धन्यवाद। अफसोस की बात है: OffsetDateTime.parse () कई वैध आईएसओ 8601 तार के लिए एक अपवाद फेंक देगा, उदाहरण के लिए "2017-09-13T10: 36: 40 + 01" या "2017-09-13"
डैनियल

मेरा कहने का मतलब सिर्फ इतना था OffsetDateTimeकि आप उन उदाहरणों को संभालते हैं जिन्हें आप संभालते हैं ZonedDateTime। मेरा मानना ​​है कि यह किसी भी उदाहरण को नहीं संभालता है जो ZonedDateTimeनहीं करता है। इस अर्थ में यह कोई सुधार नहीं है (लेकिन इससे भी बुरा नहीं)। क्षमा करें, मैं पूरी तरह से स्पष्ट नहीं था।
ओले वीवी

1
चीजों की स्थिति को देखते हुए इसे 2020 में स्वीकार किया जाना चाहिए।
स्लैश कोडर

3

Apache Jackrabbit तारीखों को जारी रखने के लिए ISO 8601 प्रारूप का उपयोग करता है, और उन्हें पार्स करने के लिए एक सहायक वर्ग है:

org.apache.jackrabbit.util.ISO8601

जैकबबिट-जेसीआर-कॉमन्स के साथ आता है ।


जबकि जैकबबिट का सबसेट काम कर सकता है, यह एक पूर्ण उद्देश्य से निर्मित पुस्तकालय का उपयोग करने के लिए अधिक समझ में आता है। जावा में जिसका अर्थ है या तो जोडा-टाइम या जावा.टाइम।
तुलसी बोर्क

3

जैसा कि दूसरों ने उल्लेख किया है कि एसडीके में शामिल वर्गों का उपयोग करके आईएसओ 8601 तिथियों को पार्स करने / स्वरूपण का समर्थन करने का एक अच्छा तरीका नहीं है। मैंने इस कोड को कई बार लिखा है इसलिए मैंने आखिरकार एक Gist बनाया जिसमें एक DateUtils वर्ग शामिल है जो ISO 8601 और RFC 1123 तिथियों को प्रारूपण और पार्स करने का समर्थन करता है। जिस्ट में एक परीक्षण मामला भी शामिल है जो यह दर्शाता है कि यह किसका समर्थन करता है।

https://gist.github.com/mraccola/702330625fad8eebe7d3


2

SimpleDateFormat JAVA 1.7 के लिए आईएसओ 8601 प्रारूप के लिए एक शांत पैटर्न है।

कक्षा SimpleDateFormat

मैंने जो किया था यह रहा:

Date d = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
         Locale.ENGLISH).format(System.currentTimeMillis());

2
Zप्रारूप स्ट्रिंग में आईएसओ 8601 समय क्षेत्र नहीं है, यदि आप आईएसओ 8601 समय क्षेत्र चाहते हैं X( XXया XXX) का उपयोग करना चाहिए
योजना

d टाइप स्ट्रिंग का है
टिम चाइल्ड

1

इसको ऐसे करो:

public static void main(String[] args) throws ParseException {

    String dateStr = "2016-10-19T14:15:36+08:00";
    Date date = javax.xml.bind.DatatypeConverter.parseDateTime(dateStr).getTime();

    System.out.println(date);

}

यहाँ उत्पादन है:

बुध अक्टूबर 19 15:15:36 सीएसटी 2016


1

जैसे स्ट्रिंग का उपयोग करें LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)


1

मुझे आश्चर्य है कि एक भी जावा लाइब्रेरी https://en.wikipedia.org/wiki/ISO_8601 के अनुसार सभी आईएसओ 8601 तिथि प्रारूपों का समर्थन नहीं करती है । जोडा डेटटाइम उनमें से अधिकांश का समर्थन कर रहा था, लेकिन सभी नहीं और इसलिए मैंने उन सभी को संभालने के लिए कस्टम लॉजिक जोड़ा। यहाँ मेरा कार्यान्वयन है।

import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;

public class ISO8601DateUtils {
	
	/**
	 * It parses all the date time formats from https://en.wikipedia.org/wiki/ISO_8601 and returns Joda DateTime.
	 * Zoda DateTime does not support dates of format 20190531T160233Z, and hence added custom logic to handle this using SimpleDateFormat.
	 * @param dateTimeString ISO 8601 date time string
	 * @return
	 */
	public static DateTime parse(String dateTimeString) {
		try {
			return new DateTime( dateTimeString );
		} catch(Exception e) {
			try {
				Date dateTime = DateUtils.parseDate(dateTimeString, JODA_NOT_SUPPORTED_ISO_DATES);
				return new DateTime(dateTime.getTime());
			} catch (ParseException e1) {
				throw new RuntimeException(String.format("Date %s could not be parsed to ISO date", dateTimeString));
			}
		}
	}
  
  	private static String[] JODA_NOT_SUPPORTED_ISO_DATES = new String[] {
			// upto millis
			"yyyyMMdd'T'HHmmssSSS'Z'",
			"yyyyMMdd'T'HHmmssSSSZ",
			"yyyyMMdd'T'HHmmssSSSXXX",
			
			"yyyy-MM-dd'T'HHmmssSSS'Z'",
			"yyyy-MM-dd'T'HHmmssSSSZ",
			"yyyy-MM-dd'T'HHmmssSSSXXX",
			
			// upto seconds
			"yyyyMMdd'T'HHmmss'Z'",
			"yyyyMMdd'T'HHmmssZ",
			"yyyyMMdd'T'HHmmssXXX",
			
			"yyyy-MM-dd'T'HHmmss'Z'", 
			"yyyy-MM-dd'T'HHmmssZ",
			"yyyy-MM-dd'T'HHmmssXXX",
			
			// upto minutes
			"yyyyMMdd'T'HHmm'Z'",
			"yyyyMMdd'T'HHmmZ",
			"yyyyMMdd'T'HHmmXXX",

			"yyyy-MM-dd'T'HHmm'Z'",
			"yyyy-MM-dd'T'HHmmZ",
			"yyyy-MM-dd'T'HHmmXXX",
			
			//upto hours is already supported by Joda DateTime
	};
}


1

थोड़ा परीक्षण जो दिखाता है कि ISO8601 में एक तारीख को पार्स कैसे किया जाए और लोकलडेट टाइम डीएसटी को हैंडल नहीं करता है।

 @Test
    public void shouldHandleDaylightSavingTimes() throws ParseException {

        //ISO8601 UTC date format
        SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");

        // 1 hour of difference between 2 dates in UTC happening at the Daylight Saving Time
        Date d1 = utcFormat.parse("2019-10-27T00:30:00.000Z");
        Date d2 = utcFormat.parse("2019-10-27T01:30:00.000Z");

        //Date 2 is before date 2
        Assert.assertTrue(d1.getTime() < d2.getTime());
        // And there is 1 hour difference between the 2 dates
        Assert.assertEquals(1000*60*60, d2.getTime() - d1.getTime());

        //Print the dates in local time
        SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm z Z", Locale.forLanguageTag("fr_CH"));
        localFormat.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));

        //Both dates are at 02h30 local time (because of DST), but one is CEST +0200 and the other CET +0100 (clock goes backwards)
        Assert.assertEquals("2019-10-27 02:30 CEST +0200", localFormat.format(d1));
        Assert.assertEquals("2019-10-27 02:30 CET +0100", localFormat.format(d2));

        //Small test that shows that LocalDateTime does not handle DST (and should not be used for storing timeseries data)
        LocalDateTime ld1 = LocalDateTime.ofInstant(d1.toInstant(), ZoneId.of("Europe/Zurich"));
        LocalDateTime ld2 = LocalDateTime.ofInstant(d2.toInstant(), ZoneId.of("Europe/Zurich"));

        //Note that a localdatetime does not handle DST, therefore the 2 dates are the same
        Assert.assertEquals(ld1, ld2);

        //They both have the following local values
        Assert.assertEquals(2019, ld1.getYear());
        Assert.assertEquals(27, ld1.getDayOfMonth());
        Assert.assertEquals(10, ld1.getMonthValue());
        Assert.assertEquals(2, ld1.getHour());
        Assert.assertEquals(30, ld1.getMinute());
        Assert.assertEquals(0, ld1.getSecond());

    }

3
FYI करें, बहुत परेशान करने वाली तारीख-समय कक्षाएं जैसे कि java.util.Date, java.util.Calendarऔर java.text.SimpleDateFormatअब विरासत है , जावा 8 और बाद में निर्मित java.time कक्षाओं द्वारा ली गई है । ओरेकल द्वारा ट्यूटोरियल देखें ।
तुलसी Bourque

आप सही हैं कि LocalDateTimeगर्मियों के समय (डीएसटी) को नहीं संभालता क्योंकि यह समय क्षेत्र को बिल्कुल भी नहीं संभालता है। उसके लिए हमें चाहिए ZonedDateTime। प्रस्ताव Dateऔर SimpleDateFormatहै - IMHO बुरा।
ओले वीवी

1
वास्तव में ZonedDateTime काम करता है। और java.time.ststant भी DST को संभालने के लिए एक अच्छा विकल्प है। मुझे पता है कि java.util.Date को अपदस्थ किया गया है और इसका उपयोग नहीं किया जाना चाहिए, लेकिन मैं सिर्फ मूल प्रश्न का उत्तर दे रहा था: 8601 में एक स्ट्रिंग को java.util.date में कैसे परिवर्तित किया जाए ...
ddtxra

0

मुझे एक समान आवश्यकता थी: मुझे पहले से सटीक प्रारूप को जानने के बिना किसी भी तारीख ISO8601 अनुरूप पार्स करने में सक्षम होने की आवश्यकता थी, और मुझे एक हल्का समाधान चाहिए था जो एंड्रॉइड पर भी काम करेगा।

जब मैंने अपनी जरूरतों को नजरअंदाज किया तो मैं इस सवाल पर लड़खड़ा गया, और देखा कि AFAIU, कोई भी जवाब पूरी तरह से मेरी जरूरतों के अनुरूप नहीं है। इसलिए मैंने jISO8601 विकसित किया और इसे सेंट्रल पर धकेल दिया।

बस आप में जोड़ें pom.xml:

<dependency>
  <groupId>fr.turri</groupId>
  <artifactId>jISO8601</artifactId>
  <version>0.2</version>
</dependency>

और फिर आप जाने के लिए अच्छे हैं:

import fr.turri.jiso8601.*;
...
Calendar cal = Iso8601Deserializer.toCalendar("1985-03-04");
Date date = Iso8601Deserializer.toDate("1985-03-04T12:34:56Z");

यह मदद की उम्मीद है।


0

इस तरह एक तारीख को प्रारूपित करने के लिए निम्नलिखित ने मेरे लिए जावा 6 आधारित अनुप्रयोग में काम किया। थाइमेलफ परियोजना में एक DateFormatवर्ग JacksonThymeleafISO8601DateFormatहै जो लापता बृहदान्त्र सम्मिलित करता है:

https://github.com/thymeleaf/thymeleaf/blob/40d27f44df7b52eda47d1bc6f1b3012add6098b3/src/main/java/org/thymeleaf/standard/serializer/StandardJavaScriptSerializer.java

मैंने इसका इस्तेमाल ECMAScript तारीख प्रारूप कंपेटिबिलिटी के लिए किया।


-1

बेस फंक्शन सौजन्य: @wrygiel

यह फ़ंक्शन ISO8601 प्रारूप को Java Date में बदल सकता है जो ऑफ़सेट मानों को संभाल सकता है। आईएसओ 8601 की परिभाषा के अनुसार ऑफसेट का विभिन्न स्वरूपों में उल्लेख किया जा सकता है।

±[hh]:[mm]
±[hh][mm]
±[hh]

Eg:  "18:30Z", "22:30+04", "1130-0700", and "15:00-03:30" all mean the same time. - 06:30PM UTC

इस वर्ग में रूपांतरित करने की स्थिर विधियाँ हैं

  • ISO8601 स्ट्रिंग टू डेट (लोकल टाइमज़ोन) ऑब्जेक्ट
  • ISO8601 स्ट्रिंग के लिए दिनांक
  • डेलाइट सेविंग स्वचालित रूप से कैल्क है

नमूना ISO8601 स्ट्रिंग्स

/*       "2013-06-25T14:00:00Z";
         "2013-06-25T140000Z";
         "2013-06-25T14:00:00+04";
         "2013-06-25T14:00:00+0400";
         "2013-06-25T140000+0400";
         "2013-06-25T14:00:00-04";
         "2013-06-25T14:00:00-0400";
         "2013-06-25T140000-0400";*/


public class ISO8601DateFormatter {

private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ");
private static final String UTC_PLUS = "+";
private static final String UTC_MINUS = "-";

public static Date toDate(String iso8601string) throws ParseException {
    iso8601string = iso8601string.trim();
    if(iso8601string.toUpperCase().indexOf("Z")>0){
        iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
    }else if(((iso8601string.indexOf(UTC_PLUS))>0)){
        iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
        iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
    }else if(((iso8601string.indexOf(UTC_MINUS))>0)){
        iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
        iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
    }

    Date date = null;
    if(iso8601string.contains(":"))
        date = DATE_FORMAT_1.parse(iso8601string);
    else{
        date = DATE_FORMAT_2.parse(iso8601string);
    }
    return date;
}

public static String toISO8601String(Date date){
    return DATE_FORMAT_1.format(date);
}

private static String replaceColon(String sourceStr, int offsetIndex){
    if(sourceStr.substring(offsetIndex).contains(":"))
        return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
    return sourceStr;
}

private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar){
    if((sourceStr.length()-1)-sourceStr.indexOf(offsetChar,offsetIndex)<=2)
        return sourceStr + "00";
    return sourceStr;
}

}


2
बाहर देखो - DateFormat और व्युत्पन्न वर्ग संगत नहीं हैं! DATE_FORMAT_1 और DATE_FORMAT_2 जैसी स्थिर SimpleDateFormat ऑब्जेक्ट्स का उपयोग करने का अर्थ है कि ISO8601DateFormatter फ़ंक्शन को कॉल करने वाले कई थ्रेड्स एक ही DateFormat ऑब्जेक्ट को साझा करेंगे। यह डेटफ़ॉर्मट कॉल्स से डेटा भ्रष्टाचार और गलत तारीखों की ओर जाता है। इसे ठीक करने के लिए, आपको बस पैटर्न स्ट्रिंग्स को स्थिर बनाना चाहिए और जब भी आवश्यकता हो, स्थानीय SimpleDateFormat चर बनाएं। यह सुनिश्चित करेगा कि प्रत्येक वस्तु का उपयोग केवल एक थ्रेड द्वारा किया जाता है।
थियो

थ्रेड-सेफ्टी के लिए एक बेहतर फ़िक्स है, इसके बजाय थ्रेड-सेफ्टी के लिए बनी डेट-टाइम लाइब्रेरी का उपयोग करें। जावा में वह दुनिया या तो जोडा-टाइम या जावा हो सकती है।
तुलसी बोर्क

-1

यह मेरे लिए सबसे अच्छा काम करने के लिए लग रहा था:

public static Date fromISO8601_( String string ) {

    try {
            return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ssXXX").parse ( string );
    } catch ( ParseException e ) {
        return Exceptions.handle (Date.class, "Not a valid ISO8601", e);
    }


}

मुझे जावा को / fro जावास्क्रिप्ट तिथि तार में बदलने की आवश्यकता है। मैंने सिफारिश के साथ उपरोक्त कार्यों को पाया। SimpleDateFormat का उपयोग करने वाले कुछ उदाहरण थे जो करीब थे, लेकिन उन्हें उपसमुच्चय के अनुसार अनुशंसित नहीं लगता था:

http://www.w3.org/TR/NOTE-datetime

और पीएलआईएसटी और जावास्क्रिप्ट स्ट्रिंग्स द्वारा समर्थित है और इस तरह जो मुझे चाहिए था।

यह ISO8601 स्ट्रिंग का सबसे सामान्य रूप है, और एक अच्छा सबसेट है।

वे उदाहरण देते हैं:

1994-11-05T08:15:30-05:00 corresponds 
November 5, 1994, 8:15:30 am, US Eastern Standard Time.

 1994-11-05T13:15:30Z corresponds to the same instant.

मेरा एक तेज़ संस्करण भी है:

final static int SHORT_ISO_8601_TIME_LENGTH =  "1994-11-05T08:15:30Z".length ();
                                            // 01234567890123456789012
final static int LONG_ISO_8601_TIME_LENGTH = "1994-11-05T08:15:30-05:00".length ();


public static Date fromISO8601( String string ) {
    if (isISO8601 ( string )) {
        char [] charArray = Reflection.toCharArray ( string );//uses unsafe or string.toCharArray if unsafe is not available
        int year = CharScanner.parseIntFromTo ( charArray, 0, 4 );
        int month = CharScanner.parseIntFromTo ( charArray, 5, 7 );
        int day = CharScanner.parseIntFromTo ( charArray, 8, 10 );
        int hour = CharScanner.parseIntFromTo ( charArray, 11, 13 );

        int minute = CharScanner.parseIntFromTo ( charArray, 14, 16 );

        int second = CharScanner.parseIntFromTo ( charArray, 17, 19 );

        TimeZone tz ;

         if (charArray[19] == 'Z') {

             tz = TimeZone.getTimeZone ( "GMT" );
         } else {

             StringBuilder builder = new StringBuilder ( 9 );
             builder.append ( "GMT" );
             builder.append( charArray, 19, LONG_ISO_8601_TIME_LENGTH - 19);
             String tzStr = builder.toString ();
             tz = TimeZone.getTimeZone ( tzStr ) ;

         }
         return toDate ( tz, year, month, day, hour, minute, second );

    }   else {
        return null;
    }

}

...

public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
    int num = digitChars[ offset ] - '0';
    if ( ++offset < to ) {
        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
        if ( ++offset < to ) {
            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
            if ( ++offset < to ) {
                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                if ( ++offset < to ) {
                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                    if ( ++offset < to ) {
                        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                        if ( ++offset < to ) {
                            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                            if ( ++offset < to ) {
                                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                if ( ++offset < to ) {
                                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return num;
}


public static boolean isISO8601( String string ) {
      boolean valid = true;

      if (string.length () == SHORT_ISO_8601_TIME_LENGTH) {
          valid &=  (string.charAt ( 19 )  == 'Z');

      } else if (string.length () == LONG_ISO_8601_TIME_LENGTH) {
          valid &=  (string.charAt ( 19 )  == '-' || string.charAt ( 19 )  == '+');
          valid &=  (string.charAt ( 22 )  == ':');

      } else {
          return false;
      }

    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
    // "1 9 9 4 - 1 1 - 0 5 T 0 8 : 1 5 : 3 0 - 0 5 : 0 0

    valid &=  (string.charAt ( 4 )  == '-') &&
                (string.charAt ( 7 )  == '-') &&
                (string.charAt ( 10 ) == 'T') &&
                (string.charAt ( 13 ) == ':') &&
                (string.charAt ( 16 ) == ':');

    return valid;
}

मैंने इसे बेंचमार्क नहीं किया है, लेकिन मुझे लगता है कि यह बहुत तेज़ होगा। यह काम करने लगता है। :)

@Test
public void testIsoShortDate() {
    String test =  "1994-11-05T08:15:30Z";

    Date date = Dates.fromISO8601 ( test );
    Date date2 = Dates.fromISO8601_ ( test );

    assertEquals(date2.toString (), date.toString ());

    puts (date);
}

@Test
public void testIsoLongDate() {
    String test =  "1994-11-05T08:11:22-05:00";

    Date date = Dates.fromISO8601 ( test );
    Date date2 = Dates.fromISO8601_ ( test );

    assertEquals(date2.toString (), date.toString ());

    puts (date);
}

-2

मुझे लगता है कि जो लोग बहुत कुछ करना चाहते हैं, वह JSON तारीख के तार हैं। इस पृष्ठ पर आने का एक अच्छा मौका है कि आप जावास्क्रिप्ट JSON दिनांक को जावा तिथि में परिवर्तित करना चाहते हैं।

यह दिखाने के लिए कि JSON दिनांक स्ट्रिंग कैसा दिखता है:

    var d=new Date();
    var s = JSON.stringify(d);

    document.write(s);
    document.write("<br />"+d);


    "2013-12-14T01:55:33.412Z"
    Fri Dec 13 2013 17:55:33 GMT-0800 (PST)

JSON दिनांक स्ट्रिंग 2013-12-14T01: 55: 33.412Z है।

प्रति JSON कल्पना द्वारा तिथियां कवर नहीं की जाती हैं, लेकिन ऊपर एक बहुत विशिष्ट आईएसओ 8601 प्रारूप है, जबकि ISO_8601 बहुत बड़ा है और यह एक बहुत ही महत्वपूर्ण है।

देखें http://www.json.org देखें http://en.wikipedia.org/wiki/ISO_8601 देखें http://www.w3.org/TR/NOTE-datetime

जैसा कि होता है मैंने एक JSON पार्सर और एक PLIST पार्सर लिखा है जिसमें दोनों ISO-8601 का उपयोग करते हैं लेकिन समान बिट्स नहीं।

/*
    var d=new Date();
    var s = JSON.stringify(d);

    document.write(s);
    document.write("<br />"+d);


    "2013-12-14T01:55:33.412Z"
    Fri Dec 13 2013 17:55:33 GMT-0800 (PST)


 */
@Test
public void jsonJavaScriptDate() {
    String test =  "2013-12-14T01:55:33.412Z";

    Date date = Dates.fromJsonDate ( test );
    Date date2 = Dates.fromJsonDate_ ( test );

    assertEquals(date2.toString (), "" + date);

    puts (date);
}

मैंने अपने प्रोजेक्ट के लिए ऐसा करने के दो तरीके लिखे। एक मानक, एक उपवास।

फिर, JSON दिनांक स्ट्रिंग ISO 8601 का एक बहुत ही विशिष्ट कार्यान्वयन है ...।

(मैंने दूसरे उत्तर में एक पोस्ट किया है जो पीएलआईएसटी तारीखों के लिए काम करना चाहिए, जो एक अलग आईएसओ 8601 प्रारूप हैं)।

JSON दिनांक इस प्रकार है:

public static Date fromJsonDate_( String string ) {

    try {

        return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss.SSSXXX").parse ( string );
    } catch ( ParseException e ) {
        return Exceptions.handle (Date.class, "Not a valid JSON date", e);
    }


}

PLIST फाइलें (ASCII non GNUNext) भी ISO 8601 का उपयोग करती हैं, लेकिन कोई भी मिलिसेकंड नहीं होता है ... सभी ISO-8601 तिथियां समान नहीं होती हैं। (कम से कम मुझे अभी तक मिलिस का उपयोग करने वाला एक नहीं मिला है और मैंने जिस पार्सर को टाइमजोन को पूरी तरह से ओएमजी छोड़ते देखा है)।

अब तेज संस्करण के लिए (आप इसे बून में पा सकते हैं)।

public static Date fromJsonDate( String string ) {

    return fromJsonDate ( Reflection.toCharArray ( string ), 0, string.length () );

}

ध्यान दें कि यदि उपलब्ध हो तो Reflection.toCharArray असुरक्षित का उपयोग करता है, लेकिन यदि नहीं तो string.toCharArray में चूक।

(आप इसे Reflection.toCharArray (string) से string.toCharArray ()) के स्थान पर उदाहरण से निकाल सकते हैं।

public static Date fromJsonDate( char[] charArray, int from, int to ) {

    if (isJsonDate ( charArray, from, to )) {
        int year = CharScanner.parseIntFromTo ( charArray, from + 0, from + 4 );
        int month = CharScanner.parseIntFromTo ( charArray,  from +5,  from +7 );
        int day = CharScanner.parseIntFromTo ( charArray,  from +8,  from +10 );
        int hour = CharScanner.parseIntFromTo ( charArray,  from +11,  from +13 );

        int minute = CharScanner.parseIntFromTo ( charArray,  from +14,  from +16 );

        int second = CharScanner.parseIntFromTo ( charArray,  from +17,  from +19 );

        int miliseconds = CharScanner.parseIntFromTo ( charArray,  from +20,  from +23 );

        TimeZone tz = TimeZone.getTimeZone ( "GMT" );


        return toDate ( tz, year, month, day, hour, minute, second, miliseconds );

    }   else {
        return null;
    }

}

IsJsonDate निम्नानुसार कार्यान्वित किया जाता है:

public static boolean isJsonDate( char[] charArray, int start, int to ) {
    boolean valid = true;
    final int length = to -start;

    if (length != JSON_TIME_LENGTH) {
        return false;
    }

    valid &=  (charArray [ start + 19 ]  == '.');

    if (!valid) {
        return false;
    }


    valid &=  (charArray[  start +4 ]  == '-') &&
            (charArray[  start +7 ]  == '-') &&
            (charArray[  start +10 ] == 'T') &&
            (charArray[  start +13 ] == ':') &&
            (charArray[  start +16 ] == ':');

    return valid;
}

वैसे भी ... मेरा अनुमान है कि काफी लोग जो यहां आते हैं .. वे JSON दिनांक स्ट्रिंग की तलाश में हो सकते हैं और यद्यपि यह एक ISO-8601 तारीख है, यह एक बहुत ही विशिष्ट है जिसे बहुत विशिष्ट पार्स की आवश्यकता है।

public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
    int num = digitChars[ offset ] - '0';
    if ( ++offset < to ) {
        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
        if ( ++offset < to ) {
            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
            if ( ++offset < to ) {
                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                if ( ++offset < to ) {
                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                    if ( ++offset < to ) {
                        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                        if ( ++offset < to ) {
                            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                            if ( ++offset < to ) {
                                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                if ( ++offset < to ) {
                                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return num;
}

देखें https://github.com/RichardHightower/boon बून में एक PLIST पार्सर (ASCII) और एक JSON पार्सर है।

JSON पार्सर सबसे तेज़ जावा JSON पार्सर है जिसे मैं जानता हूँ।

स्वतंत्र रूप से गैटलिंग प्रदर्शन के दोस्तों द्वारा सत्यापित।

https://github.com/gatling/json-parsers-benchmark

Benchmark                               Mode Thr     Count  Sec         Mean   Mean error        Units
BoonCharArrayBenchmark.roundRobin      thrpt  16        10    1   724815,875    54339,825    ops/s
JacksonObjectBenchmark.roundRobin      thrpt  16        10    1   580014,875   145097,700    ops/s
JsonSmartBytesBenchmark.roundRobin     thrpt  16        10    1   575548,435    64202,618    ops/s
JsonSmartStringBenchmark.roundRobin    thrpt  16        10    1   541212,220    45144,815    ops/s
GSONStringBenchmark.roundRobin         thrpt  16        10    1   522947,175    65572,427    ops/s
BoonDirectBytesBenchmark.roundRobin    thrpt  16        10    1   521528,912    41366,197    ops/s
JacksonASTBenchmark.roundRobin         thrpt  16        10    1   512564,205   300704,545    ops/s
GSONReaderBenchmark.roundRobin         thrpt  16        10    1   446322,220    41327,496    ops/s
JsonSmartStreamBenchmark.roundRobin    thrpt  16        10    1   276399,298   130055,340    ops/s
JsonSmartReaderBenchmark.roundRobin    thrpt  16        10    1    86789,825    17690,031    ops/s

इसमें स्ट्रीम, रीडर, बाइट्स [], चार [], चारसेंसेंस (StringBuilder, CharacterBuffer), और स्ट्रिंग के लिए सबसे तेज JSON पार्सर है।

अधिक बेंचमार्क यहां देखें:

https://github.com/RichardHightower/json-parsers-benchmark


JSON के बारे में यह उत्तर प्रश्न से ऑफ-टॉपिक है। इसके अलावा, यह प्रश्न गलत है क्योंकि बहुत कम JSON डेटा प्रकारों में "JSON दिनांक" जैसी कोई चीज नहीं है । और आजकल, इस सभी कोड को सिंगल-लाइन कॉल के साथ बिल्ट-इन जावा फीचर में बदला जा सकता है:Instant.parse( "2013-12-14T01:55:33.412Z" )
बेसिल बोर्के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.