[インデックス 19261] ファイルの概要
このコミットは、Go言語の標準ライブラリであるtime
パッケージにおけるタイムゾーン名のパースロジックの改善に関するものです。具体的には、小文字を含むタイムゾーン略語の特殊処理に、新たに「MeST (America/Metlakatla)」を追加し、関連するテストケースも更新しています。これにより、time
パッケージがより多くのタイムゾーン略語を正確に認識できるようになります。
コミット
commit 70f6c430248d57d40bef52fbd8c2c03c72badc16
Author: Rui Ueyama <ruiu@google.com>
Date: Wed Apr 30 11:30:36 2014 -0400
time: MeST is a time zone name
Not only ChST but also MeST (America/Metlakatla) is a zone
name containing a lower case letter.
LGTM=robert.hencke, r
R=golang-codereviews, robert.hencke, bradfitz, r
CC=golang-codereviews
https://golang.org/cl/99910043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/70f6c430248d57d40bef52fbd8c2c03c72badc16
元コミット内容
time: MeST is a time zone name
Not only ChST but also MeST (America/Metlakatla) is a zone
name containing a lower case letter.
LGTM=robert.hencke, r
R=golang-codereviews, robert.hencke, bradfitz, r
CC=golang-codereviews
https://golang.org/cl/99910043
変更の背景
Go言語のtime
パッケージは、日付と時刻のフォーマットやパースにおいて、様々なタイムゾーン略語を認識する必要があります。通常、タイムゾーンの略語(例: "EST", "PST", "GMT"など)は大文字で構成されています。しかし、一部のタイムゾーン略語には小文字が含まれるものがあり、これらはtime
パッケージのパースロジックにおいて特殊な扱いが必要でした。
これまでの実装では、"ChST" (Chamorro Standard Time) が小文字を含む唯一の既知のタイムゾーン略語として特別に処理されていました。しかし、新たに「MeST (America/Metlakatla)」も小文字を含むタイムゾーン略語であることが判明しました。このコミットは、time
パッケージが"MeST"を正しくタイムゾーン名として認識できるように、既存の特殊処理ロジックを拡張することを目的としています。これにより、Goアプリケーションが"MeST"を含む時刻文字列を正確にパースできるようになり、タイムゾーンの互換性と堅牢性が向上します。
前提知識の解説
Go言語のtime
パッケージ
Go言語のtime
パッケージは、日付と時刻を扱うための標準ライブラリです。時刻の表現、期間の計算、時刻のフォーマットとパース、タイムゾーンの変換など、幅広い機能を提供します。特に、time.Parse
関数やtime.Format
関数は、特定のレイアウト文字列に基づいて時刻を文字列に変換したり、文字列から時刻をパースしたりするために使用されます。
タイムゾーンとタイムゾーン略語
タイムゾーンは、地球上の特定の地域で共通して使用される標準時を定義します。タイムゾーンは通常、UTC(協定世界時)からのオフセット(例: UTC-5時間)と、夏時間(Daylight Saving Time, DST)の有無によって定義されます。
タイムゾーン略語は、特定のタイムゾーンを簡潔に表すために使用される短い文字列です。例えば、"EST"はEastern Standard Time(東部標準時)、"PST"はPacific Standard Time(太平洋標準時)を指します。これらの略語は、通常3文字または4文字の大文字で構成されます。
しかし、一部のタイムゾーン略語には、歴史的経緯や特定の地域の慣習により、小文字が含まれる場合があります。このコミットで言及されている「ChST」と「MeST」がその例です。
- ChST (Chamorro Standard Time): グアムや北マリアナ諸島で使用されるタイムゾーンで、UTC+10のオフセットを持ちます。
- MeST (Metlakatla Standard Time): アメリカ合衆国アラスカ州のメトラカトラ(Metlakatla)で使用されるタイムゾーンで、UTC-8のオフセットを持ちます。これは、アラスカ州の大部分がアラスカ標準時(AKST/AKDT)を使用するのに対し、メトラカトラは太平洋標準時(PST/PDT)に準拠しているため、独自の略語が使われることがあります。
time
パッケージにおけるタイムゾーンのパース
time
パッケージが時刻文字列をパースする際、タイムゾーン略語を識別するために内部的なロジックを使用します。このロジックは、既知のタイムゾーン略語のリストと照合したり、特定のパターン(例: "GMT"の後に続くオフセット)を認識したりします。
特に、src/pkg/time/format.go
内のparseTimeZone
関数は、文字列の特定の部分が有効なタイムゾーン名であるかどうかを判断する役割を担っています。この関数は、タイムゾーン略語の長さや文字構成に基づいて、その有効性をチェックします。
通常の大文字のみの略語とは異なり、小文字を含む略語は、一般的なパターンマッチングでは見落とされがちです。そのため、time
パッケージでは、これらの特殊なケースを明示的に処理するための「特別扱い」のロジックが導入されていました。
技術的詳細
このコミットの技術的な核心は、src/pkg/time/format.go
ファイル内のparseTimeZone
関数の修正にあります。
parseTimeZone
関数は、時刻文字列からタイムゾーン情報を抽出する際に呼び出される内部関数です。この関数は、入力文字列の先頭からタイムゾーン略語を認識しようと試みます。
変更前のparseTimeZone
関数には、以下のようなコメントとロジックがありました。
// Special case 1: This is the only zone with a lower-case letter.
if len(value) >= 4 && value[:4] == "ChST" {
return 4, true
}
このコードは、「小文字を含む唯一のタイムゾーン」として"ChST"を特別に扱っていました。value
の先頭4文字が"ChST"と完全に一致する場合にのみ、それを有効なタイムゾーンとして認識し、4文字の長さを返していました。
このコミットでは、この「Special case 1」のロジックが以下のように変更されました。
// Special case 1: ChST and MeST are the only zones with a lower-case letter.
if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
return 4, true
}
この変更により、parseTimeZone
関数は、入力文字列の先頭4文字が"ChST"であるか、または"MeST"であるかのいずれかの場合に、それを有効なタイムゾーン略語として認識するようになりました。論理OR演算子||
が導入され、両方のケースをカバーしています。
この修正は、time
パッケージがタイムゾーン略語をパースする際の堅牢性を高めます。特に、小文字を含むタイムゾーン略語は一般的ではないため、このような明示的なホワイトリスト方式で処理することは、誤認識を防ぎ、正確なパースを保証するために重要です。
また、src/pkg/time/format_test.go
には、この変更を検証するための新しいテストケースが追加されました。
{"MeST hi there", 4, true},
このテストケースは、"MeST hi there"という文字列が与えられたときに、parseTimeZone
関数が"MeST"を正しくタイムゾーンとして認識し、その長さが4であることを検証します。これにより、変更が意図通りに機能し、回帰バグが発生していないことが保証されます。
コアとなるコードの変更箇所
src/pkg/time/format.go
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -1037,8 +1037,8 @@ func parseTimeZone(value string) (length int, ok bool) {
if len(value) < 3 {
return 0, false
}
- // Special case 1: This is the only zone with a lower-case letter.
- if len(value) >= 4 && value[:4] == "ChST" {
+ // Special case 1: ChST and MeST are the only zones with a lower-case letter.
+ if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
return 4, true
}
// Special case 2: GMT may have an hour offset; treat it specially.
src/pkg/time/format_test.go
--- a/src/pkg/time/format_test.go
+++ b/src/pkg/time/format_test.go
@@ -331,6 +331,7 @@ var parseTimeZoneTests = []ParseTimeZoneTest{
{"GMT-5 hi there", 5, true},
{"GMT-51 hi there", 3, true},
{"ChST hi there", 4, true},
+ {"MeST hi there", 4, true},
{"MSDx", 3, true},
{"MSDY", 0, false}, // four letters must end in T.
{"ESAST hi", 5, true},
コアとなるコードの解説
src/pkg/time/format.go
の変更
parseTimeZone
関数内の条件文が変更されました。
変更前:
if len(value) >= 4 && value[:4] == "ChST"
これは、入力文字列value
の長さが4文字以上であり、かつ最初の4文字が厳密に"ChST"である場合にのみ真となる条件でした。
変更後:
if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST")
この新しい条件では、value
の長さが4文字以上であることに加えて、最初の4文字が"ChST"であるか、または"MeST"であるかのいずれかの場合に真となります。これにより、parseTimeZone
関数は"MeST"も"ChST"と同様に、小文字を含む特殊なタイムゾーン略語として認識し、パース処理を進めることができるようになります。コメントも「ChSTとMeSTが小文字を含む唯一のゾーンである」と更新され、コードの意図が明確になっています。
src/pkg/time/format_test.go
の変更
parseTimeZoneTests
というテストスライスに新しい要素が追加されました。
{"MeST hi there", 4, true},
このテストケースは、parseTimeZone
関数が"MeST hi there"という入力文字列に対して、タイムゾーン略語として"MeST"を正しく抽出し(長さ4)、その認識が成功すること(true
)を期待しています。このテストの追加により、parseTimeZone
関数の変更が正しく機能し、"MeST"が期待通りに処理されることが保証されます。
これらの変更は、Goのtime
パッケージが扱うタイムゾーン略語の範囲を広げ、より国際的な時刻表現に対応するための重要なステップです。
関連リンク
- Go CL 99910043: https://golang.org/cl/99910043
参考にした情報源リンク
- Go
time
package documentation: https://pkg.go.dev/time - Wikipedia - Chamorro Standard Time: https://en.wikipedia.org/wiki/Chamorro_Standard_Time
- Wikipedia - Metlakatla, Alaska: https://en.wikipedia.org/wiki/Metlakatla,_Alaska
- Time zone abbreviations (general information): https://www.timeanddate.com/time/zones/ (一般的なタイムゾーン略語に関する情報源として)