Как сгенерировать метку даты и времени, используя стандарты формата ISO 8601 и RFC 3339 ?
Цель - строка, которая выглядит следующим образом:
"2015-01-01T00:00:00.000Z"
Формат:
- год, месяц, день, как "XXXX-XX-XX"
- буква "Т" в качестве разделителя
- часы, минуты, секунды, миллисекунды, как "XX: XX: XX.XXX".
- буква «Z» в качестве обозначения зоны для смещения нуля, также известного как UTC, GMT, Zulu time.
Лучший случай:
- Быстрый исходный код, который прост, короток и понятен.
- Нет необходимости использовать какие-либо дополнительные фреймворки, подпроекты, cocoapod, C-код и т. Д.
Я искал StackOverflow, Google, Apple и т. Д. И не нашел ответа Swift на это.
Классы , которые кажутся наиболее перспективными являются NSDate
, NSDateFormatter
, NSTimeZone
.
Вопросы и ответы по теме: Как получить дату ISO 8601 в iOS?
Вот лучшее, что я придумал до сих пор:
var now = NSDate()
var formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
println(formatter.stringFromDate(now))
Ответы:
Swift 4 • iOS 11.2.1 или более поздняя версия
Использование:
iOS 9 • Swift 3 или более поздняя версия
и стратегия кодирования
Тестирование детской площадки
кодирование
декодирование
источник
extension String { var dateFormattedISO8601: NSDate? {return NSDate.Date.formatterISO8601.dateFromString(self)} }
let now = NSDate() let stringFromDate = now.iso8601 let dateFromString = stringFromDate.dateFromISO8601! XCTAssertEqual(now.timeIntervalSince1970, dateFromString.timeIntervalSince1970)
ISO8601DateFormatter
упрощает процесс. Я выпустил отчет об ошибке (27242248) для Apple, попросив их расширить этот новый форматер, чтобы также предлагать возможность указывать миллисекунды (поскольку этот новый форматер не используется для многих из нас без миллисекунд).T
например:2016-09-21 21:05:10+00:00
?Не забудьте установить язык,
en_US_POSIX
как описано в Технических вопросах и ответах A1480 . В Swift 3:Проблема в том , что если вы на устройстве , которое используется не григорианский календарь, год не будет соответствовать RFC3339 / ISO8601 , если не указать
locale
, а такжеtimeZone
иdateFormat
строка.Или вы можете использовать,
ISO8601DateFormatter
чтобы вытащить вас из сорняков сеттингаlocale
иtimeZone
себя:Для воспроизведения Swift 2 см. Предыдущую редакцию этого ответа .
источник
en_US_POSIX
. Это лингва франка для обмена датами в Интернете. И вы не можете неправильно интерпретировать даты, если один календарь использовался на устройстве при сохранении строки даты, а другой - при последующем считывании строки. Кроме того, вам нужен формат, который гарантированно никогда не изменится (именно поэтому вы используетеen_US_POSIX
и неen_US
). См. Технические вопросы и ответы 1480 или эти стандарты RFC / ISO для получения дополнительной информации.Если вы хотите использовать
ISO8601DateFormatter()
с датой из фида Rails 4+ JSON (и, конечно, не нуждаетесь в миллисекундах), вам нужно установить несколько параметров для форматера, чтобы он работал правильно, иначеdate(from: string)
функция вернет nil. Вот что я использую:Вот результат использования стихов опций, которых нет на скриншоте детской площадки:
источник
.withFractionalSeconds
но я уже пробовал это, и он продолжает выдавать ошибкуlibc++abi.dylib: terminating with uncaught exception of type NSException
..deferredToDate
при использовании протокола CodableSwift 5
Если вы ориентируетесь IOS 11.0+ / MacOS 10.13+, вы просто использовать
ISO8601DateFormatter
сwithInternetDateTime
иwithFractionalSeconds
опциями, например , так:источник
Используется
ISO8601DateFormatter
на iOS10 или новее.Используется
DateFormatter
на iOS9 или старше.Swift 4
источник
Чтобы еще больше поблагодарить Андреса Торреса Маррокина и Лео Дабуса, у меня есть версия, которая сохраняет доли секунды. Я не могу найти это нигде, но Apple усекает доли секунды до микросекунды (3 цифры точности) как на входе, так и на выходе (даже если это указано с помощью SSSSSSS, в отличие от Unicode tr35-31 ).
Я должен подчеркнуть, что это, вероятно, не является необходимым для большинства случаев использования . Онлайн-даты, как правило, не нуждаются в точности в миллисекундах, и когда они это делают, часто лучше использовать другой формат данных. Но иногда нужно взаимодействовать с уже существующей системой определенным образом.
Xcode 8/9 и Swift 3.0-3.2
источник
В моем случае мне нужно преобразовать столбец DynamoDB - lastUpdated (Unix Timestamp) в обычное время.
Начальное значение lastUpdated было: 1460650607601 - преобразовано в 2016-04-14 16:16:47 +0000 через:
источник
В будущем, возможно, потребуется изменить формат, что может быть небольшой головной болью с вызовом date.dateFromISO8601 повсюду в приложении. Используйте класс и протокол, чтобы обернуть реализацию, изменение вызова формата даты и времени в одном месте будет проще. Если возможно, используйте RFC3339, это более полное представление. DateFormatProtocol и DateFormat отлично подходят для внедрения зависимостей.
источник
Существует новый
ISO8601DateFormatter
класс, который позволяет вам создать строку с одной строкой. Для обратной совместимости я использовал старую C-библиотеку. Надеюсь это кому-нибудь пригодится.Swift 3.0
источник
Чтобы дополнить версию Leo Dabus, я добавил поддержку проектов, написанных на Swift и Objective-C, а также добавил поддержку дополнительных миллисекунд, вероятно, не самый лучший, но вы бы поняли:
Xcode 8 и Swift 3
источник
Без некоторых ручных строковых масок или TimeFormatters
источник
.iso8601
не будет включать миллисекунды.На основании приемлемого ответа в объектной парадигме
callsite
источник