1901/12/13 20:45:51以前のAsia/Tokyoの結果は環境によって違うことがあるのでようちゅうい
goのtime.Timeのゼロ値は0001-01-01 00:00:00 +0000
なのだけど、JSTでログ出力するコードのテストの結果がディストリビューションによって違うってのがあった
https://play.golang.org/p/stkTNMsByNc
0001-01-01T09:00:00+09:00
ubuntuや、go playgroundでは
0001-01-01T09:18:59+09:18
この9:18というのは、LMTというもので日本の場合は +9時間18分48秒
まあ、日本標準時が利用される前は日本標準時は無いのだから厳密にはLMTであるべき、なのはまあわかる。おなじgoのバージョンでも環境によって違うのはなんでだ?
tzdata
違いは、読み込まれた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 の内容がそもそもディストリで違った
$ cat /usr/share/zoneinfo/Asia/Tokyo | xxd 0000000: 545a 6966 3200 0000 0000 0000 0000 0000 TZif2........... 0000010: 0000 0000 0000 0003 0000 0003 0000 0000 ................ 0000020: 0000 0009 0000 0003 0000 000d c355 3b70 .............U;p 0000030: d73e 1e90 d7ec 1680 d8f9 1690 d9cb f880 .>.............. 0000040: db07 1d10 dbab da80 dce6 ff10 dd8b bc80 ................ 0000050: 0201 0201 0201 0201 0200 007e 9000 0000 ...........~.... 0000060: 008c a001 0500 007e 9000 094a 4353 5400 .......~...JCST. 0000070: 4a44 5400 4a53 5400 0000 0000 0000 545a JDT.JST.......TZ ...
- zone情報3個
- JCST, JDT, JSTの3個
ubuntuなど
$ docker run -it ubuntu bash # apt-get update; apt-get install tzdata xxd # cat /usr/share/zoneinfo/Asia/Tokyo | xxd 00000000: 545a 6966 3200 0000 0000 0000 0000 0000 TZif2........... 00000010: 0000 0000 0000 0004 0000 0004 0000 0000 ................ 00000020: 0000 0009 0000 0004 0000 000c 8000 0000 ................ 00000030: d73e 0270 d7ed 4be0 d8f8 fa70 d9cd 2de0 .>.p..K....p..-. 00000040: db07 00f0 dbad 0fe0 dce6 e2f0 dd8c f1e0 ................ 00000050: 0301 0201 0201 0201 0200 0083 0300 0000 ................ 00000060: 008c a001 0400 007e 9000 0800 007e 9000 .......~.....~.. 00000070: 084c 4d54 004a 4454 004a 5354 0000 0000 .LMT.JDT.JST.... ...
- zone情報4個ある
- LMTあり
ふむ?
zic
tzdataの元ネタであるOlson databaseから、2018eをダウンロード。ディストリについてくるzicで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をカスタマイズしている模様。
なんか古いテストコードが動かなくなる、とかそういうのがあるのかな? 深追いはしていない
けつろん
日付のテストで、すごい古いのを扱う場合、LMTの扱いがある。
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さんとごにょごにょした