タイムゾーンのオフセット+09:18:59 はて、18:59はなんぞや?

いろいろ検索したつもりでしたが、実は :18:59 timezone と検索することで先人の方々のサイトがヒットし、Google先生がいれば誰でも天才ということで表題の件は簡単に速攻で解決できたことがわかりました。しかしせっかく書いたので恥ずかしながら公開しておきます…


(追記)

2020年オリンピック時間の検討だそうです。(干からびたチーズとかイットとかなんかあったなとアルファ波を出しながらなま暖かい目で見ていた多くの人の予想通り、検討の初期段階でさっそく実施されない方向に向かっているようです。欧州では逆にサマータイムなんかやめちまえという流れのようで。)

もともとUNIX epoch timeとかtzdbとか気にしないでローカル時刻で猪突猛進の場合でも、DBのTIMESTAMPにはUNIX epoch timeで入ってる場合もあるでしょうし、UNIX epoch timeでクライアントとサーバがやり取りしている場合だとtzdbのサーバとクライアントのどちらか一方だけ更新、とかではまります。2019年にテストしてとかいうことだとzicが活躍するでしょうか。妄想するとこんな感じ?現実的にはもっと幅が広くなるのでしょうが。

基本はUNIX Epoch timeはある時刻に全世界で同じ値で、tzdbを用いてローカル時間と相互に変換できるということです。そんでもってUTCは人間の生活用の時刻の元ではあるけどローカル時刻ではないのでサマータイムは無く、毎日きっちり86400秒という決まりなので、UNIX Epoch timeはうるう秒がいつ入るか、入ったかを知らなければいけないということになります。

リテラルで9時間足したり引いたりしていると、今度はあるタイミングのときだけ11時間足したり引いたりとかハチャメチャな条件分岐が書かれていろいろ楽しいことが起きそうです。他にもUNIX Epoch timeに86400秒を足すと、翌日の同じローカル時間になると仮定しちゃってる場合とかも問題です。Pythonだと標準ライブラリではAsia/Tokyoと書けなくてリテラルで9、で涙目とかでしょうか。

まともな電波時計はDSTフラグとオフセットも受け取れるでしょうし、送る側もちゃんときっとそれらを送出するでしょうからほっといても良いのでしょうが、生活でのローカル時間が必要だけどtzbd持ってない、持っていたとしても更新できないIoT機器とか、何らかの時刻ソースから時刻を設定している機器で時刻ソースがDSTをどう扱うのか決まってない場合とか。家庭内だとECHONETとかでつながっている場合いろいろ起きそうです。スマートメーターが送ってくる時刻とかお風呂の沸く時刻のDSTの扱いとかとか。HDレコーダは国際的なメーカーでも、放送信号やら番組表やら結構ローカル度高いので、特にDSTに入るときと出るときとか。見たかったオリンピック競技が撮れてないじゃん!とかならないようにファームウェアの更新があるかもしれません。Alexa, ちゃんと朝6時に起こしてね。

逆に孤立している学校の巨大な時計とか、Wi-SUNでもWi-Fiでもつながっていないお風呂やエアコンのリモコンとかシャッターとかは自力で調整する以外ないのでシンプルです。あーつながってなくてよかった?

いくらでも出てきますね。全国同一の標準時間の国なので、実際にやることになったらいろいろ起きまくってよい啓蒙()になりそうです。


結論だけ知りたい方向けに、(09:)18:59(Pythonでは仕様で分未満のオフセットが扱えずにpytzでは09:19:00相当になるそうです)は直接的には時間関数が使用するtzfile(zicにより生成される)のAsia/Tokyoにそう書かれています。zicの入力となるtz databaseの大元はSources for Time Zone and Daylight Saving Time DataのFTP distributionTime Zone Databaseよりたどれます(訴訟を機に管轄が変わりました)。

そしてこのAsia/TokyoはSouth Ryukyu Ilands時間問題に端を発して多くの方々の尽力によって出来上がったもののようです。とてもすばらしいですね。平成8年の理科年表と書かれているので、(旧)日本測地系の値なのでは、とか考え始めたら長くなりそうなのでそれは別エントリにて。Asia/TokyoとJST-09の違いを理解していて、JDT,DST(daylight saving timeいわゆるサマータイム)やらLMT(local mean time)やらを気にしたくない、+09:18:59じゃなくて常に+09:00:00であって欲しい方(多くの場合移植性が悪くなるでしょうから一概に良いこととは思えませんが(例えば万が一実際にオリンピック時間が実施される場合はtzdbを更新してもDSTが有効にならない))は、

標準ライブラリが使用されている場合
POSIXシステムではTZ環境変数でコントロールできます。

PostgreSQL

その他独自にtimzoneを指定できるアプリケーション…

が答えです。

さて、前置きが長くなりましたが何のことを言ってるのでしょうか。

PostgreSQLで以下のSQLを実行してみます。

結果は

となり、初期化忘れか、と思いながらも何度やっても+09:18:59で安定してます。あとから考えると、普通の使い方ではオフセットだけの表示で、’LMT’のようなゾーン名が出てこないSQLならではのはまり所なのかもしれません。面白いのでデバッガで追います。PostgreSQLがOSに依存しないように自ら時間関数pg_xxx()を持っているようです。pg_localtime()で出来上がっています。その際に使用されるtimezoneは指定のファイルがあればpg_tzset()でtzfileをロード(tzload())してできています。というわけでソースアーカイブからzicに食わせる元ファイルを眺めると18:59を発見できます。環境変数TZに../../../../../../../etc/passwdなんてセットしても大丈夫ですね、などと関係のないことも確認してたりしているところで、別にPostgreSQL付属ではなくてシステム(FreeBSD)のtzfile使っているものでも同じ結果であることに気づいたので、元ファイルを見ます。ほぼ同じファイル、なるほど、ではPostgreSQL追うまでもないじゃん、というかPostgreSQLのファイル見たときに、PostgreSQL専用でなくて大元のファイルであることに気づけよという感じです。amd64なFreeBSDにて、上記の値を利用して、

してみると結果は

はい18:58LMT頂きました。00:18:59で繰り上がって00:00:00になっています。引き続き上記ファイル更新に従ってtzupdaterが出るJRE行ってみます。

結果は

残念。しかし引き続き

した結果は

なので、LMTは使用しないで通常のオフセットにしたタイムゾーンになっているようです。おそらくこれが身勝手にも暗黙のうちに期待していたもののような感じでしょうか。

Javaに関連してJDBCではTIMESTAMP WITH TIME ZONE型をサーバから ‘1887-12-31 23:59:59.999999+09:18:59’ という書式で受け取っても、java.sql.Timestamp型はepoch(1970/01/01 00:00:00+00 = 1970/01/01 09:00:00+09)からのオフセットしか保持していないのでgetTimezone()では+09:18:59は気にする必要はない、というよりも文字列から自力でタイムゾーンを抜くようなことをしないと気にできません。挿入時もsetTimestamp()ではタイムゾーンの指定はできず、セッションタイムゾーンが使用されます。

最後に、ftp://ftp.iana.org/tz/releases/ (旧ftp://elsie.nci.nih.gov/pub/) のtzdata2010o.tar.gz版より各国のLMTをUNTIL順に並べてみます。アムステルダム早っ!

コメントを残す

メールアドレスが公開されることはありません。