Go'daki tarih dizesini ayrıştırma


138

"2014-09-12T11:45:26.371Z"Go'da tarih dizesini ayrıştırmayı denedim .

kod

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

Bu hatayı aldım:

ayrıştırma süresi "2014-11-12T11: 47: 39.489Z": ay aralık dışında

Bu tarih dizesini nasıl ayrıştırabilirim?


Gelecekteki okuyucular için github.com/soniah/date_practice
Sonia Hamilton

Düzeniniz tam olarak 2006-01-02T15:04:05.000Zbazı deli gitmek standart nedeniyle olmalıdır
tharinduwijewardane

Yanıtlar:


165

Kullanım tam düzen numaraları açıklanan burada ve güzel bir blog yayınını burada .

yani:

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)

verir:

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

Biliyorum. Akıl almaz. Ayrıca beni ilk kez yakaladı. Sadece tarih saat bileşenler (için soyut bir sözdizimi kullanmaz git YYYY-MM-DD(), ama bunlar kesin sayılar Ben zamanı ilk go ait taahhüt düşünüyorum göre, Nope bu . Mu kimse bilmesi?).


119
Düzen numaraları? Ne? Neden? Ahh!
Darth Egregious

30
Ne düşünüyorlardı ! ? veya sigara içiyor musunuz?
Jishnu Prathap

14
Burada yorumlarla biraz geç olabilirim, ancak sayılarla düzenden korkmayın, sadece sabitleri kullanın ve kodunuz temiz olurdu :) örneğin zaman.RFC3339
Davyd Dzhahaiev

11
Düzen sayılarını almayanlar için, ilk bakışta çok yabancı olduğunu itiraf ediyorum, ama bir kez alıştığınızda, en azından tipik düzen cihazları kadar mantıklı olduğunu düşünüyorum ('D' kullanıyor muyum, "d", "dd", "DD" vb.) ve muhtemelen daha mantıklı. Önce bunu bilmelisin.
threeve

5
Anımsatıcı amaç için, yani bu harfleri 1, 2, 3, 4, 5, 6, 7'yi hatırlamanız gerekiyor. Bunu tartışan harika bir makale var: medium.com/@simplyianm/…
amigcamel

87

Kullanımına düzeni "gerçekten de 2006-01-02T15:04:05.000Zanlatılan" RickyA 'ın cevabı .
"İlk gitme zamanı" değil, söz konusu düzeni hatırlamanın anımsatıcı bir yolu.
Bakın pkg / saat :

Yerleşimlerde kullanılan referans süresi:

Mon Jan 2 15:04:05 MST 2006

Unix zamanı 1136239445.
MST GMT-0700 olduğundan, referans süresi şu şekilde düşünülebilir:

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

(1,2,3,4,5,6,7, 1'in ay için olduğunu ve 2 gününün kendim gibi bir Avrupalı ​​için kolay olmadığını hatırlatırsak, gün-ay tarih biçiminde kullanılır)

" Time.parse: golang zamanı neden yanlış ayrıştırıyor? " Da gösterildiği gibi , bu düzene (1,2,3,4,5,6,7 kullanarak) tam olarak uyulmalıdır .


Evet bu Avustralyalıları da yakalar! MM / DD sadece benim için hesaplamıyor ve ona bakmaya devam etmeliyim.
Simon Whitehead

3
@SimonWhitehead katılıyorum. En azından, bir kez baktığımda, YY, MM, DD, hh, mm, ss'in ne anlama geldiğini biliyorum ve bunları kolayca yeniden sipariş edebilirim. Go ile, baktıktan sonra bile, 1, 2, 3, 4 ... 'in neyi temsil ettiğini hatırlamam gerekiyor.
VonC

1
Hatırlamamın yolu: Adım 1) "Uygun" tarih sıralaması yıl> ay> gün> saat> dakika> saniye> vb. (Karışık endianlar sadece duyusal olmayan keyfi ve tutarsız ve büyük tarihler için) endian, küçük-endian yerine tercih edilir, çünkü sıralama dostu.) Bu bize 1 (yıl), 2 (ay), 3 (gün), [...] Adım 2) Git / Google Amerikalı ve Amerikalılar yıl sonunda, bu yüzden 1 (ay), 2 (gün), [...], n (yıl) Adım 3) Zaman dilimi her şeyin peşinden gider çünkü zaman dilimleri ek bir soyutlama katmanıdır.
mtraceur


58

Yanıtlandığı gibi ancak "2006-01-02T15:04:05.000Z"düzen için yazmayı kaydetmek için paketin sabit RFC3339'unu kullanabilirsiniz .

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
Ek olarak, paket sabitlerine bakarsanız (yukarıdaki cevaba bağlı olarak), kullanılabilecek bir dizi başka yaygın format vardır. Biraz farklı bir şeye ihtiyacınız varsa, bunları başlangıç ​​noktası olarak kullanın.
Hugh

Bu ve çeşitli cevaplar 2006-01-02T15:04:05.000ZGo's'un time.RFC3339da işe yarayacağını önerir ve söyler . Ama time.RFC3339 = "2006-01-02T15:04:05Z07:00". Bu iki biçim tam olarak ne time.Parseve ne kadar eşdeğer time.ParseInLocationmidir?
Miles

1
Bu doğru @Miles, bu test onayladı play.golang.org/p/T3dW1kTeAHl
robstarbuck

24

Zaman paketinden time.RFC3339 sabitini kullanmanızı öneririm. Diğer sabitleri zaman paketinden kontrol edebilirsiniz. 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); 
}

Noktalı virgül kullanmak istediniz mi?
ChristoKiwi

20

Bu partiye oldukça geç ve aslında bir şekilde ya da başka bir şekilde söylenmemiş bir şey söylemiyor, çoğunlukla yukarıdaki bağlantılarla, ama TL vermek istedim; daha az dikkat süresi olanlara DR özeti:

Go biçimi dizesinin tarihi ve saati çok önemlidir. Go hangi alanın hangisi olduğunu nasıl bilir. Genellikle 1-9 soldan sağa aşağıdaki gibidir:

  • Ocak / Ocak / Ocak / Ocak / 01 / _1 (vb.) Ay içindir
  • 02 / _2 ayın günü için
  • 15/03 / _3 / PM / P / pm / p saat ve meridyen içindir (15:00)
  • 04 / _4 dakika içindir
  • 05 / _5 saniye içindir
  • 2006/06 yıl için
  • -0700 / 07:00 / MST saat dilimi için
  • .999999999 / .000000000 vb. Kısmi saniyeler içindir.
  • Pzt / pazartesi haftanın günüdür (01-02-2006 aslında),

Bu nedenle, "Ay-İkinci-Saat" istemiyorsanız, tarih biçiminiz olarak "01-05-15" yazmayın

(... yine, bu temelde yukarıdakilerin bir özetiydi.)


5

Bu çok geç olabilir, ancak bu sorunla karşılaşabilecek ve tarih dizesini ayrıştırmak için harici paket kullanmak isteyebilecek kişiler içindir.

Bir kütüphane aramaya çalıştım ve bunu buldum:

https://github.com/araddon/dateparse

README'den bir örnek:

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
Ne yazık ki, gün ay düzeninde bir belirsizlik var. Avrupa tarih formatı gün birinci ve ay ikinci verir ve ABD saat formatı tersini kullanır. 3/5/2004 gibi bir tarih belirsiz. Tarih ABD ve Avrupa biçiminde geçerlidir, ancak 3 ve 5 gün ve aya veya tersine karşılık gelebilir. dateParse, ABD biçimini kabul eder.
chmike

-1

Diğer dillerde saat / tarih biçimlendirme / ayrıştırma ile çalıştıysanız, diğer dillerin saat / tarih biçimlendirmesi için özel yer tutucular kullandığını fark etmiş olabilirsiniz. Örneğin yakut dili kullanımları için

%d for day
%Y for year

Golang, yukarıdaki gibi kodlar kullanmak yerine, yalnızca tarih ve saate benzeyen tarih ve saat formatı yer tutucularını kullanır. Go standart zamanı kullanır:

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

Yani Go'nun kullandığını fark ederseniz

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

Bu nedenle örneğin 2020-01-29 ayrıştırılması için mizanpaj dizisi 06-01-02 veya 2006-01-02 olmalıdır.

Bu bağlantıdaki tam yer tutucu düzen tablosuna başvurabilirsiniz - https://golangbyexample.com/parse-time-in-golang/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.