¿Cómo generar una marca de fecha y hora, utilizando los estándares de formato para ISO 8601 y RFC 3339 ?
El objetivo es una cadena que se ve así:
"2015-01-01T00:00:00.000Z"
Formato:
- año, mes, día, como "XXXX-XX-XX"
- la letra "T" como separador
- hora, minuto, segundos, milisegundos, como "XX: XX: XX.XXX".
- la letra "Z" como un designador de zona para desplazamiento cero, también conocido como UTC, GMT, hora zulú.
Mejor caso:
- Código fuente rápido que es simple, corto y directo.
- No es necesario utilizar ningún marco adicional, subproyecto, cocoapod, código C, etc.
He buscado en StackOverflow, Google, Apple, etc. y no he encontrado una respuesta rápida a esto.
Las clases que parecen más prometedores son NSDate
, NSDateFormatter
, NSTimeZone
.
Preguntas y respuestas relacionadas: ¿Cómo obtengo la fecha ISO 8601 en iOS?
Aquí está lo mejor que he encontrado hasta ahora:
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))
Respuestas:
Swift 4 • iOS 11.2.1 o posterior
Uso:
iOS 9 • Swift 3 o posterior
y la estrategia de codificación
Prueba de patio de recreo
codificación
descodificación
fuente
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 el proceso. He emitido un informe de error (27242248) a Apple, solicitándoles que expandan este nuevo formateador para ofrecer la capacidad de especificar milisegundos también (ya que este nuevo formateador no es útil para muchos de nosotros sin los milisegundos).T
por ejemplo2016-09-21 21:05:10+00:00
:?Recuerde configurar la configuración regional
en_US_POSIX
como se describe en las Preguntas y respuestas técnicas 1480 . En Swift 3:La cuestión es que si estás en un dispositivo que utiliza un calendario no gregoriano, el año no cumplirá con RFC3339 / ISO8601 a menos que especifique el
locale
, así como eltimeZone
ydateFormat
cadena.O puede usarlo
ISO8601DateFormatter
para salir de la maleza del entornolocale
y detimeZone
usted mismo:Para la versión de Swift 2, vea la revisión anterior de esta respuesta .
fuente
en_US_POSIX
. Es la lengua franca para intercambiar fechas en la web. Y no puede hacer que malinterprete las fechas si se usó un calendario en el dispositivo al guardar una cadena de fecha y otro cuando la cadena se vuelve a leer más tarde. Además, necesita un formato que garantice que nunca cambiará (por eso lo usaen_US_POSIX
y noen_US
). Consulte las preguntas y respuestas técnicas 1480 o las normas RFC / ISO para obtener más información.Si desea utilizar el
ISO8601DateFormatter()
con una fecha de un feed JSON de Rails 4+ (y no necesita millis, por supuesto), debe establecer algunas opciones en el formateador para que funcione correctamente; de lo contrario, ladate(from: string)
función devolverá nil. Esto es lo que estoy usando:Aquí está el resultado de usar los versos de opciones que no están en una captura de pantalla del patio de juegos:
fuente
.withFractionalSeconds
pero ya lo intenté y sigue arrojando un errorlibc++abi.dylib: terminating with uncaught exception of type NSException
..deferredToDate
cuando use el protocolo CodificableSwift 5
Si está apuntando a iOS 11.0+ / macOS 10.13+, simplemente use
ISO8601DateFormatter
con las opcioneswithInternetDateTime
ywithFractionalSeconds
, de esta manera:fuente
Usos
ISO8601DateFormatter
en iOS10 o más reciente.Usos
DateFormatter
en iOS9 o anterior.Swift 4
fuente
Para felicitar aún más a Andrés Torres Marroquín y Leo Dabus, tengo una versión que conserva segundos fraccionarios. No puedo encontrarlo documentado en ningún lado, pero Apple trunca segundos fraccionarios al microsegundo (3 dígitos de precisión) tanto en la entrada como en la salida (aunque se especifique utilizando SSSSSSS, al contrario de Unicode tr35-31 ).
Debo enfatizar que esto probablemente no sea necesario para la mayoría de los casos de uso . Las fechas en línea generalmente no necesitan una precisión de milisegundos, y cuando lo hacen, a menudo es mejor usar un formato de datos diferente. Pero a veces uno debe interoperar con un sistema preexistente de una manera particular.
Xcode 8/9 y Swift 3.0-3.2
fuente
En mi caso, tengo que convertir la columna DynamoDB - lastUpdated (Unix Timestamp) a Normal Time.
El valor inicial de lastUpdated fue: 1460650607601 - convertido a 2016-04-14 16:16:47 +0000 a través de:
fuente
En el futuro, es posible que sea necesario cambiar el formato, lo que podría ser un pequeño dolor de cabeza con date.dateFromISO8601 en todas partes de una aplicación. Use una clase y un protocolo para ajustar la implementación, cambiar el formato de fecha y hora en un solo lugar será más simple. Utilice RFC3339 si es posible, es una representación más completa. DateFormatProtocol y DateFormat es ideal para la inyección de dependencias.
fuente
Hay una nueva
ISO8601DateFormatter
clase que le permite crear una cadena con solo una línea. Por compatibilidad con versiones anteriores, utilicé una antigua biblioteca C. Espero que esto sea útil para alguien.Swift 3.0
fuente
Para complementar la versión de Leo Dabus, agregué soporte para proyectos escritos Swift y Objective-C, también agregué soporte para los milisegundos opcionales, probablemente no sea lo mejor, pero entendería el punto:
Xcode 8 y Swift 3
fuente
Sin algunas máscaras de cadena manuales o TimeFormatters
fuente
.iso8601
no incluirá milisegundos.Basado en la respuesta aceptable en un paradigma de objeto
sitio de llamadas
fuente