Comment générer un horodatage, en utilisant les normes de format ISO 8601 et RFC 3339 ?
Le but est une chaîne qui ressemble à ceci:
"2015-01-01T00:00:00.000Z"
Format:
- année, mois, jour, sous la forme "XXXX-XX-XX"
- la lettre "T" comme séparateur
- heure, minute, secondes, millisecondes, comme "XX: XX: XX.XXX".
- la lettre «Z» comme désignateur de zone pour le décalage zéro, aka UTC, GMT, heure Zulu.
Meilleur cas:
- Code source Swift simple, court et direct.
- Pas besoin d'utiliser un framework supplémentaire, sous-projet, cocoapod, code C, etc.
J'ai recherché StackOverflow, Google, Apple, etc. et je n'ai pas trouvé de réponse Swift à cela.
Les classes qui semblent les plus prometteuses sont NSDate
, NSDateFormatter
, NSTimeZone
.
Questions et réponses connexes: Comment obtenir la date ISO 8601 dans iOS?
Voici le meilleur que j'ai trouvé jusqu'à présent:
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))
Réponses:
Swift 4 • iOS 11.2.1 ou version ultérieure
Usage:
iOS 9 • Swift 3 ou version ultérieure
et la stratégie d'encodage
Test de terrain de jeu
codage
décodage
la source
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
simplifie le processus. J'ai publié un rapport de bogue (27242248) à Apple, leur demandant d'étendre ce nouveau formateur pour offrir également la possibilité de spécifier des millisecondes (car ce nouveau formateur n'est pas utile pour beaucoup d'entre nous sans les millisecondes).T
par exemple2016-09-21 21:05:10+00:00
:?N'oubliez pas de définir les paramètres régionaux
en_US_POSIX
comme décrit dans les questions et réponses techniques1480 . Dans Swift 3:Le problème est que si vous êtes sur un appareil qui utilise un calendrier non grégorien, l'année ne sera pas conforme à RFC3339 / ISO8601, sauf si vous spécifiez le
locale
ainsi que letimeZone
etdateFormat
chaîne .Ou vous pouvez utiliser
ISO8601DateFormatter
pour vous sortir des mauvaises herbes du décorlocale
et detimeZone
vous - même:Pour le rendu Swift 2, voir la révision précédente de cette réponse .
la source
en_US_POSIX
. C'est la lingua franca pour échanger des dates sur le web. Et vous ne pouvez pas avoir une mauvaise interprétation des dates si un calendrier a été utilisé sur l'appareil lors de l'enregistrement d'une chaîne de date et un autre lorsque la chaîne est lue ultérieurement. De plus, vous avez besoin d'un format qui ne changera jamais (c'est pourquoi vous l'utilisezen_US_POSIX
et nonen_US
). Voir Questions et réponses techniques 1480 ou ces normes RFC / ISO pour plus d'informations.Si vous souhaitez utiliser le
ISO8601DateFormatter()
avec une date d'un flux JSON Rails 4+ (et n'avez pas besoin de millis bien sûr), vous devez définir quelques options sur le formateur pour que cela fonctionne correctement, sinon ladate(from: string)
fonction retournera nil. Voici ce que j'utilise:Voici le résultat de l'utilisation des versets d'options pas dans une capture d'écran de terrain de jeu:
la source
.withFractionalSeconds
mais j'ai déjà essayé cela et cela continue de générer une erreurlibc++abi.dylib: terminating with uncaught exception of type NSException
..deferredToDate
lors de l'utilisation du protocole CodableSwift 5
Si vous ciblez iOS 11.0+ / macOS 10.13+, vous utilisez simplement
ISO8601DateFormatter
avec les optionswithInternetDateTime
etwithFractionalSeconds
, comme ceci:la source
Utilise
ISO8601DateFormatter
sur iOS10 ou plus récent.Utilise
DateFormatter
sur iOS9 ou version antérieure.Swift 4
la source
Pour complimenter encore Andrés Torres Marroquín et Leo Dabus, j'ai une version qui préserve les fractions de seconde. Je ne peux le trouver documenté nulle part, mais Apple tronque les fractions de seconde à la microseconde (3 chiffres de précision) à la fois en entrée et en sortie (même si spécifié à l'aide de SSSSSSS, contrairement à Unicode tr35-31 ).
Je dois souligner que ce n'est probablement pas nécessaire pour la plupart des cas d'utilisation . Les dates en ligne n'ont généralement pas besoin d'une précision à la milliseconde, et quand c'est le cas, il est souvent préférable d'utiliser un format de données différent. Mais parfois, il faut interagir avec un système préexistant d'une manière particulière.
Xcode 8/9 et Swift 3.0-3.2
la source
Dans mon cas, je dois convertir la colonne DynamoDB - lastUpdated (horodatage Unix) en heure normale.
La valeur initiale de lastUpdated était: 1460650607601 - convertie en 2016-04-14 16:16:47 +0000 via:
la source
À l'avenir, le format devra peut-être être modifié, ce qui pourrait être un petit mal de tête avec des appels date.dateFromISO8601 partout dans une application. Utilisez une classe et un protocole pour encapsuler l'implémentation, changer l'appel de format de date et d'heure en un seul endroit sera plus simple. Utilisez RFC3339 si possible, c'est une représentation plus complète. DateFormatProtocol et DateFormat sont parfaits pour l'injection de dépendances.
la source
Il y a un nouveau
ISO8601DateFormatter
classe qui vous permet de créer une chaîne avec une seule ligne. Pour la compatibilité ascendante, j'ai utilisé une ancienne bibliothèque C. J'espère que c'est utile pour quelqu'un.Swift 3.0
la source
Pour compléter la version de Leo Dabus, j'ai ajouté la prise en charge des projets écrits Swift et Objective-C, ainsi que la prise en charge des millisecondes optionnelles, ce n'est probablement pas le meilleur, mais vous obtiendrez le point:
Xcode 8 et Swift 3
la source
Sans certains masques de chaîne manuels ou TimeFormatters
la source
.iso8601
n'inclura pas les millisecondes.Basé sur la réponse acceptable dans un paradigme d'objet
site d'appel
la source