2015-07-28 9 views
13

Ich versuche, ein UTC-formatiertes Datum von einer API in ein für Menschen lesbares Approximationsformat mit Swift zu konvertieren.Datum/Zeit Natürliche Sprachen Approximation in Swift

Ich suche nach etwas wie folgt aus:

2015-07-14T13: 51: 05.423Z

zu

Vor etwa zwei Wochen

Was ist der beste Ansatz in Swift? Während dies in optimaler Weise die Strings direkt formatieren könnte, ist es wohl notwendig, dass die Zeichenfolge in ein NSDate-Objekt umgewandelt wird.

Jede Hilfe würde sehr geschätzt werden.

EDIT: Meine Frage wurde als ein mögliches Duplikat von another question identifiziert. Toms Lösung ist für Swift geschrieben und viel eleganter, als eine neue Methode in Bezug auf meine Situation zu erstellen.

+1

überprüfen https://github.com/kevinlawler/NSDate-TimeAgo oder http: // Stackoverflow.com/questions/902950/iphone-convert-date-zeichenfolge-zu-einer-relativen-zeitstempel. – jtbandes

+0

versuchen Sie https://github.com/quire-io/SwiftyChrono, es ist sogar leistungsfähiger als gerade Muster und in Swift geschrieben. –

Antwort

31

Sie benötigen zwei Schritte. Zuerst konvertieren Sie das Datum String in einen NSDate:

let dateString = "2015-07-14T13:51:05.423Z" 

let df = NSDateFormatter() 
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" 
let date = df.dateFromString(dateString) 

(Wenn das nicht eine genaue Darstellung der Saiten Sie bekommen, werden Sie das Datumsformat-Zeichenfolge ändern müssen, um diese zu konvertieren zu bekommen).

Als nächstes verwenden NSDateComponentsFormatter Ihre gewünschte Zeichenfolge zu erhalten:

let formatter = NSDateComponentsFormatter() 
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyle.Full 
formatter.includesApproximationPhrase = true 
formatter.includesTimeRemainingPhrase = false 
formatter.allowedUnits = NSCalendarUnit.WeekOfMonthCalendarUnit 

if let pastDate = date { 
    let dateRelativeString = formatter.stringFromDate(pastDate, toDate: NSDate()) 
} 

Heute ist 28. Juli, so dass das Ergebnis für die Zeichenfolge „Etwa 2 Wochen“. Das Attribut allowedUnits ist ein Bitfeld, sodass Sie so viele Einheitentypen angeben können, wie Sie zulassen möchten.

+1

Danke Tom, die Lösung hat super funktioniert! Ich habe ein paar Änderungen vorgenommen, um meine Bedürfnisse zu erfüllen. Zuerst änderte ich die erlaubten Einheiten in '[.Year, .Month, .WeekOfMonth, .Day, .Hour, .Minute, .Second]' und fügte dann 'formatter.maximumUnitCount = 1' hinzu, was die beste" natürliche Näherung "zu erzeugen scheint "Ergebnis. Bearbeiten: Beachten Sie, dass meine NSCalendarUnit-Array Swift 2 Verwendung widerspiegelt – Tyler

+4

Eine Sache, die beachtet werden sollte, wenn Sie dies wiederholt verwenden (dh auf einer Tabellenansicht Zelle) ist, dass das Erstellen des Datums Formatierer ein wenig CPU kostet, so wäre es praktisch Behalte einen Datumsformatierer bei, der wiederverwendet werden soll (zB erstelle ihn in viewDidLoad). –

+0

Es wäre toll zu wissen, wie dies mit TTTTimeIntervalFormatter von FormatterKit verglichen wird, die ziemlich häufig verwendet wird. – algal

3

Wie Tom Harringtons Antwort feststellt, können Sie eine umgangssprachliche Darstellung eines Moments oder eines Zeitintervalls mit NSDateComponentsFormatter erstellen.

Wenn Sie jedoch wollen genau das tun, was die Frage in seinem Beispiel fragt, die eine umgangs Darstellung eines Moments in der Vergangenheit in Bezug auf den gegenwärtigen Moment zu erzeugen, ist, wie für eine Timeline-orientierte Benutzeroberfläche, dann scheint es wie NSDateComponentsFormatter ist nicht geeignet. Wie die Dokumentation für stringFromTimeInterval(_:) sagt, muss der Zeitintervallwert "eine endliche Zahl sein. Negative Zahlen werden als positive Zahlen behandelt, wenn die Zeichenfolge erzeugt wird."

So nah wie ich sagen kann, ist die beste Wahl TTTTimeIntervalFormatter, eine eigenständige Klasse in Mattt Thompson FormatterKit.

Ich habe einen Xcode 7 Spielplatz, produziert, der die Ausgaben von NSDateFormatter Ausgang mit TTTTimeIntervalFormatter vergleicht. Hier ist eine Tabelle, die die Ausgabe für verschiedene relative Zeiten in Sekunden zeigt. Wie Sie sehen können, scheint NSDateComponentsFormatter nicht in der Vergangenheit Momente oder den gegenwärtigen Moment gut zu handhaben:

aus
 -1488010 |    2 weeks ago |   -1 week remaining 
     -1468800 |    2 weeks ago |   -1 week remaining 
     -864000 |    1 week ago |  0 seconds remaining 
      -86400 |     1 day ago |   -1 day remaining 
      -36000 |    10 hours ago |  -10 hours remaining 
      -3600 |    1 hour ago |   -1 hour remaining 
      -600 |   10 minutes ago |  -10 minutes remaining 
      -60 |    1 minute ago |  -1 minute remaining 
      -10 |   10 seconds ago |  -10 seconds remaining 
       -1 |    1 second ago |  -1 second remaining 
       -0 |     just now |  0 seconds remaining 
       0 |     just now |  0 seconds remaining 
       1 |   1 second from now |  1 second remaining 
       10 |  10 seconds from now |  10 seconds remaining 
       60 |   1 minute from now |  1 minute remaining 
      600 |  10 minutes from now |  10 minutes remaining 
      3600 |   1 hour from now |   1 hour remaining 
      36000 |   10 hours from now |  10 hours remaining 
      86400 |   1 day from now |   1 day remaining 
      864000 |   1 week from now |   1 week remaining 
     1468800 |   2 weeks from now |   2 weeks remaining 
     1488010 |   2 weeks from now |   2 weeks remaining