Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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パッケージが扱うタイムゾーン略語の範囲を広げ、より国際的な時刻表現に対応するための重要なステップです。

関連リンク

参考にした情報源リンク