2015-07-28 8 views
13

Sto tentando di convertire una data in formato UTC da un'API in un formato di approssimazione leggibile da umani utilizzando Swift.Data/ora Approssimazione del linguaggio naturale in Swift

Sto cercando qualcosa di simile al seguente:

2015-07-14T13: 51: 05.423Z

a

Circa due settimane fa

Qual è l'approccio migliore a questo in Swift? Mentre in modo ottimale questo potrebbe formattare direttamente le stringhe, capisco che questo richiederà probabilmente il cast della stringa su un oggetto NSDate.

Qualsiasi aiuto sarebbe molto apprezzato.

MODIFICA: la mia domanda era stata identificata come possibile duplicato di another question. La soluzione di Tom qui sotto è scritta per Swift e molto più elegante rispetto alla creazione di un nuovo metodo per quanto riguarda la mia situazione.

+1

Partenza https://github.com/kevinlawler/NSDate-TimeAgo o http: // StackOverflow.com/domande/902.950/iphone-convertire-Data-string-to-a-parente-time-stamp. – jtbandes

+0

prova https://github.com/quire-io/SwiftyChrono, è persino più potente del modello precedente e scritto in Swift. –

risposta

31

Sono necessari due passaggi. In primo luogo, convertire la stringa di data per un 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) 

(Se questo non è una rappresentazione esatta delle corde si ottiene, si dovrà modificare la stringa di formato di data per ottenere questo per convertire).

Avanti, utilizzare NSDateComponentsFormatter per ottenere la stringa desiderata:

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()) 
} 

Oggi è il 28 luglio, quindi il risultato per quella stringa è "Circa 2 settimane". L'attributo allowedUnits è un campo bit, quindi è possibile specificare tutti i tipi di unità che si desidera consentire.

+1

Grazie Tom, la soluzione ha funzionato alla grande! Ho apportato un paio di modifiche per soddisfare le mie esigenze. Per prima cosa ho cambiato le allowUnits in "[.Year, .Month, .WeekOfMonth, .Day, .Hour, .Minute, .Second]" e poi ho aggiunto 'formatter.maximumUnitCount = 1', che sembra produrre la migliore" approssimazione naturale " "risultato. EDIT: Si noti che la mia matrice NSCalendarUnit riflette l'utilizzo di Swift 2 – Tyler

+4

Una cosa che dovrebbe essere notata se la si utilizza ripetutamente (cioè su una cella di visualizzazione tabella) è che la creazione del formatter della data costa un po 'di CPU, quindi sarebbe utile mantenere un formattatore di date da riutilizzare (ad es. crearlo in viewDidLoad). –

+0

Sarebbe bello sapere come questo si confronti con TTTTimeIntervalFormatter, da FormatterKit, che è abbastanza usato. – algal

3

Come nota di risposta di Tom Harrington, è possibile produrre una rappresentazione colloquiale di un momento o un intervallo di tempo utilizzando NSDateComponentsFormatter.

Tuttavia, se si vuole fare esattamente ciò che la domanda chiede nel suo esempio, che è quello di produrre una rappresentazione colloquiale di un momento nel passato, rispetto al momento presente, come per una timeline-oriented interfaccia utente, quindi sembra che NSDateComponentsFormatter non sia adatto. Come dice la documentazione di stringFromTimeInterval(_:), il valore dell'intervallo di tempo "deve essere un numero finito. I numeri negativi vengono considerati come numeri positivi quando si crea la stringa".

Per quanto posso dire, la scelta migliore è TTTTimeIntervalFormatter, una classe autonoma in Mattdi Mattt Thompson.

Ho prodotto un parco giochi Xcode 7, RelativeDatePlayground, che confronta le uscite di NSDateFormatter in TTTTimeIntervalFormatter. Ecco una tabella che mostra l'output per diversi tempi relativi in ​​secondi. Come si può vedere, NSDateComponentsFormatter non sembra per gestire momenti passati o il momento presente così:

 -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 
Problemi correlati