1901/12/13 20:45:51以前のJSTの結果はようちゅうい

トミール Naoki Tomita July 13th, 2018 go

(2018年当時の記事です)

goのtime.Timeのゼロ値は0001-01-01 00:00:00 +0000なのだけど、JSTでの出力結果がディストリビューションによって違うってことがあった。ってのが絡むテストがあって気づいた

この9:18というのは、日本のLMT(地方平均時)というもの。日本標準時が採用される前は日本標準時は無いのだからLMTであるべき、なのはわかる。でもおなじgoのバージョンでも環境によって違うのはなんでだ?

tzdata

違いは、time.LoadLocation("Asia/Tokyo")に対して読み込まれたzoneだった

&time.Location{
    name:"Asia/Tokyo",
    zone:[]time.zone{
        time.zone{name:"LMT", offset:33539, isDST:false}, // ubuntuではこれがあるがcentosでは無い
        time.zone{name:"JDT", offset:36000, isDST:true},
        time.zone{name:"JST", offset:32400, isDST:false},
        time.zone{name:"JST", offset:32400, isDST:false},
    }

goのtime読んでみると単にtzdataをロードしているだけの模様で、ロードされる /usr/share/zoneinfo/Asia/Tokyo の内容がそもそもディストリで違った

ふむ? tzdataって配布物が違っていいのだろうか

zic

tzdataの元ネタであるOlson databaseから、2018eをダウンロード。ディストリについてくるzic(Zone Information Compiler)でtzdataにコンパイルしてみる

$ wget https://data.iana.org/time-zones/releases/tzdata2018e.tar.gz
$ tar zxvf tzdata2018e.tar.gz
$ zic -d /tmp asia
$ cat /tmp/Asia/Tokyo | xxd

→ ソースは同じだが、各ディストリ付属のzicによって作成されるtzdataバイナリが違う事が判明!(centosやmacの /usr/sbin/zic だとLMTが無い

zic自体もコンパイルしてみる

$ wget https://data.iana.org/time-zones/releases/tzcode2018e.tar.gz
$ tar zxvf tzcode2018e.tar.gz
$ make zic
$ mkdir -p /tmp/hoge
$ ./zic -d /tmp/hoge | asia
$ cat /tmp/hoge/Asia/Tokyo | xxd

→ macやcentでもzone4個、LMTが出現!!


たぶん何か影響があって、ディストリビューションでzicをカスタマイズしている模様。 なんか古いテストコードが動かなくなる、とかそういうのがあるのかな? 深追いはしていない

perlの DateTime::Timezone みたくolson databaseを抱え込むタイプのライブラリと、goのtimeのようにライブでtzdataを読みに行くタイプのライブラリがあるとおもうのだけど後者の場合はようちゅうい

今回のgoのテストケースではこんな感じでしのいだ

// ログ出力JST固定なのでtzdataのロードはやめて、fixedzone利用
tz := time.FixedZone("Asia/Tokyo", 9*60*60)

// あとねんのためtime.Timeのゼロ値は出力前のnilチェックでepochtimeにしてしまうことにした
	if t.IsZero() {
		t = time.Unix(0, 0)
	}

というのをyowcowさんとごにょごにょした