Como gerar um carimbo de data e hora, usando os padrões de formato para ISO 8601 e RFC 3339 ?
O objetivo é uma sequência que se parece com isso:
"2015-01-01T00:00:00.000Z"
Formato:
- ano, mês, dia, como "XXXX-XX-XX"
- a letra "T" como separador
- hora, minuto, segundos, milissegundos, como "XX: XX: XX.XXX".
- a letra "Z" como um designador de zona para deslocamento zero, também conhecido como UTC, GMT, hora do Zulu.
Melhor caso:
- Código-fonte rápido, simples, curto e direto.
- Não é necessário usar nenhuma estrutura adicional, subprojeto, cocoapod, código C, etc.
Pesquisei StackOverflow, Google, Apple, etc. e não encontrei uma resposta rápida para isso.
As classes que parecem mais promissores são NSDate
, NSDateFormatter
, NSTimeZone
.
Perguntas e respostas relacionadas: Como obtenho a data ISO 8601 no iOS?
Aqui está o melhor que eu criei até agora:
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))
Respostas:
Swift 4 • iOS 11.2.1 ou posterior
Uso:
iOS 9 • Swift 3 ou posterior
e a estratégia de codificação
Teste de Playground
codificação
decodificação
fonte
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
simplifica o processo. Emiti um relatório de bug (27242248) à Apple, solicitando que eles expandissem esse novo formatador para oferecer a capacidade de especificar milissegundos também (já que esse novo formatador não é útil para muitos de nós sem os milissegundos).T
por exemplo2016-09-21 21:05:10+00:00
:?Lembre-se de definir o código do idioma para
en_US_POSIX
código como descrito nas Perguntas e Respostas Técnicas A1480 . No Swift 3:A questão é que se você estiver em um dispositivo que está usando um calendário não gregoriano, o ano não estará de acordo com RFC3339 / ISO8601 menos que você especifique o
locale
bem como otimeZone
edateFormat
string.Ou você pode usar
ISO8601DateFormatter
para tirar você do mato da configuraçãolocale
e detimeZone
si mesmo:Para a versão Swift 2, consulte a revisão anterior desta resposta .
fonte
en_US_POSIX
. É a língua franca para trocar datas na web. E você não pode interpretar mal as datas se um calendário foi usado no dispositivo ao salvar uma sequência de datas e outro quando a sequência é lida mais tarde. Além disso, você precisa de um formato que nunca será alterado (e é por isso que você usaen_US_POSIX
e nãoen_US
). Consulte o Technical Q&A 1480 ou os padrões RFC / ISO para obter mais informações.Se você quiser usar o
ISO8601DateFormatter()
com uma data de um feed JSON do Rails 4+ (e não precisar de milis é claro), precisará definir algumas opções no formatador para que ele funcione corretamente, caso contrário, adate(from: string)
função retornará nula. Aqui está o que estou usando:Aqui está o resultado do uso das opções versos que não estão em uma captura de tela do playground:
fonte
.withFractionalSeconds
mas eu já tentei isso e ele continua gerando um errolibc++abi.dylib: terminating with uncaught exception of type NSException
..deferredToDate
ao usar o protocolo codificávelSwift 5
Se você está segmentando o iOS 11.0+ / macOS 10.13+, basta usar
ISO8601DateFormatter
com as opçõeswithInternetDateTime
ewithFractionalSeconds
, assim:fonte
Para elogiar ainda mais Andrés Torres Marroquín e Leo Dabus, tenho uma versão que preserva segundos fracionários. Não consigo encontrá-lo documentado em nenhum lugar, mas a Apple trunca segundos fracionários até o microssegundo (3 dígitos de precisão) na entrada e na saída (mesmo que especificado usando SSSSSSS, ao contrário do Unicode tr35-31 ).
Devo enfatizar que isso provavelmente não é necessário para a maioria dos casos de uso . As datas on-line normalmente não precisam de precisão de milissegundos e, quando o fazem, geralmente é melhor usar um formato de dados diferente. Mas, às vezes, é preciso interoperar com um sistema preexistente de uma maneira específica.
Xcode 8/9 e Swift 3.0-3.2
fonte
Usa
ISO8601DateFormatter
no iOS10 ou mais recente.Usa
DateFormatter
no iOS9 ou mais antigo.Swift 4
fonte
No meu caso, tenho que converter a coluna DynamoDB - lastUpdated (carimbo de data e hora do Unix) para o horário normal.
O valor inicial de lastUpdated era: 1460650607601 - convertido para 14-04-2016 16:16:47 +0000 via:
fonte
No futuro, pode ser necessário alterar o formato, o que pode ser uma dor de cabeça pequena com date.dateFromISO8601 em todos os lugares em um aplicativo. Use uma classe e um protocolo para encerrar a implementação. A alteração da chamada do formato de data e hora em um local será mais simples. Use RFC3339, se possível, é uma representação mais completa. DateFormatProtocol e DateFormat são ótimos para injeção de dependência.
fonte
Há um novo
ISO8601DateFormatter
classe que permite criar uma string com apenas uma linha. Para compatibilidade com versões anteriores, usei uma biblioteca C antiga. Espero que isso seja útil para alguém.Swift 3.0
fonte
Para complementar a versão de Leo Dabus, adicionei suporte para projetos escritos Swift e Objective-C, também adicionei suporte para milissegundos opcionais, provavelmente não é o melhor, mas você entenderia:
Xcode 8 e Swift 3
fonte
Sem algumas máscaras de String manuais ou TimeFormatters
fonte
.iso8601
não incluirá milissegundos.Com base na resposta aceitável em um paradigma de objeto
callsite
fonte