Date string does not match format expected by formatter
Asked Answered
L

2

6

Was only able to reproduce this issue on a friend's device. The device is from Germany and is set to the German region in Settings. I cannot reproduce on any Canadian devices. Why is it failing when trying to create a Date property from the JSON?

Console:

dataCorrupted(Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "60", intValue: nil), CodingKeys(stringValue: "expiration", intValue: nil)], debugDescription: "Date string does not match format expected by formatter.", underlyingError: nil))

Struct:

struct TokenResponse: Decodable {
    var ticket : String
    var expiration : Date?
    var sessionId: String
}

Inside URLSession:

do {
    let decoder = JSONDecoder()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    decoder.dateDecodingStrategy = .formatted(formatter)
    let json = try decoder.decode([String: TokenResponse].self, from: data)
}
catch {
    print(error)
}

JSON:

{
   "60":{
      "ticket":"aVeryLongJWT",
      "expiration":"2022-02-04T22:00:34.8325102Z",
      "sessionId":"aUUID"
   }
}
Ligure answered 4/2, 2022 at 22:30 Comment(5)
Seems to work okay for meDeirdredeism
@Deirdredeism Yes that's the same for me as well. It was just one specific device of someone who lives in Germany that I could reproduce this on.Ligure
We had an issue with a device in the UK which was set to 24 hour time (we were testing 12 hour time) which caused no end of issues 🙄Deirdredeism
I confirmed just now that the device was in 12 hour time. Any ideas? @DeirdredeismLigure
When we had this issue, using formatter.locale = Locale(identifier: "en_US_POSIX") fixed itDeirdredeism
L
10

You should set the locale before setting dateFormat string:

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

See “Working With Fixed Format Date Representations” in DateFormatter documentation.

Laundromat answered 4/2, 2022 at 23:31 Comment(6)
I've seen people suggest also setting formatter.calendar = Calendar(identifier: .iso8601), but in my experience, setting the locale is sufficient.Laundromat
Thanks for your answer, Rob. What is actually happening that causes a German device to have an issue parsing an iso8601 date in UTC?Ligure
If their device is set on showing AM/PM (ie 12h format), that the parsing could fail with HH. You can check on your device by changing that preference, but if I remember well, it's a good reason to fail.Marchal
@Marchal Just confirmed the device was in 12h time and mine is too so I'm not really sure?Ligure
I meant that if you don't put the "en_US_POSIX" and your phone is on &é format (and maybe other settings), then the parsing should failL. So that answer should be the good fix.Marchal
I will test it out when I talk to this person on Tuesday and mark as correct if all works out. @MarchalLigure
T
0

Previous answer is worked for me! You should check the date format coming from server. Mine was different and its case sensitive. I just arranged df.dateFormat Good luck!

private let dateFormatter: DateFormatter = {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "yyyy-MM-dd'T'HH:mm:ss-hh:ss"
        return df
        }()

and then in the dataFetch function

do {
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(self.dateFormatter)
    let results = try! decoder.decode(Model.self, from: data)

    print(results)   
                        
 } catch {
    print("Decoding Error!")
 }
Transience answered 9/1, 2023 at 13:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.