I'm trying to parse the dates in IAP receipt information.
Apple says they are "in a date-time format similar to the ISO 8601".
However, when I set decoder.dateDecodingStrategy = .iso8601
I get the following decoding error: Expected date string to be ISO8601-formatted.
.
How do you parse these dates?
(No idea why Apple doesn't supply proper ISO 8601 dates.)
You can use a custom formatter for your decoder but you need to decide which version of the date field you want to use since each date is represented in GMT time, PST time and as milliseconds.
"original_purchase_date": "2013-08-01 07:00:00 Etc/GMT",
"original_purchase_date_ms": "1375340400000",
"original_purchase_date_pst": "2013-08-01 00:00:00 America/Los_Angeles",
Below are 3 different solutions but you need to be consequent since you can only use one of them for all dates.
If you want to use the GMT version like original_purchase_date
you can use a date formatter with this format and time zone
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss 'Etc/'zzz"
(Note that I am not sure this is always GMT, I am basing this on a sample receipt but it should work for any proper time zone abbreviation)
or for the PST version, original_purchase_date_pst
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss 'America/Los_Angeles'"
and then use the formatter with your decoder
decoder.dateDecodingStrategy = .formatted(formatter)
You could also use the third option with milliseconds by using the .custom
option for the decoder for the original_purchase_date_ms
variant
struct InvalidTimestampError: Error {}
decoder.dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
guard let value = Double(string) else {
throw InvalidTimestampError()
}
return Date(timeIntervalSince1970: value / 1000)
}