4

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"
   }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
SwiftCODA
  • 172
  • 2
  • 16

2 Answers2

9

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.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I've seen people suggest also setting `formatter.calendar = Calendar(identifier: .iso8601)`, but in my experience, setting the `locale` is sufficient. – Rob Feb 04 '22 at 23:32
  • Thanks for your answer, Rob. What is actually happening that causes a German device to have an issue parsing an iso8601 date in UTC? – SwiftCODA Feb 05 '22 at 05:30
  • 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. – Larme Feb 05 '22 at 08:32
  • @Larme Just confirmed the device was in 12h time and mine is too so I'm not really sure? – SwiftCODA Feb 06 '22 at 08:14
  • 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. – Larme Feb 06 '22 at 08:50
  • I will test it out when I talk to this person on Tuesday and mark as correct if all works out. @Larme – SwiftCODA Feb 06 '22 at 08:59
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!")
 }