मुझे iOS पर ISO 8601 की तारीख कैसे मिलेगी?


115

2004-02-12T15:19:21+00:00PHP के माध्यम से PHP में ISO 8601 डेट स्ट्रिंग (उदाहरण के लिए ) प्राप्त करना काफी आसान है date('c'), लेकिन कोई इसे Objective-C (iPhone) में कैसे प्राप्त कर सकता है? क्या ऐसा करने का कोई छोटा तरीका है?

यहाँ मुझे ऐसा करने का लंबा समय मिला है:

NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";

NSDate *now = [NSDate date];
NSString *formattedDateString = [dateFormatter stringFromDate:now];
NSLog(@"ISO-8601 date: %@", formattedDateString);

// Output: ISO-8601 date: 2013-04-27T13:27:50-0700

ऐसा लगता है कि कुछ बहुत केंद्रीय के लिए एक बहुत कठोर कठोरता है।


1
मुझे लगता है कि देखने वाले की नजर में कमी है। कोड की तीन लाइनें बहुत कम हैं, नहीं? एक सी NSDate उपवर्ग है जिसे आप जोड़ सकते हैं कि यह एक पंक्ति के साथ करेगा, मैं अभी इस पर ट्रिप कर रहा हूं: github.com/soffes/SAMCategories/tree/master/SAMCategories/… । उस ने कहा, वास्तव में, आपको बहुत अच्छे उत्तर मिले हैं (IMHO) और आपको एटिने को पुरस्कृत करना चाहिए या उत्तर को कठोर करना चाहिए। इसका सिर्फ अच्छा अभ्यास और वास्तविक सहायक जानकारी प्रदान करने वाले लोगों को पुरस्कार देता है (इससे मुझे मदद मिली, मुझे आज इस जानकारी की आवश्यकता है)। एटीन रेमडी से अधिक अंक का उपयोग कर सकता था। अच्छे उपाय के संकेत के रूप में मैं आपके प्रश्न को वोट करूँगा!
डेविड एच

जवाबों:


212

उपयोग करें NSDateFormatter:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];   
NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
[dateFormatter setCalendar:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]];

NSDate *now = [NSDate date];
NSString *iso8601String = [dateFormatter stringFromDate:now];

और स्विफ्ट में:

let dateFormatter = DateFormatter()
let enUSPosixLocale = Locale(identifier: "en_US_POSIX")
dateFormatter.locale = enUSPosixLocale
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
dateFormatter.calendar = Calendar(identifier: .gregorian)

let iso8601String = dateFormatter.string(from: Date())

1
धन्यवाद, मैडी। मैंने अपना कोड पोस्ट करने के बाद, मैंने अभी आपका उत्तर देखा। है setLocaleमहत्वपूर्ण है?
जॉन्स

2
@rmaddy आप केवल ZZZZZ का उपयोग करने के लिए अपने उदाहरण को संपादित कर सकते हैं ताकि लोग कॉपी-पेस्ट करने से जल न जाएं।
जेसी रस्क

4
@jlmendezbonini No. यह बहुत दुर्लभ है जो आप चाहते हैं YYYY। आप आमतौर पर yyyy चाहते हैं।
रामपाल

7
स्रोत क्यों लोकेल को en_US_POSIX पर सेट किया जाना चाहिए: developer.apple.com/library/mac/qa/qa1480/_index.html
yood

11
@ कामेडी - इसे Google के माध्यम से खोजने वाले अन्य लोगों के लिए खोज करना आसान बनाना चाहता था और आपको वास्तव में सही प्रारूप, लोकल इत्यादि को खोदने का श्रेय देना चाहता था, लेकिन अगर आप चाहें तो इसे एक अलग उत्तर के रूप में पोस्ट करने के लिए खुश हैं
रॉबिन

60

iOS 10 ने NSISO8601DateFormatterइसे संभालने के लिए एक नई क्लास शुरू की । यदि आप स्विफ्ट 3 का उपयोग कर रहे हैं, तो आपका कोड कुछ इस तरह होगा:

let formatter = ISO8601DateFormatter()
let date = formatter.date(from: "2016-08-26T12:39:00Z")
let string = formatter.string(from: Date())

और यह क्या प्रारूप देता है? इसके अलावा यह जानना अच्छा होगा कि क्या यह इससे निपट सकता है: 2016-08-26T12: 39: 00-0000 और 2016-08-26T12: 39: 00-00: 00 और 2016-08-26T12: 39: 00.374-0000
मल्हल

1
मेरे जवाब में तीन पंक्तियों के चलने के बाद, string"2016-09-03T21: 47: 27Z" शामिल है।
21

3
आप इस प्रारूप के साथ मिलीसेकंड को संभाल नहीं सकते
Enrique

3
@Enrique: आप NSISO8601DateFormatWithFractionalSeconds को मिलाने के विकल्प के रूप में मिलिसेकंड के साथ काम करने में सक्षम होने के लिए डॉक्स की जाँच करें।
पाकिटो वीवी

1
NSISO8601DateFormatWithFractionalSeconds केवल 11.2+ पर काम करता है। नहीं तो आप दुर्घटनाग्रस्त हो गए!
हैश 3r

27

मैडी के उत्तर के पूरक के रूप में, आईएसओ 8601 के लिए एकल "जेड" (जो कि आरएफसी 822 प्रारूप के लिए है) के लिए समय क्षेत्र प्रारूप "ZZZZZ" (5 गुना Z) होना चाहिए। कम से कम iOS 6 पर।

(देखें http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns )


शानदार कैच! किसी और को इसमें दिलचस्पी है, लिंक पर जाएं, 8601 की खोज करें आप इसे देखेंगे।
डेविड एच

जब दिनांक पर समय क्षेत्र UTC है, क्या कोई ऐसा तरीका है जिससे आप Z के बजाय 00:00 दिखा सकते हैं (जो कि समतुल्य है)?
शिम

बहुत बहुत धन्यवाद;) मेरे सिर को दीवार से टकरा रहा था और एक डेटफॉर्मेटर के साथ निल डेट लौट रहा था !!! :)
पोलो 987

19

एक अक्सर अनदेखा मुद्दा यह है कि आईएसओ 8601 प्रारूप में तार मिलिसेकंड हो सकते हैं और नहीं हो सकते हैं।

दूसरे शब्दों में, "2016-12-31T23: 59: 59.9999999" और "2016-12-01T00: 00: 00" दोनों वैध हैं, लेकिन यदि आप स्थैतिक-टाइप किए गए दिनांक फ़ॉर्मेटर का उपयोग कर रहे हैं, तो उनमें से एक को पार्स नहीं किया जाएगा। ।

IOS 10 से शुरू होकर आपको ऐसे उपयोग करने चाहिए ISO8601DateFormatterजो ISO 8601 डेट स्ट्रिंग्स के सभी विविधताओं को संभालते हैं। नीचे उदाहरण देखें:

let date = Date()
var string: String

let formatter = ISO8601DateFormatter()
string = formatter.string(from: date)

let GMT = TimeZone(abbreviation: "GMT")
let options: ISO8601DateFormatOptions = [.withInternetDateTime, .withDashSeparatorInDate, .withColonSeparatorInTime, .withTimeZone]
string = ISO8601DateFormatter.string(from: date, timeZone: GMT, formatOptions: options)

के लिए आईओएस 9 और नीचे उपयोग एक से अधिक डेटा formatters साथ निम्नलिखित दृष्टिकोण।

मुझे ऐसा उत्तर नहीं मिला है जो इस सूक्ष्म अंतर को दूर करता हो। इसका समाधान यहां दिया गया है:

extension DateFormatter {

    static let iso8601DateFormatter: DateFormatter = {
        let enUSPOSIXLocale = Locale(identifier: "en_US_POSIX")
        let iso8601DateFormatter = DateFormatter()
        iso8601DateFormatter.locale = enUSPOSIXLocale
        iso8601DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
        iso8601DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
        return iso8601DateFormatter
    }()

    static let iso8601WithoutMillisecondsDateFormatter: DateFormatter = {
        let enUSPOSIXLocale = Locale(identifier: "en_US_POSIX")
        let iso8601DateFormatter = DateFormatter()
        iso8601DateFormatter.locale = enUSPOSIXLocale
        iso8601DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
        iso8601DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
        return iso8601DateFormatter
    }()

    static func date(fromISO8601String string: String) -> Date? {
        if let dateWithMilliseconds = iso8601DateFormatter.date(from: string) {
            return dateWithMilliseconds
        }

        if let dateWithoutMilliseconds = iso8601WithoutMillisecondsDateFormatter.date(from: string) {
            return dateWithoutMilliseconds
        }

        return nil
    }
}

उपयोग:

let dateToString = "2016-12-31T23:59:59.9999999"
let dateTo = DateFormatter.date(fromISO8601String: dateToString)
// dateTo: 2016-12-31 23:59:59 +0000

let dateFromString = "2016-12-01T00:00:00"
let dateFrom = DateFormatter.date(fromISO8601String: dateFromString)
// dateFrom: 2016-12-01 00:00:00 +0000

मैं तारीख के स्वरूपकों के बारे में Apple लेख की जाँच करने की भी सलाह देता हूँ ।


क्या आप यह भी बता सकते हैं कि ओबीज-सी में NSISO8601DateFormtter की पकड़ कैसे हो? (iOS 10 और इसके बाद के संस्करण पर)
Motti Shneor

8

इसलिए यहाँ पाए जाने वाले NSDate पर सैम सोफ़ी की श्रेणी का उपयोग करें । अपनी परियोजना में उस कोड को जोड़ने के साथ, आप तब से NSDate पर एकल विधि का उपयोग कर सकते हैं:

- (NSString *)sam_ISO8601String

न केवल यह एक पंक्ति है, NSDateFormatter दृष्टिकोण की तुलना में बहुत तेज है, क्योंकि यह शुद्ध C में लिखा गया है।


1
श्रेणी का वर्तमान स्थान यहाँ है
पेरी

1
मैं इसके खिलाफ सलाह
दूंगा

1
@M_Waly तुमने उसे यह रिपोर्ट दी? मैंने बिना किसी चेतावनियों के उसका कोड बनाया और यह ठीक-ठीक विश्लेषण की जाँच में पास हुआ।
डेविड एच।

6

से IS8601 , समस्याओं प्रतिनिधित्व और समय क्षेत्र हैं

  • आईएसओ 8601 = year-month-day time timezone
  • दिनांक और समय के लिए, बुनियादी (YYYYMMDD, hhmmss, ...) और विस्तारित प्रारूप (YYYY-MM-DD, hh: mm: ss, ...) हैं।
  • समय क्षेत्र ज़ुलु, ऑफसेट या जीएमटी हो सकता है
  • दिनांक और समय के लिए विभाजक स्थान हो सकता है, या T
  • तारीख के लिए सप्ताह के प्रारूप हैं, लेकिन इसका उपयोग शायद ही कभी किया जाता है
  • टाइमज़ोन के बाद बहुत सारे स्थान हो सकते हैं
  • दूसरा वैकल्पिक है

यहाँ कुछ मान्य तार हैं

2016-04-08T10:25:30Z
2016-04-08 11:25:30+0100
2016-04-08 202530GMT+1000
20160408 08:25:30-02:00
2016-04-08 11:25:30     +0100

समाधान

  • चरण दर चरण पार्स करें, जैसे कि आईएसओ 860101
  • बुनियादी प्रारूप में कनवर्ट करें, जैसे onmyway133 ISO8601

NSDateFormatter

तो यहाँ प्रारूप है कि मैं onmyway133 ISO8601 में उपयोग कर रहा हूँ

let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyyMMdd HHmmssZ"

बारे में Zपहचानकर्ता तिथि फील्ड प्रतीक तालिका

Z: The ISO8601 basic format with hours, minutes and optional seconds fields. The format is equivalent to RFC 822 zone format (when optional seconds field is absent)

स्थानीय सेटिंग का उपयोग करके डेटा स्वरूपण के बारे मेंlocale

स्थान विशेष उपयोगकर्ता के लिए प्रारूपण विकल्पों का प्रतिनिधित्व करते हैं, उपयोगकर्ता की पसंदीदा भाषा के नहीं। ये अक्सर समान होते हैं लेकिन अलग-अलग हो सकते हैं। उदाहरण के लिए, एक मूल अंग्रेजी वक्ता जो जर्मनी में रहता है, वह भाषा को भाषा और जर्मनी को क्षेत्र के रूप में चुन सकता है

तकनीकी प्रश्नोत्तर के बारे में en_US_POSIX QA1480 NSDateFormatter and Internet Dates

दूसरी ओर, यदि आप निश्चित-प्रारूप की तारीखों के साथ काम कर रहे हैं, तो आपको पहले से तारीख स्वरूप के स्थान को किसी निश्चित प्रारूप के लिए उपयुक्त होना चाहिए। ज्यादातर मामलों में चुनने के लिए सबसे अच्छा लोकेल "en_US_POSIX" है, एक ऐसा लोकेल जो विशेष रूप से उपयोगकर्ता और सिस्टम वरीयताओं दोनों की परवाह किए बिना अमेरिकी अंग्रेजी परिणाम प्राप्त करने के लिए डिज़ाइन किया गया है। "en_US_POSIX" समय में भी अपरिवर्तनीय है (यदि अमेरिका, भविष्य में किसी बिंदु पर, जिस तरह से यह दिनांक स्वरूप बदलता है, "en_US" नए व्यवहार को प्रतिबिंबित करने के लिए बदल जाएगा, लेकिन "en_US_POSIX नहीं होगा), और मशीनों के बीच (और "en_US_POSIX" iOS पर वैसा ही काम करता है जैसा कि वह OS X पर करता है, और जैसा वह अन्य प्लेटफार्मों पर करता है)।

दिलचस्प संबंधित प्रश्न


मैंने सिर्फ 2016-07-23T07: 24: 23Z के साथ प्रयास किया, यह काम नहीं करता है
कामेन

@KamenDobrev आपको "काम नहीं" से क्या मतलब है? मैं सिर्फ आपके उदाहरण को github.com/onmyway133/ISO8601/blob/master/ISO8601Tests/… के
उदाहरणों से जोड़ता हूं


3

इस gist के आधार पर: https://github.com/justinmakaila/NSDate-ISO-8601/blob/master/NSDateISO8601.swift , निम्नलिखित विधि का उपयोग NSDate को ISO 8601 दिनांक स्ट्रिंग में yyyy-MM के प्रारूप में परिवर्तित करने के लिए किया जा सकता है -dd'T'HH: mm: ss.SSSZ

-(NSString *)getISO8601String
    {
        static NSDateFormatter *formatter = nil;
        if (!formatter)
        {
            formatter = [[NSDateFormatter alloc] init];
            [formatter setLocale: [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
            formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"];
            [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS"];

        }
        NSString *iso8601String = [formatter stringFromDate: self];
        return [iso8601String stringByAppendingString: @"Z"];
    }

Sउप-सेकंड के लिए टोपी यहां महत्वपूर्ण थी
मार्क मेयर

ध्यान दें कि यदि आपको 3 S से अधिक की आवश्यकता है तो आप उस तारीख फॉर्मैटर का उपयोग नहीं कर सकते हैं, जिसे मैन्युअल रूप से पार्स करना है।
मल्हल

-1

यह थोड़ा सरल है और UTC में दिनांक डालता है।

extension NSDate
{
    func iso8601() -> String
    {
        let dateFormatter = NSDateFormatter()
        dateFormatter.timeZone = NSTimeZone(name: "UTC")
        let iso8601String = dateFormatter.stringFromDate(NSDate())
        return iso8601String
    }
}

let date = NSDate().iso8601()

-1

स्विफ्ट 3.0 और आईओएस 9.0 का उपयोग करना

extension Date {
    private static let jsonDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(identifier: "UTC")!
        return formatter
    }()

    var IOS8601String: String {
        get {
            return Date.jsonDateFormatter.string(from: self)
        }
    }

    init?(fromIOS8601 dateString: String) {
        if let d = Date.jsonDateFormatter.date(from: dateString) {
            self.init(timeInterval: 0, since:d)
        } else {
            return nil
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.