以前の記事で取り上げたNTPにまつわる、2036年問題について取り上げます。
なお、過去記事は以下にURLを貼っておきますので、よろしければそちらもご覧ください🐜
桜時計で立てたSNTPサーバから、有線LANで時刻取得するときの設定方法 - ari23の研究ノート
NTPと2036年問題とは
Network Time Protocolの略称で、時刻同期のためのプロトコルです。
世界にはNTPサーバというものがあり、協定世界時(UTC)を送信してくれます。
NTPサーバが送る時間は、1900年01月01日00時00分00秒からの積算秒数です。
なぜこの時間を起点にしたかは特に理由がないようですね。
受信側はこの積算秒数をもらって、現地時間にしたり、暦に変えたりして、時刻同期をします。
ただし、この積算秒数は32ビット整数で送られるため、将来オーバーフローしてしまう問題、いわゆる2036年問題があります。
2036年問題の解決策
アプローチとしては2つあります。
NTPサーバが送信するデータを64ビット整数にする
64ビット整数にすれば、西暦3000億年くらい使えるため、根本的な解決になります。受信側でうまくやる
オーバーフローしたら、過去の1900年に戻るのではなく、受け手側で未来の時間として理解します。
前者の方がスマートなアプローチですが、実際は後者の方法を取るようです。
受信側の対応
まずオーバーフローする現象を整理し、理解した上で受信側の対応方法を述べます。
オーバーフローする現象
NTPサーバが送る秒(HEX)を、ビットと暦時刻にして整理します。1
秒(HEX) | 秒(BIN) | 暦時刻 |
---|---|---|
0x00000000 | 0000 0000 0000 0000 0000 0000 0000 0000 | 1900年01月01日00時00分00秒(UTC+0) |
0x7fffffff | 0111 1111 1111 1111 1111 1111 1111 1111 | 1968年01月20日03時14分07秒(UTC+0) |
0x80000000 | 1000 0000 0000 0000 0000 0000 0000 0000 | 1968年01月20日03時14分08秒(UTC+0) |
0xffffffff | 1111 1111 1111 1111 1111 1111 1111 1111 | 2036年02月07日06時28分15秒(UTC+0) |
上記の表を見ると、2036年にオーバーフローを起こし、過去の1900年に戻ってしまうことがわかります。
具体的な対応方法
この記事を書いているのは、2020年で日本では令和2年です。一方1900年は、明治33年で日露戦争前です。
タイムマシンに乗って、2019年の製品を1900年代に持ち込んで使う(ナニに?w)ことはないので2、 受け手側で読み替えてしまおうというのが、実際の対応です。3
やり方は簡単で最上位ビットで判定します。
秒(HEX) | 秒(BIN) | 暦時刻 |
---|---|---|
0x80000000 | 1000 0000 0000 0000 0000 0000 0000 0000 | 1968年01月20日03時14分08秒(UTC+0) |
0xffffffff | 1111 1111 1111 1111 1111 1111 1111 1111 | 2036年02月07日06時28分15秒(UTC+0) |
0x00000000 | 0000 0000 0000 0000 0000 0000 0000 0000 | 2036年02月07日06時28分16秒(UTC+0) |
0x7fffffff | 0111 1111 1111 1111 1111 1111 1111 1111 | 2104年02月26日09時42分23秒(UTC+0) |
これにより、2104年まで現行のNTPでも使えるようになります。
おわりに
時刻同期のAPIを開発しているときは、「NTPサーバから64ビットで時間欲しいなぁ」と思いました。
しかし、こうやって整理すると68年も持つんだから、この解決策でもいいのかと考えるようになりました。
世界にあるすべてのNTPサーバの仕様を変更するのは、かなりコストがかかってしまいますもんね。
参考になれば幸いです(^^)