Go에서 날짜 문자열 파싱


138

"2014-09-12T11:45:26.371Z"Go 에서 날짜 문자열 을 구문 분석하려고했습니다 .

암호

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

이 오류가 발생했습니다.

구문 분석 시간 "2014-11-12T11 : 47 : 39.489Z": 달이 범위를 벗어남

이 날짜 문자열을 어떻게 구문 분석 할 수 있습니까?


미래의 독자를 위해, 나는 날짜 구문 분석 연습에 대한 몇 가지 운동을 쓴 github.com/soniah/date_practice을
소니아 해밀턴에게

귀하의 레이아웃은 정확하게 2006-01-02T15:04:05.000Z미쳐가는 표준으로
이루어져야

답변:


164

여기에 설명 된 정확한 레이아웃 번호 와 여기 에 멋진 블로그 게시물을 사용 하십시오 .

그래서:

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)

제공합니다 :

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

알아. 흔들리는 마음. 또한 처음으로 나를 잡았다. Go는 datetime 구성 요소 ( YYYY-MM-DD)에 추상 구문을 사용하지 않지만 정확한 숫자입니다 ( 이것 에 따르면 go Nope 의 첫 번째 커밋 시간은 누구나 알고 있습니다.).


118
레이아웃 번호? 뭐? 왜? 아아!
Darth Egregious

29
그들은 무엇을 생각하고 있었습니까! ? 또는 흡연?
Jishnu Prathap

14
여기 의견에 조금 늦게 될 수도 있지만 숫자와 레이아웃을 무서워하지 않는, 단지 상수를 사용하여 코드 : 예 time.RFC3339 깨끗한 것
다빗 Dzhahaiev

11
레이아웃 번호를 얻지 못한 사람들에게는 언뜻보기에는 매우 외국인이라는 것을 인정하지만 일단 익숙해지면 적어도 일반적인 레이아웃 장치만큼 의미가 있다고 생각합니다 ( 'D'를 사용합니까? "d", "dd", "DD"등?), 아마도 더 의미가 있습니다. 먼저 알아야합니다.
3시

5
그것은 니모닉 목적으로, 즉이 글자들을 1, 2, 3, 4, 5, 6, 7 만 기억하면됩니다. 이것을 논의하는 훌륭한 기사가 있습니다 : medium.com/@simplyianm/…
amigcamel

85

사용할 레이아웃 2006-01-02T15:04:05.000ZRickyA답변 에 실제로 설명되어 있습니다.
"가는 첫 커밋의 시간"이 아니라, 레이아웃을 기억하는 기억에 남는 방법입니다. pkg / 시간
참조 :

레이아웃에 사용 된 참조 시간은 다음과 같습니다.

Mon Jan 2 15:04:05 MST 2006

유닉스 시간 1136239445입니다.
MST는 GMT-0700이므로 참조 시간은 다음과 같이 생각할 수 있습니다.

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

(1,2,3,4,5,6,7, 1은 월, 2는 하루와 같은 것으로, 나 자신과 같은 유럽인에게는 쉽지 않은 일입니다.

" time.parse : 왜 golang이 시간을 잘못 구문 분석합니까? "에 설명 된대로 해당 레이아웃 (1,2,3,4,5,6,7 사용)은 정확하게 존중되어야합니다 .


그래, 호주인들도 따라 잡는다! MM / DD는 단지 나를 위해 계산하지 않으며 계속 살펴 봐야합니다.
Simon Whitehead

3
@SimonWhitehead 동의합니다. 적어도 일단 검색하면 YY, MM, DD, hh, mm, ss의 의미를 알고 쉽게 다시 주문할 수 있습니다. Go를 사용하면 검색 한 후에도 1, 2, 3, 4 ...의 의미를 기억해야합니다.
VonC

1
내가 기억하는 방법은 다음과 같습니다. 1 단계) "적절한"날짜 순서는 연도> 월> 일> 시간> 분> 초> 등입니다 (혼합 엔디안은 비 의도적으로 임의적이고 일관성이 없으며 날짜가 큰 경우). endian은 친절하기 때문에 little-endian보다 선호됩니다.) 이것은 우리에게 1 년, 2 개월, 3 일, [...] 단계 2) Go / Google은 미국인이며 미국인들은 날짜가 끝날 때 연도이므로 1 (월), 2 (일), [...], n (년)입니다. 3 단계) 시간대는 추가 추상화 계층이므로 시간대는 다른 모든 요소를 ​​따릅니다.
mtraceur

@mtraceur 예 ... 나는 너무 그리워 web.archive.org/web/20180501100155/http://...는 (에서 github.com/bdotdub/fuckinggodateformat ). 내 말은, strftimeFTW.
VonC

58

답변했지만 "2006-01-02T15:04:05.000Z"레이아웃 입력을 저장 하기 위해 패키지의 상수 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
또한 패키지 상수 (위의 답변에 링크 됨)를 보면 사용할 수있는 다른 일반적인 형식이 많이 있습니다. 약간 다른 것이 필요한 경우 시작점으로 사용하십시오.

이 답변과 여러 답변 2006-01-02T15:04:05.000Z은 Go의 기능 time.RFC3339이 작동 한다고 제안 하고 언급합니다 . 그러나 time.RFC3339 = "2006-01-02T15:04:05Z07:00". 이 두 형식은 무엇을 time.Parse하고 time.ParseInLocation어떻게 할 것인가에 따라 정확히 동일 합니까?
Miles

1
맞습니다. @ Miles입니다.이 테스트는 play.golang.org/p/T3dW1kTeAHl을
robstarbuck

24

시간 패키지에서 time.RFC3339 상수를 사용하는 것이 좋습니다. 시간 패키지에서 다른 상수를 확인할 수 있습니다. 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); 
}

세미콜론을 사용 했습니까?
ChristoKiwi

20

이것은 당에 다소 늦었고, 실제로 위의 링크를 통해 이미 어떤 형태로든 말하지 않은 것을 말하지는 않지만 TL; DR을 관심이 적은 사람들에게 요약하고 싶었습니다.

이동 형식 문자열의 날짜와 시간은 매우 중요합니다. Go가 어떤 필드가 어떤 필드인지 아는 방법입니다. 그것들은 일반적으로 다음과 같이 왼쪽에서 오른쪽으로 1-9입니다 :

  • 1 월 / 1 월 / 1 월 / 1 월 / 01 / _1 등
  • 02 / _2는 요일입니다
  • 15 / 03 / _3 / PM / P / pm / p는 시간 및 자오선 용입니다 (오후 3시)
  • 04 / _4 분
  • 05 / _5는 초입니다
  • 2006/06 년
  • -0700 / 07:00 / MST는 시간대입니다
  • .999999999 / .000000000000 등은 부분 초입니다 (후행 0을 제거하면 구별이 있다고 생각합니다)
  • 월요일 / 월요일은 요일입니다 (실제로 01-02-2006).

따라서 "Month-Second-Hour"를 원하지 않는 한 "01-05-15"를 날짜 형식으로 쓰지 마십시오.

(... 다시, 이것은 기본적으로 위의 요약이었습니다.)


5

이것은 매우 늦을 수 있지만이 문제가 발생하여 날짜 문자열을 구문 분석하기 위해 외부 패키지를 사용하려는 사람들을위한 것입니다.

나는 도서관을 찾으려고 노력했으며 이것을 찾았습니다.

https://github.com/araddon/dateparse

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
불행히도, 일 월 순서에는 모호성이 있습니다. 유럽 ​​날짜 형식은 1 일 1 초를 제공하고 미국 시간 형식은 그 반대로 사용합니다. 2004 년 3 월 5 일과 같은 날짜는 모호합니다. 날짜는 미국 및 유럽 형식으로 유효하지만 3과 5는 일과 월 또는 그 반대 일 수 있습니다. dateParse 는 미국 형식을 가정합니다.
chmike

-1

다른 언어로 시간 / 날짜 형식 / 구문 분석을 수행 한 경우 다른 언어가 시간 / 날짜 형식에 특수 자리 표시자를 사용하는 것을 알 수 있습니다. 예를 들어 루비 언어는

%d for day
%Y for year

Golang은 위와 같은 코드를 사용하는 대신 날짜 및 시간 만 보이는 날짜 및 시간 형식 자리 표시자를 사용합니다. Go는 표준 시간을 사용합니다.

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

Go가 사용하는 것을 발견하면

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

따라서 2020-01-29 구문 분석의 경우 레이아웃 문자열은 06-01-02 또는 2006-01-02 여야합니다.

이 링크 ( https://golangbyexample.com/parse-time-in-golang/) 에서 전체 자리 표시 자 레이아웃 테이블을 참조 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.