2014-09-15 10 views
52

Próbowałem parsować ciąg daty "2014-09-12T11: 45: 26.371Z" w języku go.Parsowanie łańcucha daty w golang

Kod

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

czas parsowania "2014-11-12T11: 47: 39.489Z": miesiąc poza zasięgiem

mam ten błąd.

Jak przeanalizować ten ciąg daty?

+0

Dla przyszłych czytelników, napisałem kilka ćwiczeń do uprawiania data parsowanie https://github.com/soniah/date_practice –

Odpowiedz

68

Użyj dokładnych numerów układów opisanych here i ładnego bloga here.

tak:

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) 

daje:

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

wiem. Rozumiem. Za pierwszym razem mnie przyłapał. Go po prostu nie używa abstrakcyjnej składni datetime składników (YYYY-MM-DD), ale te dokładne liczby ( Myślę, że czas pierwszego zatwierdzenia go Nie, zgodnie z this. Czy ktoś wie?).

+34

numery układu? Co? Czemu? Argh! – Fuser97381

+9

@ Fuser97381 Dzielę się twoją agonią ... – RickyA

+0

samo tutaj ... i zero! string z zero nie do przyjęcia .. –

47

Używany układ to rzeczywiście "2006-01-02T15:04:05.000Z" opisany w answer.
Nie jest to "czas pierwszego zatwierdzenia przejścia", ale raczej mnemoniczny sposób na zapamiętanie wspomnianego układu.
Patrz pkg/time:

Czas odniesienia stosowane w układach jest:

Mon Jan 2 15:04:05 MST 2006 

których czas Unix 1136239445.
Od MST jest GMT-0700, czas odniesienia może być traktowane jako

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

(1,2,3,4,5,6,7, pod warunkiem, że należy pamiętać, że 1 jest za miesiąc i 2 na dzień, co nie jest łatwe dla Europejczyków takich jak ja, użyte w formacie daty dzień-miesiąc)

Jak pokazano w "time.parse : why does golang parses the time incorrectly?", ten układ (za pomocą 1,2,3,4,5 , 6,7) musi być respektowany dokładnie.

+0

Miło, dzięki za wyjaśnienie. – RickyA

+0

Taa, która łapie też Australijczyków! MM/DD po ​​prostu mnie nie oblicza i muszę na nie patrzeć. –

+2

@SimonWhitehead Zgadzam się. Przynajmniej raz go sprawdzę, wiem, co oznaczają YY, MM, DD, hh, mm, ss i mogę je łatwo zamówić. Z Go, nawet po sprawdzeniu, muszę pamiętać, co oznaczają 1, 2, 3, 4 .... – VonC

10

Zgodnie z odpowiedzią, ale aby zapisać wpisanie do układu "2006-01-02T15:04:05.000Z", można użyć stałej pakietu: RFC3339.

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

Dodatkowo, jeśli spojrzysz na stałe pakietów (połączone w powyższej odpowiedzi), istnieje wiele innych popularnych formatów, pod warunkiem, że mogą być użyte. Jeśli potrzebujesz czegoś innego, użyj ich jako punktu wyjścia. – Hugh

+0

Ta i kilka odpowiedzi poleca '2006-01-02T15: 04: 05.000Z' i wspomina, że ​​Go' time.RFC3339' również będzie działać. Ale 'time.RFC3339 =" 2006-01-02T15: 04: 05Z07: 00 "'. Czy te dwa formaty są dokładnie równoważne, o ile zrobią to 'time.Parse' i' time.ParseInLocation'? – Miles

+1

To prawda, @Miles, ten test potwierdza to https://play.golang.org/p/T3dW1kTeAHl – robstarbuck

1

To może być bardzo późno, ale to jest dla osób, które mogą natknąć się na ten problem i chcą korzystać z zewnętrznego pakietu do analizowania datę ciąg.

Próbowałem szukają bibliotek i znalazłem ten:

https://github.com/araddon/dateparse

przykład z 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()) 
} 
+1

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać link do odniesienia . Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. - [Z recenzji] (/ opinia/niskiej jakości-posts/18671993) – talves

+0

Witam @talves, zaktualizowałem odpowiedź, dodając przykład kodu z pliku readme pakietu. dzięki! – srf

0

będę sugerować użyciu time.RFC3339 stała od czasu pakietu . Możesz sprawdzić inne stałe z pakietu czasu. 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); 
}