10

I'm getting UTC string dates that look like this "2015-10-17T00:00:00.000Z" and want to convert them to an NSDate in this format "October 12th 2015 11:19:12 am"

This is the route that I'm trying but I can't seem to get the right dateFormat.

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = //can't seem to get this right
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let date = dateFormatter.dateFromString("2015-10-17T00:00:00.000Z")
jonv562
  • 293
  • 1
  • 4
  • 23
  • 2
    Possible duplicate of [Converting an ISO 8601 timestamp into an NSDate: How does one deal with the UTC time offset?](http://stackoverflow.com/questions/5185230/converting-an-iso-8601-timestamp-into-an-nsdate-how-does-one-deal-with-the-utc) – Guillaume Algis Nov 02 '15 at 18:27
  • 1
    None of the answers listed there work for me for some reason – jonv562 Nov 02 '15 at 21:49

4 Answers4

22

I think this should work

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let localDate = formatter.date(from: date)
Sourabh Sharma
  • 8,222
  • 5
  • 68
  • 78
ozzyzig
  • 709
  • 8
  • 19
  • 1
    This was part of the answer, but the Date I get back isn't in the right format, but if apply a new format to this NSDate and change it to a string it works formatter.dateFormat = "MMMM d 'at' h:mm a" var dateString = formatter.stringFromDate(localDate!) – jonv562 Nov 02 '15 at 22:00
  • Ok great yes I forgot to say that. Or you could make a new DataFormatter() object to retrieve date in required format. – ozzyzig Nov 02 '15 at 22:12
3

This works for Swift 3.0 and latest Xcode [April 2017]

let dateString = "2017-Jan-01 12:00:00.250"
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-M-dd HH:mm:ss.SSS"
        dateFormatter.locale = Locale.init(identifier: "en_GB")
        let dateObj = dateFormatter.date(from: dateString)

        let date = dateObj
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSXXXXX"
        let currentDateTime = formatter.string(from: date!)
BHUVANESH MOHANKUMAR
  • 2,747
  • 1
  • 33
  • 33
1

Swift 4 code

let dateString = "2015-10-17T00:00:00.000Z"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date = formatter.date(from: dateString)

You can find useful info about date formats here

0

This question is a few years old but let's answer it literally.

First of all DateFormatter doesn't provide a format specifier for an ordinal suffix so we have to write a function

func ordinalSuffix(for day : String) -> String {
    switch day {
        case "1", "11", "21", "31": return "st"
        case "2", "12", "22": return "nd"
        case "3", "13", "23": return "rd"
        default: return "th"
    }
}

To convert the iso8601 string to date create a DateFormatter, set its calendar to an iso8601 calendar and convert the string to Date. As the time zone is specified in the string you don't need to set it explicitly

let dateString = "2015-10-17T00:00:00.000Z"
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
guard let date = formatter.date(from: dateString) else {
    // replace that with a proper error handling
    fatalError("Could not convert date string")
}

To convert the date back to string you have to set the Locale to a fixed value, set the am/pm symbols to the lowercase versions, extract the day component first for the ordinal suffix calculation and then take advantage of String(format to insert the ordinal suffix.

formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.amSymbol = "am"
formatter.pmSymbol = "pm"
formatter.dateFormat = "dd"
let day = formatter.string(from: date)
formatter.dateFormat = "MMMM dd'%@' yyyy h:mm:ss a"
let output = String(format: formatter.string(from: date), ordinalSuffix(for: day))
print(output)
vadian
  • 274,689
  • 30
  • 353
  • 361