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を
Sonia Hamilton

あなたのレイアウトは2006-01-02T15:04:05.000Z、クレイジーゴーの標準によるものです
tharinduwijewardane

回答:


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は、日時コンポーネント(YYYY-MM-DD)に抽象的な構文を使用していませんが、これらの正確な数値を使用しています(これによると、Go Nopeの最初のコミットの時刻だと思います。誰か知っていますか?)。


118
レイアウト番号?何?どうして?ああ!
Darth Egregious 2015

29
彼らは何を考えていました!?または喫煙?
Jishnu Prathap 2017年

14
私はここでコメントに少し遅れるかもしれませんが、数値でのレイアウトを怖がらないで、定数を使用するだけでコードがクリーンになります:)たとえば、time.RFC3339
Davyd Dzhahaiev

11
レイアウト番号がわからない人にとっては、一見非常に異質であると認めますが、慣れれば、少なくとも一般的なレイアウトデバイスと同じくらい意味があると思います(「Dを使用するか、 「d」、「dd」、「DD」など)、そしておそらくもっと意味があります。最初にそれについて知っておく必要があります。
18

5
これはニーモニックな目的のためです。つまり、これらの文字を1、2、3、4、5、6、7覚えておく必要があります。:この議論素晴らしい記事がありますmedium.com/@simplyianm/...
amigcamel

85

実際に使用するレイアウト2006-01-02T15:04:05.000Zは、RickyA回答に記載されている「」です。
これは、「goの最初のコミット時」ではなく、前述のレイアウトを覚えておくためのニーモニックな方法です。pkg / timeを
参照してください。

レイアウトで使用される基準時間は次のとおりです。

Mon Jan 2 15:04:05 MST 2006

これはUnix時間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の意味がわかり、簡単に並べ替えることができます。囲碁では、調べた後でも、1、2、3、4 ...の意味を覚えておく必要があります。
VonC、2014

1
私が覚えている方法は次のとおりです。ステップ1)「適切な」日付順は、年>月>日>時間>分>秒>などです(混合エンディアンは、意味のない任意で一貫性がなく、日付が大きいため、エンディアンはリトルエンディアンよりも望ましいです。並べ替えに対応しています。)これにより、1(年)、2(月)、3(日)、[...] ステップ2) Go / Googleはアメリカ人であり、アメリカ人は日付の最後の年、つまり1(月)、2(日)、[...]、n(年)です。ステップ3)タイムゾーンは追加の抽象化レイヤーであるため、タイムゾーンは他のすべての後に続きます。
mtraceur

はい@mtraceur ...私、あまりにもミスweb.archive.org/web/20180501100155/http://...(からgithub.com/bdotdub/fuckinggodateformat)。strftimeつまり、FTW。
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"。これらの2つの形式は、何をしtime.Parsetime.ParseInLocation実行するのかに関して、まったく同じですか?
Miles

1
それは正しい@Miles、このテストを確認それだ play.golang.org/p/T3dW1kTeAHl
robstarbuckを

24

timeパッケージの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形式文字列の日付と時刻は非常に重要です。Goがどのフィールドがどのフィールドであるかを知る方法です。通常、次のように左から右に1〜9です。

  • 1月/ 1月/ 1月/ 1月/ 01 / _1(など)は月
  • 02 / _2は月の日
  • 15/03 / _3 / PM / P / pm / pは時間と子午線(3pm)
  • 04 / _4は分
  • 05 / _5は秒
  • 2006/06は年間
  • -0700 / 07:00 / MSTはタイムゾーン用
  • .999999999 / .000000000などは秒の一部です(違いは末尾のゼロが削除されているかどうかです)
  • 月曜日/月曜日は曜日(2006年1月2日は実際には曜日でした)、

そのため、「月-秒-時間」が必要でない限り、日付形式として「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
残念ながら、日と月の順序はあいまいです。ヨーロッパの日付形式は日を最初に、月を2番目に、米国の時間形式はその逆を使用します。2004年3月5日のような日付はあいまいです。日付は米国とヨーロッパの形式で有効ですが、3と5は日と月、またはその逆に対応する場合があります。dateParseはUS形式を想定しています。
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.