मैं इसे पार्स करने की कोशिश कर रहा हूं

2017-01-23T10:12:31.484Z

iOS 10 द्वारा प्रदान की गई देशी ISO8601DateFormatter कक्षा का उपयोग करना लेकिन हमेशा विफल रहता है। यदि स्ट्रिंग में मिलीसेकंड नहीं है, तो Date ऑब्जेक्ट बिना किसी समस्या के बनाया जाता है।

मैंने यह कोशिश की है और कई options संयोजन लेकिन हमेशा विफल रहता है ...

let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.formatOptions = [.withInternetDateTime, .withDashSeparatorInDate, .withColonSeparatorInTime, .withColonSeparatorInTimeZone, .withFullTime]

कोई विचार? धन्यवाद!

38
mhergon 25 जिंदा 2017, 12:19
1
इसे एक बार देखें stackoverflow.com/questions/28016578/…
 – 
Anbu.Karthik
25 जिंदा 2017, 12:29
हां, मुझे पता है कि dateFormat का उपयोग करना तरीका है, लेकिन मैं आईओएस 10 के मूल वर्ग का उपयोग करना चाहता हूं ... :(
 – 
mhergon
25 जिंदा 2017, 12:37

4 जवाब

सबसे बढ़िया उत्तर

MacOS 10.13 / iOS 11 से पहले ISO8601DateFormatter मिलीसेकंड सहित डेट स्ट्रिंग्स का समर्थन नहीं करता है।

नियमित अभिव्यक्ति के साथ मिलीसेकंड भाग को हटाने के लिए एक समाधान है।

let isoDateString = "2017-01-23T10:12:31.484Z"
let trimmedIsoString = isoDateString.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: trimmedIsoString)

MacOS 10.13+ / iOS 11+ में भिन्नात्मक सेकंड का समर्थन करने के लिए एक नया विकल्प जोड़ा गया है:

static var withFractionalSeconds: ISO8601DateFormatter.Options { get }

let isoDateString = "2017-01-23T10:12:31.484Z"
let formatter = ISO8601DateFormatter()
formatter.formatOptions =  [.withInternetDateTime, .withFractionalSeconds]
let date = formatter.date(from: isoDateString)
73
vadian 12 जिंदा 2019, 17:10
1
वह कब जोड़ा गया था? मैंने लगभग 3 सप्ताह पहले एक रडार फाइल किया था क्योंकि उसमें फ्रैक्शनल सेकंड्स नहीं थे। यह अभी भी दशमलव स्थानों की संख्या का चयन करने की अनुमति नहीं देता है हालांकि :( openradar.appspot. com/radar?id=6095965782016000
 – 
Fogmeister
23 अक्टूबर 2017, 11:46
2
इसे macOS 10.13 / iOS 11 SDK के साथ जोड़ा गया था।
 – 
vadian
23 अक्टूबर 2017, 11:48
नहीं, यह वास्तव में नहीं था। वह 3 हफ्ते पहले नहीं था। बहुत हाल ही में जोड़ा गया होगा। यह 11.0 पर वापस समर्थन कर सकता है लेकिन इसे केवल पिछले कुछ दिनों में जोड़ा जाना चाहिए। मैंने एक सहकर्मी को भी दिखाया कि वह पिछले हफ्ते ही नहीं था। :)
 – 
Fogmeister
23 अक्टूबर 2017, 11:49
11
11.2 तक फ्रैक्शनलसेकंड क्रैश से सावधान रहें। यह 11.2+ . में तय है
 – 
hash3r
11 अप्रैल 2019, 12:41
1
मैं हमारे लिए भी दुर्घटनाग्रस्त हो रहा था, दस्तावेज़ीकरण भ्रामक है, धन्यवाद @ हैश 3 आर
 – 
vauxhall
1 अप्रैल 2020, 18:05

उन लोगों के लिए जो अभी तक iOS 11 पर जाने के लिए तैयार नहीं हैं, आप मिलीसेकंड को संभालने के लिए हमेशा अपना खुद का फॉर्मेटर बना सकते हैं, जैसे:

extension DateFormatter {
    static var iSO8601DateWithMillisec: DateFormatter {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        return dateFormatter
    }
}

उपयोग:

let formater = DateFormatter.iSO8601DateWithMillisec
let date = formater.date(from: "2017-01-23T10:12:31.484Z")!
print(date) // output: 2017-01-23 10:12:31 +0000

इनपुट स्ट्रिंग से मिलीसेकंड को अलग करने के लिए रेगेक्स लिखने से यह थोड़ा अधिक सुरुचिपूर्ण है।

7
Yuchen 4 अगस्त 2019, 23:24

शायद यह थोड़ा अलग प्रारूपों को डीकोड करने में मदद करेगा:

extension JSONDecoder {
    enum DateDecodeError: String, Error {
        case invalidDate
    }

    static var bestDateAttemptDecoder: JSONDecoder {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
            let container = try decoder.singleValueContainer()
            if let dateSecs = try? container.decode(Double.self) {
                return Date(timeIntervalSince1970: dateSecs)
            }

            if let dateSecs = try? container.decode(UInt.self) {
                return Date(timeIntervalSince1970: TimeInterval(dateSecs))
            }

            let dateStr = try container.decode(String.self)
            let isoFormatter = ISO8601DateFormatter()
            isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
            if let date = isoFormatter.date(from: dateStr) {
                return date
            }

            isoFormatter.formatOptions = [.withInternetDateTime ]
            if let date = isoFormatter.date(from: dateStr) {
                return date
            }

            log.warning("Cannot decode date");
            throw DateDecodeError.invalidDate
        })

        return decoder
    }
}

प्रेषक: https://gist.github.com/th3m477/442a0d1da6354dd3b84e3b71df5dca6a

मुझे कुछ महीने पहले इसी मुद्दे का सामना करना पड़ा था। और यहाँ संदर्भ के लिए मेरा समाधान है:

// *****************************************
// MARK: - Formatter extension
// *****************************************
extension Formatter {
    static let iso8601: ISO8601DateFormatter = {
        let formatter = ISO8601DateFormatter()
        formatter.timeZone = TimeZone.current 
        formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
        return formatter
    }()
    static let iso8601NoSecond: ISO8601DateFormatter = {
        let formatter = ISO8601DateFormatter()
        formatter.timeZone = TimeZone.current 
        formatter.formatOptions = [.withInternetDateTime]
        return formatter
    }()
}

// *****************************************
// MARK: - ISO8601 helper
// *****************************************
    func getDateFrom(DateString8601 dateString:String) -> Date?
    {
        if let date = Formatter.iso8601.date(from: dateString)  {
            return date
        }
        if let date = Formatter.iso8601NoSecond.date(from: dateString)  {
            return date
        }
        return nil
    }

// *****************************************
// usage
// *****************************************
    let d = getDateFrom(DateString8601: "2017-01-23T10:12:31.484Z")
    print("2017-01-23T10:12:31.484Z millis= ", d?.timeIntervalSinceReferenceDate)

    let d2 = getDateFrom(DateString8601: "2017-01-23T10:12:31Z")
    print("2017-01-23T10:12:31Z millis= ", d2?.timeIntervalSinceReferenceDate)


// *****************************************
// result
// *****************************************
2017-01-23T10:12:31.484Z millis=  Optional(506859151.48399997)
2017-01-23T10:12:31Z millis=  Optional(506859151.0)
2
Orange 16 अप्रैल 2019, 10:08
formatter.timeZone = TimeZone.current गलत है। आपको क्या लगता है कि Apple ने ISO8601DateFormatter टाइमज़ोन को GMT से शून्य सेकंड में डिफ़ॉल्ट क्यों बनाया?
 – 
Leo Dabus
16 जुलाई 2020, 20:02