Phân tích chuỗi ngày trong Go


138

Tôi đã thử phân tích chuỗi ngày "2014-09-12T11:45:26.371Z"trong Go.

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

Tôi đã nhận được lỗi này:

thời gian phân tích cú pháp "2014-11-12T11: 47: 39.489Z": tháng nằm ngoài phạm vi

Làm thế nào tôi có thể phân tích chuỗi ngày này?


Đối với độc giả trong tương lai, tôi đã viết một số bài tập để thực hành phân tích ngày github.com/soniah/date_practice
Sonia Hamilton

Bố cục của bạn chính xác là 2006-01-02T15:04:05.000Zdo một số tiêu chuẩn điên rồ
tharinduwijewardane

Câu trả lời:


164

Sử dụng số bố cục chính xác được mô tả ở đây và một blogpost tốt đẹp ở đây .

vì thế:

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)

cho:

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

Tôi biết. Tâm boggling. Cũng bắt gặp tôi lần đầu tiên. Go chỉ không sử dụng một cú pháp trừu tượng cho các thành phần datetime ( YYYY-MM-DD), nhưng những con số chính xác này ( tôi nghĩ rằng thời gian của cam kết đầu tiên của Nope, theo điều này . Có ai biết không?).


118
Bố cục số? Gì? Tại sao? Argh!
Darth Egregious

29
Họ đã nghĩ gì! ? hay hút thuốc?
Jishnu Prathap

14
Tôi có thể hơi muộn với các bình luận ở đây, nhưng đừng sợ bố cục với các số, chỉ cần sử dụng các hằng số và mã của bạn sẽ sạch :), ví dụ như thời gian.RFC3339
Davyd Dzhahaiev

11
Đối với những người không nhận được số bố cục, tôi thừa nhận thoạt nhìn rất xa lạ, nhưng một khi bạn đã quen với nó, tôi nghĩ nó ít nhất có ý nghĩa như các thiết bị bố trí thông thường ('Tôi có sử dụng "D" không, "D", "dd", "DD", v.v?), và có lẽ có ý nghĩa hơn. Bạn chỉ cần biết về nó đầu tiên.
ba giờ

5
Đó là cho mục đích ghi nhớ, nghĩa là bạn chỉ cần nhớ 1, 2, 3, 4, 5, 6, 7 những chữ cái này. Có một bài viết tuyệt vời thảo luận về điều này: Medium.com/@simplyianm/ Từ
amigcamel

85

Bố cục để sử dụng thực sự là " 2006-01-02T15:04:05.000Z" được mô tả trong câu trả lời của RickyA . Đó không phải là "thời gian của lần đầu tiên đi", mà là một cách ghi nhớ để nhớ bố cục. Xem pkg / lần :

Thời gian tham chiếu được sử dụng trong các bố cục là:

Mon Jan 2 15:04:05 MST 2006

đó là thời gian Unix 1136239445.
Vì MST là GMT-0700, thời gian tham chiếu có thể được coi là

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

(1,2,3,4,5,6,7, miễn là bạn nhớ rằng 1 là cho tháng và 2 cho ngày, điều này không dễ đối với một người châu Âu như tôi, được sử dụng cho định dạng ngày tháng)

Như được minh họa trong " time.parse: tại sao golang phân tích thời gian không chính xác? ", Bố cục đó (sử dụng 1,2,3,4,5,6,7) phải được tôn trọng chính xác .


Vâng, điều đó cũng bắt người Úc! MM / DD chỉ không tính toán cho tôi và tôi phải tiếp tục xem xét nó.
Simon Whitehead

3
@SimonWhitehead Tôi đồng ý. Ít nhất, một khi tôi tìm kiếm nó, tôi biết YY, MM, DD, hh, mm, ss là gì và tôi có thể đặt hàng lại chúng một cách dễ dàng. Với Go, ngay cả sau khi tìm kiếm nó, tôi cần nhớ những gì 1, 2, 3, 4 ... đại diện cho.
VonC

1
Cách tôi nhớ là: Bước 1) Thứ tự ngày "thích hợp" là năm> tháng> ngày> giờ> phút> giây> v.v (Bởi vì người kết hợp sẽ không độc đoán và không nhất quán và cho ngày lớn- endian thích hợp hơn endian nhỏ vì nó thân thiện với mọi người.) Điều này sẽ giúp chúng tôi 1 (năm), 2 (tháng), 3 (ngày), [...] Bước 2) Đi / Google là người Mỹ và người Mỹ đặt năm vào cuối ngày của họ, vì vậy thay vào đó là 1 (tháng), 2 (ngày), [...], n (năm) Bước 3) Múi giờ đi sau mọi thứ khác vì múi giờ là một lớp trừu tượng bổ sung.
mtraceur

@mtraceur Có ... Tôi cũng rất nhớ web.archive.org/web/20180501100155/http://th (từ github.com/bdotdub/fuckinggodateformat ). Ý tôi là, strftimeFTW.
VonC

58

Như đã trả lời nhưng để lưu kiểu gõ "2006-01-02T15:04:05.000Z"cho bố cục, bạn có thể sử dụng RFC3339 không đổi của gói .

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
Ngoài ra, nếu bạn nhìn vào các hằng số gói (được liên kết trong câu trả lời ở trên), có một loạt các định dạng phổ biến khác được cung cấp có thể được sử dụng. Nếu bạn cần một cái gì đó hơi khác nhau, sử dụng chúng như một điểm khởi đầu.
Hugh

Điều này và một số câu trả lời đề nghị 2006-01-02T15:04:05.000Zvà đề cập rằng Go's time.RFC3339cũng sẽ hoạt động. Nhưng time.RFC3339 = "2006-01-02T15:04:05Z07:00". Là hai định dạng chính xác tương đương trong chừng mực như những gì time.Parsetime.ParseInLocationsẽ làm gì?
Miles

1
Đúng vậy @Miles, bài kiểm tra này xác nhận nó play.golang.org/p/T3dW1kTeAHl
robstarbuck

24

Tôi sẽ đề nghị sử dụng hằng số time.RFC3339 từ gói thời gian. Bạn có thể kiểm tra các hằng số khác từ gói thời gian. 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); 
}

Ý của bạn là sử dụng dấu chấm phẩy?
ChristoKiwi

20

Điều này khá muộn cho bữa tiệc, và không thực sự nói bất cứ điều gì chưa được nói dưới dạng này hay dạng khác, chủ yếu thông qua các liên kết ở trên, nhưng tôi muốn đưa ra một bản tóm tắt TL; DR cho những người ít chú ý hơn:

Ngày và thời gian của chuỗi định dạng đi là rất quan trọng. Đó là cách Go biết lĩnh vực nào. Chúng thường từ 1-9 trái sang phải như sau:

  • Tháng 1 / tháng 1 / tháng một / tháng một / 01 / _1 (vv) là cho tháng
  • 02 / _2 là cho ngày trong tháng
  • 15/03 / _3 / PM / P / pm / p dành cho giờ & kinh tuyến (3 giờ chiều)
  • 04 / _4 là trong vài phút
  • 05 / _5 là trong vài giây
  • 2006/06 là cho năm
  • -0700 / 07:00 / MST dành cho múi giờ
  • .999999999 / .000000000, v.v. chỉ trong một phần giây (Tôi nghĩ rằng sự khác biệt là nếu các số 0 ở cuối được loại bỏ)
  • Thứ Hai / Thứ Hai là ngày trong tuần (mà ngày 01/02/2006 thực sự là),

Vì vậy, đừng viết "01-05-15" dưới dạng định dạng ngày của bạn, trừ khi bạn muốn "Tháng-Giờ-Giờ"

(... Một lần nữa, đây về cơ bản là một bản tóm tắt ở trên.)


5

Điều này có thể là siêu muộn, nhưng điều này là dành cho những người có thể vấp phải vấn đề này và có thể muốn sử dụng gói bên ngoài để phân tích chuỗi ngày.

Tôi đã thử tìm kiếm một thư viện và tôi tìm thấy thư viện này:

https://github.com/araddon/dateparse

Ví dụ từ 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
Thật không may, có một sự mơ hồ trong thứ tự ngày tháng. Định dạng ngày châu Âu cung cấp ngày đầu tiên và tháng thứ hai và định dạng thời gian Hoa Kỳ sử dụng ngược lại. Một ngày như 3/5/2004 là mơ hồ. Ngày có giá trị ở định dạng Hoa Kỳ và Châu Âu, nhưng 3 và 5 có thể tương ứng với ngày và tháng hoặc ngược lại. datePude giả định định dạng Hoa Kỳ.
chmike

-1

Nếu bạn đã làm việc với định dạng thời gian / ngày / phân tích cú pháp bằng các ngôn ngữ khác, bạn có thể nhận thấy rằng các ngôn ngữ khác sử dụng trình giữ chỗ đặc biệt để định dạng thời gian / ngày. Ví dụ: sử dụng ngôn ngữ ruby

%d for day
%Y for year

vv Golang, thay vì sử dụng các mã như ở trên, sử dụng các trình giữ chỗ định dạng ngày và giờ trông giống như ngày và giờ. Đi sử dụng thời gian tiêu chuẩn, đó là:

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

Vì vậy, nếu bạn nhận thấy sử dụng Go

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

Do đó, ví dụ để phân tích cú pháp 2020-01-29, chuỗi bố cục phải là 06-01 / 02 hoặc 2006-01 / 02.

Bạn có thể tham khảo bảng bố trí giữ chỗ đầy đủ tại liên kết này - https://golangbyexample.com/parse-time-in-golang/

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.