Stringa della data di analisi in Vai


138

Ho provato ad analizzare la stringa della data "2014-09-12T11:45:26.371Z"in Go.

Codice

layout := "2014-09-12T11:45:26.371Z"
str := "2014-11-12T11:45:26.371Z"
t, err := time.Parse(layout , str)

Ho ricevuto questo errore:

tempo di analisi "2014-11-12T11: 47: 39.489Z": mese fuori intervallo

Come posso analizzare questa stringa di date?


Per i futuri lettori, ho scritto alcuni esercizi per esercitarsi con l'analisi della data su github.com/soniah/date_practice
Sonia Hamilton,

Il tuo layout dovrebbe essere esattamente 2006-01-02T15:04:05.000Zdovuto al folle standard
tharinduwijewardane il

Risposte:


165

Usa gli esatti numeri di layout descritti qui e un bel post sul blog qui .

così:

layout := "2006-01-02T15:04:05.000Z"
str := "2014-11-12T11:45:26.371Z"
t, err := time.Parse(layout, str)

if err != nil {
    fmt.Println(err)
}
fmt.Println(t)

dà:

>> 2014-11-12 11:45:26.371 +0000 UTC

Lo so. Mente da capogiro. Mi ha anche catturato la prima volta. Go non utilizza una sintassi astratta per i componenti datetime ( YYYY-MM-DD), ma questi numeri esatti ( penso che il tempo del primo commit di go Nope, secondo questo . Qualcuno lo sappia?).


118
Numeri di layout? Che cosa? Perché? Argh!
Darth Egregious,

29
Cosa stavano pensando ! ? o fumare?
Jishnu Prathap

14
Potrei essere un po 'in ritardo con i commenti qui, ma non aver paura del layout con i numeri, usa solo le costanti e il tuo codice sarebbe pulito :) es. Time.RFC3339
Davyd Dzhahaiev

11
Per quelli che non ottengono i numeri di layout, ammetto che a prima vista è molto estraneo, ma una volta che ti ci abitui, penso che abbia almeno lo stesso senso dei tipici dispositivi di layout ("Uso" D ", "d", "dd", "DD", ecc?), e probabilmente più senso. Devi solo saperlo prima.
tre

5
È per scopi mnemonici, cioè devi solo ricordare 1, 2, 3, 4, 5, 6, 7 queste lettere. C'è un ottimo articolo che parla di questo: medium.com/@simplyianm/…
amigcamel

86

Il layout di utilizzo è davvero " 2006-01-02T15:04:05.000Z" descritta nel RickyA 's risposta .
Non è "il momento del primo commit di go", ma piuttosto un modo mnemonico di ricordare detto layout.
Vedi pkg / time :

Il tempo di riferimento utilizzato nei layout è:

Mon Jan 2 15:04:05 MST 2006

che è tempo di Unix 1136239445.
Poiché MST è GMT-0700, il tempo di riferimento può essere considerato come

 01/02 03:04:05PM '06 -0700

(1,2,3,4,5,6,7, a condizione che ricordi che 1 è per il mese e 2 per il giorno, il che non è facile per un europeo come me, abituato al formato della data giorno-mese)

Come illustrato in " time.parse: perché Golang analizza il tempo in modo errato? ", Quel layout (usando 1,2,3,4,5,6,7) deve essere rispettato esattamente .


Sì, questo cattura anche gli australiani! MM / DD semplicemente non calcola per me e devo continuare a guardarlo.
Simon Whitehead,

3
@SimonWhitehead Sono d'accordo. Almeno, una volta che lo guardo, so cosa significano AA, MM, GG, hh, mm, ss e posso riordinarli facilmente. Con Go, anche dopo averlo cercato, devo ricordare cosa significano 1, 2, 3, 4 ....
VonC,

1
Il modo in cui mi ricordo è: Fase 1) Il "vero" data di ordinazione è l'anno> mese> giorno> ora> minuti> secondo> ecc (A causa mixed-endian sarebbe solo non sensically arbitrario e incoerente e per le date di grande- endian è preferibile a little-endian perché è facile da usare.) Questo ci porterebbe 1 (anno), 2 (mese), 3 (giorno), [...] Passaggio 2) Go / Google sono americani e americani mettono il loro anno alla fine delle loro date, quindi invece è 1 (mese), 2 (giorno), [...], n (anno) Passaggio 3) Il fuso orario segue tutto il resto perché i fusi orari sono un ulteriore livello di astrazione.
mtraceur,

@mtraceur Sì ... anche a me manca web.archive.org/web/20180501100155/http://… (da github.com/bdotdub/fuckinggodateformat ). Voglio dire, strftimeFTW.
VonC,

58

Come risposta ma per salvare la battitura a macchina "2006-01-02T15:04:05.000Z"per il layout, è possibile utilizzare la costante RFC3339 del pacchetto .

str := "2014-11-12T11:45:26.371Z"
t, err := time.Parse(time.RFC3339, str)

if err != nil {
    fmt.Println(err)
}
fmt.Println(t)

https://play.golang.org/p/Dgu2ZvHwTh


1
Inoltre, se si guardano le costanti del pacchetto (collegate nella risposta sopra), ci sono molti altri formati comuni che possono essere utilizzati. Se hai bisogno di qualcosa di leggermente diverso, usali come punto di partenza.
Hugh,

Questa e diverse risposte raccomandano 2006-01-02T15:04:05.000Ze menzionano che anche Go's time.RFC3339funzionerebbe. Ma time.RFC3339 = "2006-01-02T15:04:05Z07:00". Questi due formati sono esattamente equivalenti nella misura in cui cosa time.Parsee cosa time.ParseInLocationfaranno?
Miglia

1
Proprio così @Miles, questo test lo conferma play.golang.org/p/T3dW1kTeAHl
robstarbuck

24

Suggerirò di usare la costante time.RFC3339 dal pacchetto time. Puoi controllare altre costanti dal pacchetto orario. https://golang.org/pkg/time/#pkg-constants

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("Time parsing");
    dateString := "2014-11-12T11:45:26.371Z"
    time1, err := time.Parse(time.RFC3339,dateString);
    if err!=nil {
    fmt.Println("Error while parsing date :", err);
    }
    fmt.Println(time1); 
}

Intendevi usare i punti e virgola?
ChristoKiwi il

20

Questo è piuttosto tardi per la festa, e in realtà non dice nulla che non sia già stato detto in una forma o nell'altra, principalmente attraverso i link sopra, ma volevo dare un riassunto TL; DR a quelli con meno attenzione:

La data e l'ora della stringa del formato go è molto importante. È come Go sa quale campo è quale. Sono generalmente 1-9 da sinistra a destra come segue:

  • Gennaio / gennaio / gennaio / gennaio / 01 / _1 (ecc.) Sono per mese
  • 02 / _2 sono per il giorno del mese
  • 15/03 / _3 / PM / P / pm / p sono per ora e meridiano (3pm)
  • 04 / _4 sono per minuti
  • 05 / _5 sono per secondi
  • 2006/06 sono per anno
  • -0700 / 07:00 / MST sono per il fuso orario
  • .999999999 / .000000000 ecc. Sono per secondi parziali (penso che la distinzione sia se gli zeri finali vengono rimossi)
  • Lun / Lunedì sono il giorno della settimana (che in realtà era il 01-02-2006),

Quindi, non scrivere "01-05-15" come formato della data, a meno che tu non voglia "Mese-Seconda-Ora"

(... di nuovo, questo era fondamentalmente un sommario di cui sopra.)


5

Potrebbe essere super in ritardo, ma questo è per le persone che potrebbero inciampare in questo problema e potrebbero voler usare un pacchetto esterno per analizzare la stringa della data.

Ho provato a cercare una biblioteca e ho trovato questo:

https://github.com/araddon/dateparse

Esempio dal README:

package main

import (
    "flag"
    "fmt"
    "time"

    "github.com/apcera/termtables"
    "github.com/araddon/dateparse"
)

var examples = []string{
    "May 8, 2009 5:57:51 PM",
    "Mon Jan  2 15:04:05 2006",
    "Mon Jan  2 15:04:05 MST 2006",
    "Mon Jan 02 15:04:05 -0700 2006",
    "Monday, 02-Jan-06 15:04:05 MST",
    "Mon, 02 Jan 2006 15:04:05 MST",
    "Tue, 11 Jul 2017 16:28:13 +0200 (CEST)",
    "Mon, 02 Jan 2006 15:04:05 -0700",
    "Thu, 4 Jan 2018 17:53:36 +0000",
    "Mon Aug 10 15:44:11 UTC+0100 2015",
    "Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)",
    "12 Feb 2006, 19:17",
    "12 Feb 2006 19:17",
    "03 February 2013",
    "2013-Feb-03",
    //   mm/dd/yy
    "3/31/2014",
    "03/31/2014",
    "08/21/71",
    "8/1/71",
    "4/8/2014 22:05",
    "04/08/2014 22:05",
    "4/8/14 22:05",
    "04/2/2014 03:00:51",
    "8/8/1965 12:00:00 AM",
    "8/8/1965 01:00:01 PM",
    "8/8/1965 01:00 PM",
    "8/8/1965 1:00 PM",
    "8/8/1965 12:00 AM",
    "4/02/2014 03:00:51",
    "03/19/2012 10:11:59",
    "03/19/2012 10:11:59.3186369",
    // yyyy/mm/dd
    "2014/3/31",
    "2014/03/31",
    "2014/4/8 22:05",
    "2014/04/08 22:05",
    "2014/04/2 03:00:51",
    "2014/4/02 03:00:51",
    "2012/03/19 10:11:59",
    "2012/03/19 10:11:59.3186369",
    // Chinese
    "2014年04月08日",
    //   yyyy-mm-ddThh
    "2006-01-02T15:04:05+0000",
    "2009-08-12T22:15:09-07:00",
    "2009-08-12T22:15:09",
    "2009-08-12T22:15:09Z",
    //   yyyy-mm-dd hh:mm:ss
    "2014-04-26 17:24:37.3186369",
    "2012-08-03 18:31:59.257000000",
    "2014-04-26 17:24:37.123",
    "2013-04-01 22:43",
    "2013-04-01 22:43:22",
    "2014-12-16 06:20:00 UTC",
    "2014-12-16 06:20:00 GMT",
    "2014-04-26 05:24:37 PM",
    "2014-04-26 13:13:43 +0800",
    "2014-04-26 13:13:44 +09:00",
    "2012-08-03 18:31:59.257000000 +0000 UTC",
    "2015-09-30 18:48:56.35272715 +0000 UTC",
    "2015-02-18 00:12:00 +0000 GMT",
    "2015-02-18 00:12:00 +0000 UTC",
    "2017-07-19 03:21:51+00:00",
    "2014-04-26",
    "2014-04",
    "2014",
    "2014-05-11 08:20:13,787",
    // mm.dd.yy
    "3.31.2014",
    "03.31.2014",
    "08.21.71",
    //  yyyymmdd and similar
    "20140601",
    // unix seconds, ms
    "1332151919",
    "1384216367189",
}

var (
    timezone = ""
)

func main() {
    flag.StringVar(&timezone, "timezone", "UTC", "Timezone aka `America/Los_Angeles` formatted time-zone")
    flag.Parse()

    if timezone != "" {
        // NOTE:  This is very, very important to understand
        // time-parsing in go
        loc, err := time.LoadLocation(timezone)
        if err != nil {
            panic(err.Error())
        }
        time.Local = loc
    }

    table := termtables.CreateTable()

    table.AddHeaders("Input", "Parsed, and Output as %v")
    for _, dateExample := range examples {
        t, err := dateparse.ParseLocal(dateExample)
        if err != nil {
            panic(err.Error())
        }
        table.AddRow(dateExample, fmt.Sprintf("%v", t))
    }
    fmt.Println(table.Render())
}

2
Sfortunatamente, c'è un'ambiguità nell'ordine del mese. Il formato data europeo indica il giorno primo e il mese secondo, mentre il formato ora USA usa il contrario. Una data come il 3/5/2004 è ambigua. La data è valida in formato USA ed europeo, ma 3 e 5 possono corrispondere a giorno e mese o viceversa. dateParse assume il formato USA.
chmike,

-1

Se hai lavorato con la formattazione / analisi dell'ora / data in altre lingue, potresti aver notato che le altre lingue usano segnaposti speciali per la formattazione dell'ora / data. Ad esempio usi del linguaggio rubino

%d for day
%Y for year

ecc. Golang, invece di utilizzare codici come sopra, utilizza segnaposto in formato data e ora che sembrano solo data e ora. Go utilizza l'ora standard, ovvero:

Mon Jan 2 15:04:05 MST 2006  (MST is GMT-0700)
or 
01/02 03:04:05PM '06 -0700

Quindi se noti che Go usa

01 for the day of the month,
02 for the month
03 for hours,
04 for minutes
05 for second
and so on

Pertanto, ad esempio per l'analisi del 2020-01-29, la stringa di layout dovrebbe essere 06-01-02 o 2006-01-02.

È possibile fare riferimento alla tabella di layout segnaposto completa a questo link - https://golangbyexample.com/parse-time-in-golang/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.