20

Hello i have a dictionary

self.publishedAt = dictionary["publishedAt"] as? NSString

in which i'm getting date "2017-01-27T18:36:36Z". I want to convert it in readable format : dd-MM-yyyy hh:mm:ss. i tried via

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy hh:mm:ss"
let date = dateFormatter.date(from: (self.publishedAt as? String)!)
print("EXACT_DATE : \(date)") 

But getting nil. :(

What is the correct way to get date in simple format?

Abhishek Thapliyal
  • 3,497
  • 6
  • 30
  • 69
  • 1
    You need an **input** format to convert the ISO8601 string to date and an **output** format to convert the date back to string, see also http://stackoverflow.com/questions/33277970/how-to-convert-string-to-date-to-string-in-swift-ios?rq=1, And don't use `NSString` in Swift. – vadian Jan 28 '17 at 07:36

3 Answers3

53

You need an input format to convert the ISO8601 string to date and an output format to convert the date back to string:

let string = "2017-01-27T18:36:36Z"

let dateFormatter = DateFormatter()
let tempLocale = dateFormatter.locale // save locale temporarily
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let date = dateFormatter.date(from: string)!
dateFormatter.dateFormat = "dd-MM-yyyy HH:mm:ss"
dateFormatter.locale = tempLocale // reset the locale
let dateString = dateFormatter.string(from: date)
print("EXACT_DATE : \(dateString)")
vadian
  • 274,689
  • 30
  • 353
  • 361
  • @vadian Why do you reset the locale? – user1960169 Aug 16 '17 at 11:12
  • @user1960169 As mentioned in Rob's answer please read [Apple Technical Q&A 1480](https://developer.apple.com/library/content/qa/qa1480/_index.html) – vadian Aug 16 '17 at 14:52
  • 1
    I'm getting `Thread7: Fatal error: Unexpectedly found nil while unwrapping an Optional Value`. What could be the reason for this? – JkAlombro Jul 14 '18 at 07:27
  • @JkAlombro The string doesn't match the date format. It must be **exactly** the format as in the answer – vadian Jul 14 '18 at 08:00
  • Yeah I just found out that my string has a format of `yyyy-MM-dd'T'HH:mm:ss.sssZ`. Thanks a lot – JkAlombro Jul 14 '18 at 08:03
  • @vadian: Help me https://stackoverflow.com/questions/52741294/ios-dateformatter-giving-nil-when-device-timezone-and-region-changes – Abhishek Thapliyal Oct 10 '18 at 13:48
  • The problem I had was the forced unwrapping login in initializing date. I missed the exclamatory mark. What a silly bug! – Kumar C Oct 22 '20 at 07:53
  • How to convert this? "createdOn": "2021-02-12T00:28:27.8533333" into swift datetime. I tried formatter but it always return fatal error. – SoftSan Dec 07 '22 at 21:35
  • It's without time zone (remove `Z`) but with fractional seconds (add a period and `S`)`"yyyy-MM-dd'T'HH:mm:ss.S"` – vadian Dec 07 '22 at 22:07
  • EXACT_DATE : 28/01/2017 it suppose to get 27/01/2023 – Yalamandarao Jun 21 '23 at 06:29
17

To convert string to Date object:

let string = "2017-01-27T18:36:36Z"
let isoFormatter = ISO8601DateFormatter()
let date = isoFormatter.date(from: string)!

Or, if you need to support iOS versions that predate ISO8601DateFormatter:

let isoFormatter = DateFormatter()
isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
isoFormatter.locale = Locale(identifier: "en_US_POSIX")
isoFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let date = isoFormatter.date(from: string)!

(To understand why we set the locale for the ISO 8601 date formatter, see Apple Technical Q&A 1480.)

Then, to convert that to a user-friendly date format, you'd use a separate formatter (or use the second example, above, you can re-use the formatter, but remember to reset the locale back to Locale.current):

let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .medium
let result = formatter.string(from:date)

Note, I'd suggest using those style parameters when presenting the date back to the user rather than the dateFormat string, so it's using the styles appropriate for their locale, rather than assuming they want 24h clock or not and/or whether they use dd-MM-yyyy vs MM-dd-yyyy format.


Note, changing the formats of date formatter (e.g. changing the dateFormat string) is a relatively expensive process, so if you're performing this process for multiple dates, do not take a single DateFormatter and constantly change its dateFormat or styles repeatedly back and forth (or worse, instantiate new formatters for each date). Instead, create one formatter per date format style and re-use it grammar as much as possible.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
3

Just used the function in your code(swift 4.2).

public func convertDateFormatter(date: String) -> String {

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"//this your string date format
dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
dateFormatter.locale = Locale(identifier: "your_loc_id")
let convertedDate = dateFormatter.date(from: date)

guard dateFormatter.date(from: date) != nil else {
    assert(false, "no date from string")
    return ""
}
dateFormatter.dateFormat = "HH:mm a"///this is what you want to convert format
dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
let timeStamp = dateFormatter.string(from: convertedDate!)
print(timeStamp)
return timeStamp
}

Thanks

Nil Rathod
  • 450
  • 5
  • 21