Wie erstelle ich einen Datums- / Zeitstempel unter Verwendung der Formatstandards für ISO 8601 und RFC 3339 ?
Das Ziel ist eine Zeichenfolge, die so aussieht:
"2015-01-01T00:00:00.000Z"
Format:
- Jahr, Monat, Tag als "XXXX-XX-XX"
- der Buchstabe "T" als Trennzeichen
- Stunde, Minute, Sekunden, Millisekunden als "XX: XX: XX.XXX".
- der Buchstabe "Z" als Zonenbezeichnung für Nullpunktverschiebung, auch bekannt als UTC, GMT, Zulu-Zeit.
I'm besten fall:
- Schneller Quellcode, der einfach, kurz und unkompliziert ist.
- Sie müssen kein zusätzliches Framework, Teilprojekt, Cocoapod, C-Code usw. verwenden.
Ich habe nach StackOverflow, Google, Apple usw. gesucht und keine schnelle Antwort darauf gefunden.
Die Klassen , die vielversprechendsten scheinen sind NSDate
, NSDateFormatter
, NSTimeZone
.
Verwandte Fragen und Antworten: Wie erhalte ich das ISO 8601-Datum in iOS?
Hier ist das Beste, was ich mir bisher ausgedacht habe:
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))
Antworten:
Swift 4 • iOS 11.2.1 oder höher
Verwendung:
iOS 9 • Swift 3 oder höher
und die Codierungsstrategie
Spielplatztests
Codierung
Dekodierung
quelle
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
vereinfacht das neue iOS 10 den Vorgang. Ich habe Apple einen Fehlerbericht (27242248) gesendet, in dem sie aufgefordert wurden, diesen neuen Formatierer zu erweitern, um auch die Angabe von Millisekunden zu ermöglichen (da dieser neue Formatierer für viele von uns ohne Millisekunden nicht von Nutzen ist).T
zB :2016-09-21 21:05:10+00:00
?Denken Sie daran, das Gebietsschema
en_US_POSIX
wie in Technische Fragen und Antworten A1480 beschrieben einzustellen . In Swift 3:Das Problem ist, dass wenn Sie sich auf einem Gerät befinden, das einen nicht-gregorianischen Kalender verwendet, das Jahr nicht RFC3339 / ISO8601 entspricht, es sei denn, Sie geben sowohl die Zeichenfolge
locale
als auch die ZeichenfolgetimeZone
und andateFormat
.Oder Sie können verwenden
ISO8601DateFormatter
, um Sie aus dem Unkraut der Umgebunglocale
und sichtimeZone
selbst herauszuholen :Informationen zur Swift 2-Wiedergabe finden Sie in der vorherigen Überarbeitung dieser Antwort .
quelle
en_US_POSIX
. Es ist die Verkehrssprache für den Austausch von Daten im Internet. Und Sie können Datumsangaben nicht falsch interpretieren, wenn beim Speichern einer Datumszeichenfolge ein Kalender auf dem Gerät verwendet wurde und ein anderer, wenn die Zeichenfolge später wieder eingelesen wird. Außerdem benötigen Sie ein Format, das sich garantiert nie ändert (weshalb Sie es verwendenen_US_POSIX
und nichten_US
). Weitere Informationen finden Sie in den technischen Fragen und Antworten 1480 oder in diesen RFC / ISO-Standards.Wenn Sie den
ISO8601DateFormatter()
mit einem Datum aus einem Rails 4+ JSON-Feed verwenden möchten (und natürlich keine Millis benötigen), müssen Sie einige Optionen für den Formatierer festlegen, damit er richtigdate(from: string)
funktioniert. Andernfalls gibt die Funktion null zurück. Folgendes verwende ich:Hier ist das Ergebnis der Verwendung der Optionsverse, die nicht in einem Spielplatz-Screenshot enthalten sind:
quelle
.withFractionalSeconds
aber ich habe das bereits versucht und es wird immer wieder ein Fehler ausgegebenlibc++abi.dylib: terminating with uncaught exception of type NSException
..deferredToDate
Datumsdecodierungsstrategie, wenn Sie das codierbare Protokoll verwendenSwift 5
Wenn Sie iOS ab Version 11.0 / macOS 10.13+ Targeting sind, verwenden Sie einfach
ISO8601DateFormatter
mit denwithInternetDateTime
undwithFractionalSeconds
Optionen, etwa so:quelle
Um Andrés Torres Marroquín und Leo Dabus weiter zu beglückwünschen, habe ich eine Version, die Sekundenbruchteile bewahrt. Ich kann es nirgendwo dokumentiert finden, aber Apple schneidet sowohl bei der Eingabe als auch bei der Ausgabe Sekundenbruchteile auf die Mikrosekunde (3 Stellen Genauigkeit) ab (obwohl dies im Gegensatz zu Unicode tr35-31 mit SSSSSSS angegeben wurde ).
Ich sollte betonen, dass dies für die meisten Anwendungsfälle wahrscheinlich nicht notwendig ist . Online-Daten erfordern normalerweise keine Millisekundengenauigkeit. In diesem Fall ist es häufig besser, ein anderes Datenformat zu verwenden. Manchmal muss man jedoch auf bestimmte Weise mit einem bereits vorhandenen System zusammenarbeiten.
Xcode 8/9 und Swift 3.0-3.2
quelle
Verwendet
ISO8601DateFormatter
unter iOS10 oder neuer.Verwendet
DateFormatter
unter iOS9 oder älter.Swift 4
quelle
In meinem Fall muss ich die Spalte DynamoDB - lastUpdated (Unix Timestamp) in Normal Time konvertieren.
Der Anfangswert von lastUpdated war: 1460650607601 - konvertiert auf 2016-04-14 16:16:47 +0000 via:
quelle
In Zukunft muss das Format möglicherweise geändert werden. Dies kann ein kleiner Kopfschmerz sein, wenn date.dateFromISO8601 überall in einer App aufgerufen wird. Verwenden Sie eine Klasse und ein Protokoll, um die Implementierung zu verpacken. Das Ändern des Datums-Zeit-Format-Aufrufs an einer Stelle ist einfacher. Verwenden Sie nach Möglichkeit RFC3339, um eine vollständigere Darstellung zu erhalten. DateFormatProtocol und DateFormat eignen sich hervorragend für die Abhängigkeitsinjektion.
quelle
Es gibt eine neue
ISO8601DateFormatter
Klasse, mit der Sie eine Zeichenfolge mit nur einer Zeile erstellen können. Aus Gründen der Abwärtskompatibilität habe ich eine alte C-Bibliothek verwendet. Ich hoffe das ist nützlich für jemanden.Swift 3.0
quelle
Um die Version von Leo Dabus zu ergänzen, habe ich Unterstützung für Projekte hinzugefügt, die Swift und Objective-C geschrieben haben, und Unterstützung für die optionalen Millisekunden hinzugefügt. Dies ist wahrscheinlich nicht die beste, aber Sie würden den Punkt verstehen:
Xcode 8 und Swift 3
quelle
Ohne manuelle String-Masken oder TimeFormatters
quelle
.iso8601
keine Millisekunden.Basierend auf der akzeptablen Antwort in einem Objektparadigma
Callsite
quelle