iOS Swift 3: преобразовать строку формата "yyyy-MM-dd'T'HH: mm: ssZ" на сегодняшний день

Привет, у меня есть словарь

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

в котором я получаю дату " 2017-01-27T18: 36: 36Z ". Я хочу преобразовать его в читаемом формате: dd-MM-yyyy hh: mm: ss. я пробовал через

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

Но ноль. :(

Каков правильный способ получить дату в простом формате?

Ответ 1

Вам нужен формат ввода для преобразования строки ISO8601 в дату и выходной формат для преобразования даты в строку:

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)")

Ответ 2

Чтобы преобразовать строку в объект Date:

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

Или, если вам нужно поддерживать версии iOS, предшествующие 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)!

(Чтобы понять, почему мы установили locale для форматера даты ISO 8601, см. Технический вопрос и ответ Apple 1480.)

Затем, чтобы преобразовать это в удобный формат даты, вы должны использовать отдельный форматер (или использовать второй пример, приведенный выше, вы можете повторно использовать форматер, но не забудьте сбросить locale обратно на Locale.current):

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

Обратите внимание, я бы предложил использовать эти параметры стиля при представлении даты обратно пользователю, а не в строке dateFormat, поэтому в ней используются стили, соответствующие их локали, вместо того, чтобы предполагать, что им нужны 24-часовые часы или нет, и/или используют ли они dd-MM-yyyy против MM-dd-yyyy формат.


Обратите внимание, что изменение форматов форматера даты (например, изменение строки dateFormat) является относительно дорогим процессом, поэтому, если вы выполняете этот процесс для нескольких дат, не берите один DateFormatter и постоянно меняйте его dateFormat или стили многократно назад и вперед (или, что еще хуже, создавать новые средства форматирования для каждой даты). Вместо этого создайте один форматтер для каждого стиля формата даты и максимально используйте его грамматику.