The Gopher character is based on the Go mascot designed by Renée French.
Gopherのイラストはegonelbre/gophersを利用しました。
はじめに
TIG/EXユニット所属の宮永です。 Go 1.20連載の4本目です。
Go 1.20 Release Notesに記載のMinor changes to the libraryのtime
パッケージのアップデート4点について解説します。
1. layoutにDateTime
,DateOnly
,TimeOnly
が追加された
Proposalはこちらのissueでされています。
Goの日時表現ですが、他の多くの言語とは勝手が異なります。
今回のアップデートを確認する前に他の言語とGoとの日時表現の違いについて確認します。
例えば、Pythonでyyyy-mm-dd
という形式でフォーマットをかける場合は以下の様にします。
from datetime import datetime |
Rustの場合は以下の様にします。
use chrono::Utc; |
いずれの場合も文字列%Y-%m-%d
を与えてフォーマットしています。
ではGoの場合はどうでしょうか。
package main |
2006-01-02
?
はじめて見たとき2006-01-02
って何がなんだかわかりませんでした。
ググってみるとこんな記事がありました。
Goのtimeパッケージのリファレンスタイム(2006年1月2日)は何の日?
答えは単純だ。これはアメリカ式の時刻の順番なのだ。”1月2日午後3時4分5秒2006年”(つまり「自然な順番」で1, 2, 3, 4, 5, 6)を指しているのである。Go開発者のRob Pikeさんがgolang-nutsメーリングリストで、最初からよく考えていればこの順番にはしなかったと言っていたが(英語圏でもイギリスとかだと違う順番だしね)、もうその順番になっているので変えられないし、それにきちんと文章化もされているともコメントしていた。従ってこれは単純にそういうものだと思うしかなさそうだ。
そんな馬鹿な!と思いましたが受け入れるしかありません。正直2006-01-02
の文字列、私は覚えられないので毎度コピー&ペーストしてます。
▼おとなりのチームにも同じ悩みを抱えている方がいました
(その気持ちとてもわかります!!!)
今回のアップデートでyyyy-mm-dd
は以下の様にできます。
package main |
これなら私でも覚えられます。
些細なアップデートですが、待ち望んでいた方は多かったのではないでしょうか。
今回追加された定数ですが、それぞれの以下のように定義されています。
DateTime = "2006-01-02 15:04:05" |
2. Time.Compare
メソッドの追加
Proposalはこちらのissueでされています。
Proposalを立てた方の主張をまとめると
「Time型の比較には
Before()
、Equal()
、After()
の3つがあるが、これはそれぞれ<
、==
、>
に相当する。以前、以後を表す<=
、>=
のメソッドもほしい!!」
ということです。たしかに以前、以後というメソッドがないため、Go1.20がリリースされる前までは
以前を表すのに!x.After(y)
(>
の否定)で<=
となる)とするしかありませんでした。
x.Equal(y) || x.Before(y)
でもいいですね
今回Time.Compare
メソッドの追加により以前、以後は以下の様に表現することが可能になりました。
以前(xはyよりも前) ⇒
x.Compare(y)<=0
以後(xはyよりも後) ⇒
x.Compare(y)>=0
Compare
メソッドはGoの他のライブラリも同じようなルールで実装されているため、使い勝手も良さそうです。今後頻繁に使う機会が出てきそうです。
3. Parse
でナノ秒以下の入力の精度は無視する様になった
issueはこちらです。
issueにかかれているコードをそのまま引用します。
package main |
入力として0が10個並んでおり、厳密にいえばRFC3339Nano
が期待している桁数よりも多い状況です。
このコードの出力としては両者とも2021-09-29 16:04:33 +0000 UTC <nil>
を期待していますが、実際には以下の様に出力されます。
2021-09-29 16:04:33 +0000 UTC <nil> |
Go 1.20では、2つ目の例でエラーとならないように、ナノ秒以下の精度が入力の場合には無視するようになります。
4. Time.MarshalJSON
メソッドのRFC3339
への準拠がより厳格になった
あれTime.Marshal
だけ?Time.Unmarshal
はいいの?
と思ったのですが、こちらのissueに経緯が書かれていました。
こちらのissueの対応でTime.Unmarshal
とTime.Marshal
のRFC3339
への準拠がより厳格になったということですが、Time.Unmarshal
の対応でAWS SDKのテストでエラーがでてしまうという事態になったようです。そのためTime.Unmarshal
についてはロールバックされ、Go1.20ではTime.Marshal
のみGo 1.20 Release Notesに記載されているということみたいです。
こちらのissueによると既存のParse
にはいくつか問題があるようで、もともとはこの問題に対応するためにTime.Unmarshal
で厳格な対応を入れたかったようです。
例えば、現行のParse
では少数部の.
と,
を区別していないようで、どちらもエラーなくParse
されるようです。
import ( |
0000-01-01 00:00:00 +0000 UTC |
他には時間の桁が1桁を許容するという問題もあるようで、00:00:00.000Z
と書くべきところを0:00:00.000Z
としてもParse
されるようです。
package main |
0000-01-01 00:00:00 +0000 UTC |
確かにこのままでは定義が明確ではなくなるため対応が必要そうですが、AWS SDKのテストでエラーがでてくるとなると影響は大きそうです。time
はGo1.21でも変更がありそうですね。
まとめ
本記事ではGo 1.20リリースのtime
パッケージのアップデートについて解説しました
- layoutに
DateTime
,DateOnly
,TimeOnly
が追加された Time.Compare
メソッドの追加によって以前、以後が表現できるようになったParse
でナノ秒以下の入力の精度は無視する様になったTime.MarshalJSON
メソッドのRFC3339
への準拠がより厳格になった
個人的にはlayoutに定数が追加されたアップデートが地味に嬉しかったです。😀
次は辻さんの HTTP ResponseControllerです。