楽に Go で ISO 8601 の日付と時刻を扱ってみる
この記事では github.com/Code-Hex/synchro/iso8601 というライブラリを使って ISO 8601 形式の文字列を Go で扱ってみます。
ISO 8601 の形式を採用した日付(2023-09-11
)や時間(12:00:00
)をよくコードの中で扱うのではないのでしょうか。
ISO 8601 について:
ISO 8601 は "Data elements and interchange formats--Information interchange--Representation of dates and times" (和訳: 情報交換のためのデータ要素及び交換方式ー日付及び時刻の表記) というタイトルが表すように、コンピュータ間で日付と時刻の送受信を行うためのフォーマットを規定する規格です。ISO 8601 以前にも日付と時刻の表現を定めた規格は複数存在していましたが、ISO 8601 はそれらを統合した規格となっています。現行版は第 3 版にあたる ISO 8601:2004 です。
日付
ISO 8601 で扱える日付は次のようなものがあります:
- 暦日付 (calendar date)
- 標準形式: YYYYMMDD (拡張形式: YYYY-MM-DD)
- 例:
20140321
,2014-03-21
- 年間通算日 (ordinal date)
- 標準形式: YYYYDDD (拡張形式: YYYY-DDD)
- 例:
2014080
,2014-080
- 暦週日付 (week date)
- 標準形式: YYYYWwwD (拡張形式: YYYY-Www-D)
- 例:
2014W125
,2014-W12-5
また各言語のライブラリによって、クオーター形式の日付にも対応されているケースがあります。
- クオーター日付 (quarter date)
- 標準形式: YYYYQqDD (拡張形式: YYYY-Qq-DD)
- 例:
2014Q180
,2014-Q4-80
iso8601.ParseDateTime
関数もしくは iso8601.ParseDate
関数を利用します。 iso8601.ParseDateTime
は time.Time
を返しますが、iso8601.ParseDate
は DateLike
interface を返します。
func main() {
// calendar date
t1, _ := iso8601.ParseDateTime("20140321")
// ordinal date
t2, _ := iso8601.ParseDateTime("2014080")
// week date
t3, _ := iso8601.ParseDateTime("2014W125")
// quarter date
t4, _ := iso8601.ParseDateTime("2014Q180")
}
Playground
時刻
- 時刻
- 基本形式: hhmmss (拡張形式: hh:mm:ss)
- 小数を含む時刻
-
.
(ピリオド)もしくは,
(カンマ)で区切ります。 - 基本形式: hhmmss.sssssssss (拡張形式: hh:mm:ss.sssssssss)
- 基本形式: hhmm.mmmmmmmmm (拡張形式: hh:mm.mmmmmmmmm)
- 基本形式: hh.hhhhhhhhh (拡張形式: hh.hhhhhhhhh)
-
時刻のみをパースする場合は iso8601.ParseTime
を利用します。この関数はタイムゾーンを含めない、ISO 8601 の時刻を表現する構造体 Time
を返します。
func main() {
t1, _ := iso8601.ParseTime("24:00:00")
t2, _ := iso8601.ParseTime("23:59:59.999999999")
t3, _ := iso8601.ParseTime("2359.5") // 23:59:30
t4, _ := iso8601.ParseTime("23.5") // 23:30:00
}
Playground
日付と時刻の組み合わせ
前述した、日付と時刻の形式の組み合わせの文字列を iso8601.ParseDateTime
を利用することで time.Time
へ変換できます。またタイムゾーンを含めることもできます。
標準ライブラリのようにレイアウトを指定しなくてもいいので、とても便利ですね!
func main() {
s := "2017-04-24T09:41:34.89312523"
t1, _ := iso8601.ParseDateTime(s) // local time
fmt.Println(t1)
t2, _ := iso8601.ParseDateTime(s + "Z") // UTC
fmt.Println(t2)
t3, _ := iso8601.ParseDateTime(s + "+09:00") // +09:00
fmt.Println(t3)
s2 := "2017-04-24 09:41:34.89312523" // 'T' ではなく ' ' を区切りにする
t4, _ := iso8601.ParseDateTime(s2, iso8601.WithTimeDesignators(' '))
fmt.Println(t4)
}
Playground
タイムゾーンファーストで ISO 8601 を使う
github.com/Code-Hex/synchro/iso8601 は synchro
のサブパッケージです。
synchro
は time.Time
をタイムゾーンを含めた型として扱うことができるライブラリです。
synchro.ParseISO
関数を利用することで、型で指定したタイムゾーンの出力を保証しながら、ISO 8601 の日付、時刻の文字列を扱うことが可能です。
func main() {
s := "2017-04-24T09:41:34.89312523"
t1, _ := synchro.ParseISO[tz.AsiaTokyo](s) // local time
fmt.Println(t1)
t2, _ := synchro.ParseISO[tz.AsiaTokyo](s + "Z") // UTC
fmt.Println(t2)
t3, _ := synchro.ParseISO[tz.AsiaTokyo](s + "+09:00") // +09:00
fmt.Println(t3)
}
// 2017-04-24 18:41:34.89312523 +0900 JST
// 2017-04-24 18:41:34.89312523 +0900 JST
// 2017-04-24 09:41:34.89312523 +0900 JST
Playground
最後に
今回は、synchro
とそのサブパッケージである github.com/Code-Hex/synchro/iso8601 を紹介しました。このライブラリを使用することで、ISO 8601 の日付と時刻の扱いが Go で非常にシンプルになり、さらにタイムゾーンを型として保証することが可能になります。
また、このライブラリはまだ開発途中の段階にあり、新しい機能の追加や改善を続けています。
使用してみて感じたこと、改善したい点などがあれば、ぜひ GitHub のリポジトリにフィードバックとして共有してください!
Discussion