Reputation: 149
I'm trying to decode a date of the format 2019-11-08T01:26:45+00:00
in Swift. Not sure if this is relevant, but it's a String taken from JSON. I've tried using ISO8601DateFormatter
, setting the date format manually, etc., but nothing works.
(response.timestamp
has the value "2019-11-12T21:37:39+00:00"
, taken from JSON.)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
dateFormatter.locale = Locale.current
self.timestamp = dateFormatter.date(from: response.timestamp)
When I build and run the application and set a breakpoint after initializing date
, the value is always nil
.
Upvotes: 0
Views: 409
Reputation: 1
func convertDateString(dateString:String,dateFormat:String = "") -> String {
if dateString.isEmpty {
return ""
}
let dateFormatter = DateFormatter()
let tempLocale = dateFormatter.locale // save locale temporarily
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX en_US_POSIX
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss+s:s"
let date = dateFormatter.date(from: dateString)!
dateFormatter.dateFormat = dateFormat.isEmpty ? "dd-MM-yyyy" : dateFormat
dateFormatter.locale = tempLocale // reset the locale
let dateStr = dateFormatter.string(from: date)
return dateStr
}
usage - your api response date in string format
let time1 = "2019-11-08T01:26:45+00:00"
print(convertDateString(dateString: time1,dateFormat: "EEEE, MMM d, yyyy"))
OUTPUT --->>> Friday, Nov 8, 2019
Upvotes: -1
Reputation: 437632
The key observation is to make sure you’re using en_US_POSIX
as the locale
, as outlined in Working With Fixed Format Date Representations:
let string = "2019-11-12T21:37:39+00:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let date = dateFormatter.date(from: string)
It’s worth noting though, while this formatter will successfully interpret date strings with +00:00
, if and when you convert dates back to strings, it will use the literal Z
common in ISO 8601/RFC 3339 dates, e.g. "2019-11-12T21:37:39Z"
. If you really want your resulting strings (if you’re converting dates to strings at all) to use the +00:00
convention, then you’ll want to use xxxxx
instead of ZZZZZ
. You’ll also want to specify a timeZone
for your formatter, too:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxxxx"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let string = dateFormatter.string(from: date) // "2019-11-12T21:37:39+00:00"
So use ZZZZZ
if you want the standard "2019-11-12T21:37:39Z"
, but use xxxxx
if you want "2019-11-12T21:37:39+00:00"
.
By the way, for more information on all the different permutation of Z
, ZZZZZ
, X
, xxxxx
, etc., see the time zone section of table at Date Format Patterns.
When I build and run the application and set a breakpoint after initializing date, the value is always
nil
.
By the way, always print
(or PO
in lldb) the value. Sometimes the inspector window in Xcode gets out of sync and shows nil
when there really is some value there.
As jms said, if you’re using JSONDecoder
, you probably shouldn’t use date(from:)
or string(from:)
at all. Make your property a Date
type, and then give your decoder a dateDecodingStrategy
:
let json = """
{"date" : "2019-11-12T21:37:39+00:00"}
"""
let data = json.data(using: .utf8)!
struct ResponseObject: Codable {
let date: Date
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
do {
let object = try decoder.decode(ResponseObject.self, from: data)
} catch {
print(error)
}
Upvotes: 2