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)