[インデックス 12038] ファイルの概要
このコミットは、Go言語の標準ライブラリの一部であるlib/time
ディレクトリに、タイムゾーン情報(zoneinfo)を管理するためのREADME
ファイルとupdate.bash
スクリプトを追加するものです。これにより、Goが使用するタイムゾーンデータが、IANA Time Zone Databaseの最新情報に基づいて適切に更新される仕組みが導入されました。特に、生成されるタイムゾーンファイルのサイズを最適化し、特定の互換性要件を満たすための重要な変更が含まれています。
コミット
commit 228d941157e744c1416cafc354c8d33bdd068de0
Author: Russ Cox <rsc@golang.org>
Date: Sat Feb 18 20:33:58 2012 -0500
lib/time: add README, update.bash script
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5674104
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/228d941157e744c1416cafc354c8d33bdd068de0
元コミット内容
lib/time: add README, update.bash script
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5674104
変更の背景
Go言語のtime
パッケージは、日付と時刻の処理においてタイムゾーン情報を正確に扱うために、IANA Time Zone Database(tzdata)に依存しています。このデータベースは、世界中のタイムゾーンのルール(夏時間を含む)を定義しており、定期的に更新されます。Goのアプリケーションが常に最新かつ正確なタイムゾーン情報を使用できるようにするためには、このデータをGoのビルドプロセスや実行環境に組み込む必要があります。
このコミットが行われた2012年当時、Goはタイムゾーンデータをどのように取得・更新するかについて、より堅牢なメカニズムを必要としていました。特に、Goのtime
パッケージが内部的に利用するzoneinfo
ファイルは、IANAデータベースからコンパイルされたものです。このコミットは、以下の目的で導入されました。
- タイムゾーンデータの出所を明確にする:
README
ファイルを追加することで、lib/time/zoneinfo
ディレクトリ内のデータがIANA Time Zone Databaseに由来すること、およびそのパブリックドメインとしての性質を明示します。 - タイムゾーンデータの更新プロセスを自動化・標準化する:
update.bash
スクリプトを提供することで、IANAの公式リポジトリから最新のtzcode
(タイムゾーンコンパイラなどのツール)とtzdata
(タイムゾーンデータ)をダウンロードし、Goが利用できるzoneinfo
形式にコンパイルする手順を自動化します。これにより、手動での更新作業の負担を軽減し、一貫性を保つことができます。 - 生成される
zoneinfo
ファイルのサイズと互換性を管理する:update.bash
スクリプトには、zic
(タイムゾーン情報コンパイラ)の挙動を調整し、生成されるzoneinfo
ファイルが64ビットのタイムスタンプ情報を含まないようにする重要なステップが含まれています。これは、ファイルサイズの肥大化を防ぎ、当時のGoのランタイムやシステムが32ビット形式のzoneinfo
ファイルを前提としていた可能性、または2038年問題(Unix時間における32ビット符号付き整数のオーバーフロー問題)が顕在化する前の段階での最適化として重要でした。
前提知識の解説
IANA Time Zone Database (tzdata)
IANA Time Zone Database(通称 tzdata
、zoneinfo database
、または Olson database
)は、世界中のタイムゾーンの歴史的な変化、夏時間(Daylight Saving Time, DST)のルール、およびUTCオフセットに関する情報を集約した、共同で維持されているデータベースです。これは、コンピュータシステムが正確な時刻とタイムゾーン変換を行うために広く利用されています。
- tzdata: タイムゾーンのルールや歴史的な変更に関する実際のデータが含まれています。これは通常、人間が読めるテキストファイル形式で配布されます。
- tzcode:
tzdata
を処理し、バイナリ形式のzoneinfo
ファイルを生成するためのツール群(zic
コンパイラなど)が含まれています。
zic
(Time Zone Information Compiler)
zic
は、IANA Time Zone Databaseのソースファイル(テキスト形式)を、システムが効率的に読み込めるバイナリ形式のzoneinfo
ファイルにコンパイルするためのツールです。これらのバイナリファイルは、通常/usr/share/zoneinfo
のようなディレクトリに配置され、オペレーティングシステムやプログラミング言語のライブラリによって利用されます。
32ビット/64ビットタイムスタンプと2038年問題
Unix時間(エポック秒)は、1970年1月1日00:00:00 UTCからの経過秒数を表すものです。多くのシステムでは、これを32ビットの符号付き整数で表現してきました。しかし、32ビット符号付き整数の最大値は2,147,483,647であり、これは2038年1月19日03:14:07 UTCに到達します。この時刻を超えると、32ビットシステムではタイムスタンプがオーバーフローし、負の値として解釈されるなどの問題が発生する可能性があります。これが「2038年問題」です。
zoneinfo
ファイルも、内部的にタイムスタンプを保持しており、これが32ビット形式か64ビット形式かによってファイルサイズや互換性に影響が出ます。このコミットの時点では、まだ2038年問題が差し迫ったものではなかったため、ファイルサイズを抑えるために32ビット形式のzoneinfo
ファイルを生成することが望ましいと判断された可能性があります。
Go言語のtime
パッケージ
Go言語の標準ライブラリであるtime
パッケージは、日付、時刻、期間、タイムゾーンの処理を提供します。time.Time
構造体は、特定の時点を表し、そのタイムゾーン情報(time.Location
)を含みます。time.Location
は、システム上のzoneinfo
ファイルからロードされるか、組み込みのタイムゾーンデータを使用します。
技術的詳細
このコミットの核となるのは、lib/time/update.bash
スクリプトです。このスクリプトは、Goが使用するタイムゾーンデータを自動的に更新するための包括的なワークフローを定義しています。
-
バージョン指定: スクリプトの冒頭で、ダウンロードする
tzcode
とtzdata
のバージョンがCODE
とDATA
変数で明示的に指定されています(例:CODE=2011i
,DATA=2011n
)。これにより、特定の安定したバージョンのデータを使用することが保証されます。 -
作業ディレクトリの準備:
rm -rf zoneinfo work
で既存のzoneinfo
ディレクトリと一時作業ディレクトリwork
を削除し、mkdir zoneinfo work
で新しいディレクトリを作成します。その後、cd work
で作業ディレクトリに移動します。 -
データのダウンロード:
curl -O http://www.iana.org/time-zones/repository/releases/tzcode$CODE.tar.gz
とcurl -O http://www.iana.org/time-zones/repository/releases/tzdata$DATA.tar.gz
コマンドを使用して、IANAの公式リポジトリから指定されたバージョンのtzcode
とtzdata
のアーカイブファイルをダウンロードします。 -
アーカイブの展開: ダウンロードした
tar.gz
ファイルをtar xzf
コマンドで展開します。これにより、work
ディレクトリ内にtzcode
とtzdata
のソースファイルが配置されます。 -
zic.c
のパッチ適用(64ビット出力の無効化):perl -p -i -e 's/pass <= 2/pass <= 1/' zic.c
というコマンドが実行されます。これは非常に重要なステップです。zic.c
はtzcode
に含まれるzic
コンパイラのC言語ソースコードです。pass <= 2
という文字列は、zic
のコンパイルプロセスにおける特定の「パス」(段階)を指します。通常、pass 2
は64ビットのタイムスタンプ情報を含むzoneinfo
ファイルを生成するために使用されます。- この
perl
コマンドは、zic.c
内のpass <= 2
という記述をpass <= 1
に置換します。これにより、zic
は64ビットのタイムスタンプを生成するパスを実行しなくなり、結果として生成されるzoneinfo
ファイルは32ビット形式に限定されます。 - スクリプト内のコメント「
We don't need those until 2037.
」が示すように、これは2038年問題が現実のものとなるまでの間、ファイルサイズを小さく保つための意図的な最適化です。64ビットのタイムスタンプはファイルサイズを約3倍に増加させるとされています。
-
タイムゾーンファイルのコンパイル:
make CFLAGS=-DSTD_INSPIRED AWK=awk TZDIR=../zoneinfo posix_only
コマンドが実行されます。- これは、展開された
tzcode
のソースを使用してzic
をビルドし、タイムゾーンデータをコンパイルするプロセスです。 CFLAGS=-DSTD_INSPIRED
: コンパイルフラグで、zic
の挙動に影響を与える可能性があります。AWK=awk
:awk
コマンドのパスを指定します。TZDIR=../zoneinfo
: 生成されたバイナリzoneinfo
ファイルをwork
ディレクトリの親ディレクトリにあるzoneinfo
ディレクトリに出力するよう指定します。posix_only
: POSIX互換のタイムゾーンファイルのみを生成するよう指示します。これにより、非標準のタイムゾーンが除外され、ファイルセットが簡潔になります。
- これは、展開された
-
生成されたファイルのサイズ検証:
size=$(ls -l ../zoneinfo/America/Los_Angeles | awk '{print $5}')
で、コンパイルされたAmerica/Los_Angeles
タイムゾーンファイルのサイズを取得します。if [ $size -gt 1200 ]; then ...
で、そのサイズが1200バイトを超えているかどうかをチェックします。もし超えている場合、「zone file too large; 64-bit edit failed?
」というエラーメッセージを出力し、スクリプトを終了します。これは、前述のperl
コマンドによる64ビット出力の無効化が正しく機能したことを確認するための重要な健全性チェックです。 -
バージョン管理システムへの追加/削除:
cd ..
で親ディレクトリに戻り、hg addremove zoneinfo
を実行します。これは、Goが当時使用していたMercurial(hg
)バージョン管理システムに対して、新しく生成されたzoneinfo
ディレクトリ内のファイルを追加または削除するコマンドです。これにより、リポジトリが最新のタイムゾーンファイルの状態を反映するようになります。 -
クリーンアップ: スクリプトの最後に、
-work
引数が指定されていない限り、一時作業ディレクトリwork
をrm -rf work
で削除します。
コアとなるコードの変更箇所
lib/time/README
--- /dev/null
+++ b/lib/time/README
@@ -0,0 +1,9 @@
+The zoneinfo directory contains time zone files compiled using
+the code and data maintained as part of the IANA Time Zone Database.
+The IANA asserts that the database is in the public domain.
+
+For more information, see
+http://www.iana.org/time-zones
+ftp://ftp.iana.org/tz/code/tz-link.htm
+http://tools.ietf.org/html/draft-lear-iana-timezone-database-05
+
lib/time/update.bash
--- /dev/null
+++ b/lib/time/update.bash
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Copyright 2012 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This script rebuilds the time zone files using files
+# downloaded from the ICANN/IANA distribution.
+
+# Versions to use.
+CODE=2011i
+DATA=2011n
+
+set -e
+rm -rf zoneinfo work
+mkdir zoneinfo work
+cd work
+curl -O http://www.iana.org/time-zones/repository/releases/tzcode$CODE.tar.gz
+curl -O http://www.iana.org/time-zones/repository/releases/tzdata$DATA.tar.gz
+tar xzf tzcode$CODE.tar.gz
+tar xzf tzdata$DATA.tar.gz
+
+# Turn off 64-bit output in time zone files.
+# We don't need those until 2037.
+perl -p -i -e 's/pass <= 2/pass <= 1/' zic.c
+
+make CFLAGS=-DSTD_INSPIRED AWK=awk TZDIR=../zoneinfo posix_only
+
+# America/Los_Angeles should not be bigger than 1100 bytes.
+# If it is, we probably failed to disable the 64-bit output, which
+# triples the size of the files.
+size=$(ls -l ../zoneinfo/America/Los_Angeles | awk '{print $5}')
+if [ $size -gt 1200 ]; then
+ echo 'zone file too large; 64-bit edit failed?' >&2
+ exit 2
+fi
+
+cd ..
+hg addremove zoneinfo
+echo
+if [ "$1" == "-work" ]; then
+ echo Left workspace behind in work/.\n
+else
+ rm -rf work
+fi
+echo New time zone files in zoneinfo/.\n
コアとなるコードの解説
lib/time/README
この新しいREADME
ファイルは、lib/time/zoneinfo
ディレクトリに格納されているタイムゾーンデータの出所を明確にしています。
- IANA Time Zone Database: データがIANA Time Zone Databaseからコンパイルされたものであることを明記しています。これは、Goが公式かつ信頼できるタイムゾーン情報源を使用していることを示します。
- Public Domain: IANAがデータベースをパブリックドメインであると主張していることを記載しており、Goプロジェクトでの利用におけるライセンス上の懸念を解消します。
- 関連リンク: IANAのタイムゾーンに関する公式ウェブサイト、FTPサイト、および関連するIETFドラフトへのリンクを提供しており、ユーザーや開発者が詳細情報を参照できるようにしています。
lib/time/update.bash
このシェルスクリプトは、Goのタイムゾーンデータを自動的に更新するための包括的な手順を実装しています。
-
スクリプトヘッダとライセンス:
#!/bin/sh
でシェルスクリプトであることを宣言し、Goプロジェクトの標準的なBSDスタイルのライセンス情報が含まれています。 -
目的のコメント: スクリプトの目的が「ICANN/IANAディストリビューションからダウンロードしたファイルを使用してタイムゾーンファイルを再構築する」と明確に記述されています。
-
バージョン変数 (
CODE
,DATA
):CODE=2011i
とDATA=2011n
は、それぞれダウンロードするtzcode
とtzdata
の特定のバージョンを指定しています。これにより、スクリプトの実行時に常に同じバージョンのデータが使用され、再現性が保証されます。 -
エラー時の終了 (
set -e
):set -e
は、スクリプト内の任意のコマンドが失敗した場合に、スクリプトが即座に終了するように設定します。これにより、部分的な成功や不完全な更新を防ぎ、エラーが発生した際には早期に検知できます。 -
作業ディレクトリの準備と移動:
rm -rf zoneinfo work
とmkdir zoneinfo work
は、以前の実行で残った可能性のあるzoneinfo
ディレクトリと一時作業ディレクトリwork
をクリーンアップし、新しいディレクトリを作成します。cd work
で、以降の操作がこの一時ディレクトリ内で行われるようにします。 -
データのダウンロードと展開:
curl -O ...
コマンドは、IANAの公式リポジトリからtzcode
とtzdata
の圧縮アーカイブをダウンロードします。tar xzf ...
は、これらのアーカイブを展開し、ソースファイルを作業ディレクトリに配置します。 -
64ビット出力の無効化 (
perl
コマンド):perl -p -i -e 's/pass <= 2/pass <= 1/' zic.c
は、このスクリプトの最も技術的に重要な部分です。zic.c
は、タイムゾーンファイルをコンパイルするzic
ツールのCソースコードです。pass <= 2
は、zic
がタイムゾーンデータを処理する際の内部的な段階(パス)を指します。pass 2
は通常、2038年問題に対応するために64ビットのタイムスタンプを生成するロジックを含んでいます。- この
perl
コマンドは、zic.c
内のpass <= 2
という文字列をpass <= 1
に置換します。これにより、zic
は64ビットのタイムスタンプを生成するパスを実行しなくなり、結果として生成されるzoneinfo
ファイルは32ビット形式に限定されます。 - コメント「
We don't need those until 2037.
」は、この変更の理由を説明しています。2038年問題が現実のものとなるまでは、64ビットのタイムスタンプは不要であり、ファイルサイズを小さく保つことが優先されたことを示唆しています。64ビットのタイムスタンプは、ファイルサイズを大幅に増加させます。
-
タイムゾーンファイルのコンパイル (
make
コマンド):make CFLAGS=-DSTD_INSPIRED AWK=awk TZDIR=../zoneinfo posix_only
は、展開されたtzcode
のソースからzic
をビルドし、ダウンロードしたtzdata
を使用してバイナリ形式のzoneinfo
ファイルをコンパイルします。TZDIR=../zoneinfo
は、生成されたzoneinfo
ファイルをwork
ディレクトリの親ディレクトリ(つまりlib/time/zoneinfo
)に出力するよう指示します。posix_only
は、POSIX標準に準拠したタイムゾーンのみを生成し、非標準のタイムゾーンを省略することで、生成されるファイルセットを簡潔に保ちます。
-
サイズ検証:
size=$(ls -l ../zoneinfo/America/Los_Angeles | awk '{print $5}')
とそれに続くif
文は、America/Los_Angeles
タイムゾーンファイルのサイズをチェックします。もしサイズが1200バイトを超えている場合、64ビット出力の無効化が失敗した可能性を示唆するエラーメッセージを出力し、スクリプトを終了します。これは、perl
コマンドによるパッチが正しく適用され、意図した通りに32ビット形式のzoneinfo
ファイルが生成されたことを確認するための重要な検証ステップです。 -
Mercurialへの変更の反映:
cd ..
で親ディレクトリに戻り、hg addremove zoneinfo
を実行します。これは、Goプロジェクトが当時使用していたMercurialバージョン管理システムに対して、zoneinfo
ディレクトリ内の新規ファイルを追加し、削除されたファイルを追跡対象から外すコマンドです。これにより、リポジトリが最新のタイムゾーンファイルの状態を正確に反映するようになります。 -
クリーンアップ:
if [ "$1" == "-work" ]; then ... else rm -rf work; fi
は、スクリプトの引数に-work
が指定されていない限り、一時作業ディレクトリwork
を削除します。これにより、ビルドプロセス後に不要なファイルが残らないようにします。
関連リンク
- IANA Time Zone Database: https://www.iana.org/time-zones
- Go言語
time
パッケージドキュメント: https://pkg.go.dev/time
参考にした情報源リンク
- IANA Time Zone Database (Wikipedia): https://en.wikipedia.org/wiki/Tz_database
- tzcode and tzdata explanation: (Web search results from grounding)
- Go language time zone handling: (Web search results from grounding)
- 2038年問題 (Wikipedia): https://ja.wikipedia.org/wiki/2038%E5%B9%B4%E5%95%8F%E9%A1%8C
zic
man page (一般的な情報源): https://man7.org/linux/man-pages/man8/zic.8.html (このコミットの特定のバージョンとは異なる可能性がありますが、一般的な理解に役立ちます)