2021-12-15
世界にある、2つの時刻。協定世界時(UTC)と、これより37秒早い国際原子時(TAI)。

国際原子時(TAI)は、1967年、1秒の定義が「セシウム133の原子の基底状態の二つの超微細準位の間の遷移に対応する放射の周期の9192631770倍の継続時間」と定められ、日付をプログラムで扱っているとよくでてくる、1970年あたりからずっと運用されている連続した時刻。

TAIの問題は、地球の自転は一定ではないため、何も調整しないと1000年で1時間ほど日没の時間がずれてしまうらしい(長期的な問題 - 閏秒)。 それを防ぐために時々閏秒をいれて調整しているのが協定世界時((UTC)。日本標準時(JST)はこちらUTCを基準。 (研究業務内容・標準時 国際原子時・協定世界時とうるう秒 - NICT

直近の閏秒は、2017年1月1日。この日の1日の長さは86,401秒、日本時間で2017-01-01T23:59:60という変な時刻が存在した通常より0.001157%長いお正月だった。通常の時計では表現できないので、秒針が1秒戻ったり、1秒止めたりする必要がある。 (閏秒にちゃんと対応した時計づくりはおもしろそうだが、次の閏秒の予定は定まっていない)

もし、時刻の差分を使って計測していたりすると1秒余計に測ってしまったり、閏秒を考慮していないシステムではマイナスとして計算されてしまったりといろいろまずく、実際いろいろトラブルがあるので、システム的にはTAIを使いたい。

クリスから聞いた便利な日時表現「TAI64N」は、TAIを1970-01-01T00:00を基準に秒を64bitでナノ秒を32bitで、12byteのバイナリ形式と、@で始まる16進法25文字の文字列で表現する仕様。 2038年問題もなく、時刻の連続性も保証されていていい感じ!TAI64NのJavaScript実装がGitHubで見つからなかったので、作ってみた。


code4fukui/TAI64N-es: TAI64N in JavaScript (ES modules) implementation for browsers and Deno
ESモジュールなのでブラウザ上と、Denoですぐ使える。現在時刻を取得する now、文字列化する stringify、秒とナノ秒から相互変換する encode / decode など、詳しいドキュメントは未整備なので、詳細は実装テストコードをご参照ください。 正確なUTC化が必要な場合、TAIをUTC化するためのテーブル leapSeconds.js を閏秒に合わせて運用する必要がある。

ESモジュールなので、ES-Jamを使って、動かすことができる。 <!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"> <div id=div></div> <script type="module"> import { TAI64N } from "https://code4fukui.github.io/TAI64N-es/TAI64N.js"; onload = () => { const f = () => { const tai64n = TAI64N.now(); const stai64n = TAI64N.stringify(tai64n); div.textContent = stai64n; requestAnimationFrame(f); }; f(); }; </script> こちら実際のTAI64Nの文字列表現で表示するTAI64N時計。


TAI64Nは、バイナリ表現があるので、CBOR(シーボル)との相性良し!

閏秒オープンデータもきっちり世界中で共有されるべきデータですね。
意外と深い、時刻の話。次の閏秒が待ち遠しい!

Tweet
クリエイティブ・コモンズ・ライセンス
本ブログの記事や写真は「Creative Commons — CC BY 4.0」の下に提供します。記事内で紹介するプログラムや作品は、それぞれに記載されたライセンスを参照ください。
CC BY / @taisukef / アイコン画像 / プロフィール画像 / 「一日一創」画像 / RSS