NTP うるう秒(閏秒)

$Id: ntpd-leapseconds.html,v 1.15 2015/05/21 01:22:18 candy Exp candy $
この文書の内容は無保証です。 ツッコミはこっち

新着

2015.07.01 JST にうるう秒挿入があります。

実録!! 2009 年うるう秒! その時 (GPS|ntpd) は!?!!

  1. 秒の定義

    1 秒の長さは、 SI (国際単位) によって、 セシウム原子の固有の周波数で定義されている(SI 秒)。
    「秒は、セシウム 133 原子の基底状態の 2 つの超微細準位(F=4, M=0 および F=3, M=0)の間の遷移に対応する放射の 9 192 631 770 周期の継続時間」
    原子時計は、この 1 秒を積算することによって、時刻を決定する。

    この定義が制定されたのは 1967 年で、 それ以前は地球の運動に基づいた定義だった。 地球の自転速度は一定でないので、以前の定義では 1 秒の長さも一定ではなかった。

  2. タイムシステム

    時刻を表す方法はいくつもある。 普段我々が使っている時刻は日本標準時(JST)であるが、 それは協定世界時(UTC)を 9 時間進めた時刻である。 UTC は TAI と UT1 から決定される。 参考:
  3. うるう秒

    地球の自転は年々変化するので、UT1 もそれに伴い一日の長さが変化する。 UT1 と UTC との差が +-0.9 秒以内に収まるように、 UTC に 1 秒単位で挿入か削除を行う。 この 1 秒をうるう秒と言う。 うるう秒の調整は 6 月 30 日か 12 月 31 日に行い、 挿入の場合は 23:59:59 の次に 23:59:60 を挿入し、 削除の場合は 23:59:59 を削除する。

    UTC が TAI - 10 で開始以来 1998/12/31 23:59:60 まで、 うるう秒調整は 22 回あった(すべて挿入)。 この時点で UTC = TAI - 32。 2005/12/31 23:59:60 のうるう秒挿入後は、 UTC = TAI - 33 となる。

    2008/12/31 23:59:60 うるう秒挿入がある。

  4. UNIX time とうるう秒

    UNIX time はある起点からの秒数として表現されるので、 UNIX time と日付を正しく相互変換するには、うるう秒を考慮する必要がある。 うるう秒を考慮するかどうかはシステムの設定に依存する。 考慮しないシステムでは、うるう秒調節がなかったことにして変換する。 当然、うるう秒を考慮するシステムとしないシステムとでは、時刻の互換性がない (同じ値を持つ UNIX time が異なる日付に表示される。 同じ日付を UNIX time に変換すると、異なる値になる)。

    例えば 2006/01/01 09:00:00 (JST) は、 うるう秒考慮なしのシステムでは

    $ perl -e 'use POSIX; printf("%d\n", mktime(0, 0, 9, 1, 0, 106));'
    1136073600
    
    となり、うるう秒考慮ありのシステムでは、
    $  perl -e 'use POSIX; printf("%d\n", mktime(0, 0, 9, 1, 0, 106));'
    1136073623
    
    となる。

    2006/01/01 JST のうるう秒挿入前後の JST と UNIX time の動きを、 時系列で表すと次のようになる。
    日付(JST)UNIX time (うるう秒考慮なし)UNIX time (うるう秒考慮あり
    2006/01/01 08:59:5911360735991136073621
    2006/01/01 08:59:6011360736001136073622
    2006/01/01 09:00:0011360736001136073623
    2006/01/01 09:00:0111360736011136073624
    うるう秒考慮のあるシステムでは、うるう秒の前後でも連続して 1 秒ずつ増加する。

    うるう秒考慮のないシステムの場合、 08:59:60 と 09:00:00 で同じ値を返すのが正しい(POSIX 仕様)。 つまりうるう秒挿入直後、UNIX time を 1 秒戻さなければならない (削除の場合は 1 秒進める)。

    ではだれが UNIX time を調整するのか? カーネルがうるう秒のスケジュールを知っていて、調整してくれるなら問題ない。 そうでなければ誰かが(NTP を使うなり手作業でやるなり)調整する必要がある。

    (例えば FreeBSD のカーネルはうるう秒など知らないし、 FreeBSD の ntpd も、うるう秒操作時に UNIX time を調整してくれない (そもそも NTP time のうるう秒調整すらしない)。 従って、FreeBSD の場合、09:00:00 に、 ntpdate なり date コマンドなりでカーネルの UNIX time を調整する必要がある。)

    参考:

  5. NTP とうるう秒

    NTP time はある起点からの秒数として表現されるが、 UTC と NTP time の変換では、うるう秒を考慮しなくてよい。 その代わり、 うるう秒調整が起きると、NTP time は一秒だけ止まったり(挿入時)、 一秒飛ばしたり(削除時)する。

    うるう秒調整がある場合、 その日(6 月 30 日か、12 月 31 日)の NTP パケットには、 Leap Indicator (LI) が特別な値になる。 通常 LI の値は 00(2進数)だが、 うるう秒挿入の日は 01 (2進数)に、 うるう秒削除の日は 10 (2進数)にセットされる。 これによって、NTP はうるう秒調整を知ることができる。

    2006/01/01 JST のうるう秒挿入前後の JST と NTP time の動きを、 時系列で表すと次のようになる。 うるう秒と次の秒で、NTP time が同じ値を示すことに注意!
    日付(JST)NTP timeLI
    2006/01/01 08:59:59334506239901
    2006/01/01 08:59:60334506240001
    2006/01/01 09:00:00334506240000
    (参考: The NTP Timescale and Leap Seconds) (この NTP の仕様では、 うるう秒挿入時は NTP time を止め、 時刻問い合わせがあるごとに 1 ナノ秒進めることになっている。 よって UTC, TAI, and UNIX time で指摘されたように時間が逆行することはない (極めてゆっくりと進む)。 しかし ntpd 4.2.0 の実装は仕様通りではなく、 相変わらず逆行するようである)

  6. GPS とうるう秒

    GPS 衛星からの信号は 50bps で、1 フレームは 1500bit である。 つまり、1 フレームの受信には 30 秒かかる。 1 つのフレームは 5 つのサブフレームから構成され、サブフレームの長さは 300bit。 サブフレームの 4 と 5 については、 25 フレームをまとめて一つのマスターフレームを作る。 マスターフレームを完全に受信するには 12.5 分かかる。

    サブフレーム 4 ページ 18 には、 現在の GPS - UTC (Δt LS) の他に、 次回のうるう秒操作が起こる週(WN LFS)と、 操作後の GPS - UTC (Δt LFS) が定義されているので、 GPS 受信機は、

    を事前に知ることができる。 なお、この WN LFS や Δt LFS の情報は、 うるう秒実施の半年前頃から更新されるらしい(未確認)。
  7. ntpd とうるう秒

    ntpd は NTP の参照実装である。

    ntpd version 4 は OS の時計がうるう秒に対応していないことを前提にしているので、 ntpd を動かす OS は、うるう秒を考慮しない設定にしておく必要がある。

    2008 年 12 月 5 日に、開発バージョンである ntp version 4.2.5p149 が リリースされた。 このバージョンではうるう秒をおおむね正しく扱っているようである。

    なお 2008/12/09 時点で FreeBSD の ports/net/ntpd-devel は version 4.2.5p122 になっている。 残念ながらこのバージョンではうるう秒を正しく扱えない。 (leap_sec と leapsec のスペルミスというバグのせいで……。 そんな紛らわしい名前使うなよ……)

    ntpd 4.2.5p149 ではうるう秒の情報を外部ファイルから与えるようになっている。 Leap Indicator (LI) の面倒も ntpd のカーネルがみてくれる。 このため各ドライバはうるう秒のことをほとんど気にしないで済むようになった。 例えば NMEA ドライバ (127.127.20.*) は、 GPS レシーバから 23:59:60 という時刻を受け取ると、エラーとして捨てる。 ntpd に正しいうるう秒情報を与えていれば、これでも正しく動くようである。

    うるう秒情報ファイルは ftp://time.nist.gov/pub/leap-seconds.3629404800 を取得すればよい。 (当サイトのコピーは leap-seconds.3629404800)。 このファイルを /usr/local/etc/leap-seconds.3629404800 に保存し、 ntp.conf に

    leapfile /usr/local/etc/leap-seconds.3629404800
    
    と追加すればよい。 これで ntpd を再起動すれば閏秒挿入に対応した動作をするようになる。。

    ntpd 4.2.5p149 の NMEA ドライバを使い、 疑似的に ntpd に 2008/12/31 の日付を与え、 ntpd の動作を確認してみた。 やたら長いが、recv と trans と LI に注目すると、 2009/01/01 08:59:59 を二度繰り返していることがわかる。 また offset が途中から 1 減っていることもわかる。 (表示されている日付は UTC ではなく JST である。 またクライアントの時計は 2008/12/09 JST。) 59 秒を 2 回繰り返す以外は、おおむね正しい動作である。 (ちなみにこの動作は 2006/01/01 JST のうるう秒挿入時の mfeed のサーバの動作 と似ている。)

    $ sntpc -t 40 -i 100000 ntp-test.example.com
    #host             offset      delay     deviation(o)  (d)
    LI=1 VN=4 Mode=4 St=1 orig=3437797873.562795 2008/12/09 16:51:13.562795 recv=3439756798.564879 2009/01/01 08:59:58.564879 trans=3439756798.565023 2009/01/01 08:59:58.565023 dest=3437797873.563193 2008/12/09 16:51:13.563193 o = 1958925.001956940  d = 0.000253677
    LI=1 VN=4 Mode=4 St=1 orig=3437797873.663953 2008/12/09 16:51:13.663953 recv=3439756798.666029 2009/01/01 08:59:58.666029 trans=3439756798.666104 2009/01/01 08:59:58.666104 dest=3437797873.664259 2008/12/09 16:51:13.664259 o = 1958925.001960516  d = 0.000231266
    LI=1 VN=4 Mode=4 St=1 orig=3437797873.764948 2008/12/09 16:51:13.764948 recv=3439756798.767022 2009/01/01 08:59:58.767022 trans=3439756798.767098 2009/01/01 08:59:58.767098 dest=3437797873.765246 2008/12/09 16:51:13.765246 o = 1958925.001963139  d = 0.000222206
    LI=1 VN=4 Mode=4 St=1 orig=3437797873.865945 2008/12/09 16:51:13.865945 recv=3439756798.868014 2009/01/01 08:59:58.868014 trans=3439756798.868087 2009/01/01 08:59:58.868087 dest=3437797873.866227 2008/12/09 16:51:13.866227 o = 1958925.001964331  d = 0.000209332
    LI=1 VN=4 Mode=4 St=1 orig=3437797873.966944 2008/12/09 16:51:13.966944 recv=3439756798.969013 2009/01/01 08:59:58.969013 trans=3439756798.969083 2009/01/01 08:59:58.969083 dest=3437797873.967222 2008/12/09 16:51:13.967222 o = 1958925.001964808  d = 0.000208378
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.067943 2008/12/09 16:51:14.067943 recv=3439756799.070012 2009/01/01 08:59:59.070012 trans=3439756799.070079 2009/01/01 08:59:59.070079 dest=3437797874.068218 2008/12/09 16:51:14.068218 o = 1958925.001964808  d = 0.000208378
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.168942 2008/12/09 16:51:14.168942 recv=3439756799.171013 2009/01/01 08:59:59.171013 trans=3439756799.171097 2009/01/01 08:59:59.171097 dest=3437797874.169251 2008/12/09 16:51:14.169251 o = 1958925.001958370  d = 0.000225067
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.269941 2008/12/09 16:51:14.269941 recv=3439756799.272011 2009/01/01 08:59:59.272011 trans=3439756799.272087 2009/01/01 08:59:59.272087 dest=3437797874.270228 2008/12/09 16:51:14.270228 o = 1958925.001964569  d = 0.000210762
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.370940 2008/12/09 16:51:14.370940 recv=3439756799.373009 2009/01/01 08:59:59.373009 trans=3439756799.373076 2009/01/01 08:59:59.373076 dest=3437797874.371214 2008/12/09 16:51:14.371214 o = 1958925.001965523  d = 0.000206947
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.471939 2008/12/09 16:51:14.471939 recv=3439756799.474008 2009/01/01 08:59:59.474008 trans=3439756799.474084 2009/01/01 08:59:59.474084 dest=3437797874.472223 2008/12/09 16:51:14.472223 o = 1958925.001965046  d = 0.000207901
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.572938 2008/12/09 16:51:14.572938 recv=3439756799.575007 2009/01/01 08:59:59.575007 trans=3439756799.575074 2009/01/01 08:59:59.575074 dest=3437797874.573213 2008/12/09 16:51:14.573213 o = 1958925.001965046  d = 0.000207901
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.673937 2008/12/09 16:51:14.673937 recv=3439756799.676006 2009/01/01 08:59:59.676006 trans=3439756799.676088 2009/01/01 08:59:59.676088 dest=3437797874.674226 2008/12/09 16:51:14.674226 o = 1958925.001965523  d = 0.000206947
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.774937 2008/12/09 16:51:14.774937 recv=3439756799.777006 2009/01/01 08:59:59.777006 trans=3439756799.777074 2009/01/01 08:59:59.777074 dest=3437797874.775213 2008/12/09 16:51:14.775213 o = 1958925.001965046  d = 0.000207901
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.875936 2008/12/09 16:51:14.875936 recv=3439756799.878004 2009/01/01 08:59:59.878004 trans=3439756799.878084 2009/01/01 08:59:59.878084 dest=3437797874.876222 2008/12/09 16:51:14.876222 o = 1958925.001965046  d = 0.000205994
    LI=1 VN=4 Mode=4 St=1 orig=3437797874.976935 2008/12/09 16:51:14.976935 recv=3439756799.979004 2009/01/01 08:59:59.979004 trans=3439756799.979071 2009/01/01 08:59:59.979071 dest=3437797874.977209 2008/12/09 16:51:14.977209 o = 1958925.001965523  d = 0.000206947
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.077934 2008/12/09 16:51:15.077934 recv=3439756799.080003 2009/01/01 08:59:59.080003 trans=3439756799.080078 2009/01/01 08:59:59.080078 dest=3437797875.078215 2008/12/09 16:51:15.078215 o = 1958924.001966000  d = 0.000205994
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.178933 2008/12/09 16:51:15.178933 recv=3439756799.181002 2009/01/01 08:59:59.181002 trans=3439756799.181069 2009/01/01 08:59:59.181069 dest=3437797875.179207 2008/12/09 16:51:15.179207 o = 1958924.001965523  d = 0.000206947
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.279932 2008/12/09 16:51:15.279932 recv=3439756799.282002 2009/01/01 08:59:59.282002 trans=3439756799.282069 2009/01/01 08:59:59.282069 dest=3437797875.280211 2008/12/09 16:51:15.280211 o = 1958924.001964092  d = 0.000211716
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.380931 2008/12/09 16:51:15.380931 recv=3439756799.383000 2009/01/01 08:59:59.383000 trans=3439756799.383071 2009/01/01 08:59:59.383071 dest=3437797875.381138 2008/12/09 16:51:15.381138 o = 1958924.002001047  d = 0.000135899
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.481930 2008/12/09 16:51:15.481930 recv=3439756799.483999 2009/01/01 08:59:59.483999 trans=3439756799.484066 2009/01/01 08:59:59.484066 dest=3437797875.482205 2008/12/09 16:51:15.482205 o = 1958924.001965046  d = 0.000207901
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.582929 2008/12/09 16:51:15.582929 recv=3439756799.584998 2009/01/01 08:59:59.584998 trans=3439756799.585078 2009/01/01 08:59:59.585078 dest=3437797875.583217 2008/12/09 16:51:15.583217 o = 1958924.001964808  d = 0.000208378
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.683928 2008/12/09 16:51:15.683928 recv=3439756799.685997 2009/01/01 08:59:59.685997 trans=3439756799.686069 2009/01/01 08:59:59.686069 dest=3437797875.684208 2008/12/09 16:51:15.684208 o = 1958924.001965046  d = 0.000207901
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.784928 2008/12/09 16:51:15.784928 recv=3439756799.786997 2009/01/01 08:59:59.786997 trans=3439756799.787072 2009/01/01 08:59:59.787072 dest=3437797875.785211 2008/12/09 16:51:15.785211 o = 1958924.001965046  d = 0.000207901
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.885927 2008/12/09 16:51:15.885927 recv=3439756799.887995 2009/01/01 08:59:59.887995 trans=3439756799.888064 2009/01/01 08:59:59.888064 dest=3437797875.886202 2008/12/09 16:51:15.886202 o = 1958924.001964808  d = 0.000205517
    LI=1 VN=4 Mode=4 St=1 orig=3437797875.986927 2008/12/09 16:51:15.986927 recv=3439756799.988995 2009/01/01 08:59:59.988995 trans=3439756799.989062 2009/01/01 08:59:59.989062 dest=3437797875.987200 2008/12/09 16:51:15.987200 o = 1958924.001965046  d = 0.000205994
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.087924 2008/12/09 16:51:16.087924 recv=3439756800.089995 2009/01/01 09:00:00.089995 trans=3439756800.090076 2009/01/01 09:00:00.090076 dest=3437797876.088215 2008/12/09 16:51:16.088215 o = 1958924.001966000  d = 0.000209808
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.188924 2008/12/09 16:51:16.188924 recv=3439756800.190993 2009/01/01 09:00:00.190993 trans=3439756800.191073 2009/01/01 09:00:00.191073 dest=3437797876.189212 2008/12/09 16:51:16.189212 o = 1958924.001965046  d = 0.000207901
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.289923 2008/12/09 16:51:16.289923 recv=3439756800.291995 2009/01/01 09:00:00.291995 trans=3439756800.292065 2009/01/01 09:00:00.292065 dest=3437797876.290207 2008/12/09 16:51:16.290207 o = 1958924.001965046  d = 0.000213623
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.390925 2008/12/09 16:51:16.390925 recv=3439756800.392993 2009/01/01 09:00:00.392993 trans=3439756800.393061 2009/01/01 09:00:00.393061 dest=3437797876.391131 2008/12/09 16:51:16.391131 o = 1958924.001999140  d = 0.000137806
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.491921 2008/12/09 16:51:16.491921 recv=3439756800.493989 2009/01/01 09:00:00.493989 trans=3439756800.494057 2009/01/01 09:00:00.494057 dest=3437797876.492195 2008/12/09 16:51:16.492195 o = 1958924.001965046  d = 0.000205994
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.592920 2008/12/09 16:51:16.592920 recv=3439756800.594999 2009/01/01 09:00:00.594999 trans=3439756800.595253 2009/01/01 09:00:00.595253 dest=3437797876.593443 2008/12/09 16:51:16.593443 o = 1958924.001944542  d = 0.000268936
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.693919 2008/12/09 16:51:16.693919 recv=3439756800.695990 2009/01/01 09:00:00.695990 trans=3439756800.696110 2009/01/01 09:00:00.696110 dest=3437797876.694251 2008/12/09 16:51:16.694251 o = 1958924.001964808  d = 0.000212193
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.794918 2008/12/09 16:51:16.794918 recv=3439756800.796987 2009/01/01 09:00:00.796987 trans=3439756800.797065 2009/01/01 09:00:00.797065 dest=3437797876.795204 2008/12/09 16:51:16.795204 o = 1958924.001964808  d = 0.000208378
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.895917 2008/12/09 16:51:16.895917 recv=3439756800.897987 2009/01/01 09:00:00.897987 trans=3439756800.898078 2009/01/01 09:00:00.898078 dest=3437797876.896218 2008/12/09 16:51:16.896218 o = 1958924.001965046  d = 0.000209808
    LI=0 VN=4 Mode=4 St=1 orig=3437797876.996917 2008/12/09 16:51:16.996917 recv=3439756800.998986 2009/01/01 09:00:00.998986 trans=3439756800.999062 2009/01/01 09:00:00.999062 dest=3437797876.997200 2008/12/09 16:51:16.997200 o = 1958924.001965523  d = 0.000206947
    LI=0 VN=4 Mode=4 St=1 orig=3437797877.097916 2008/12/09 16:51:17.097916 recv=3439756801.099988 2009/01/01 09:00:01.099988 trans=3439756801.100086 2009/01/01 09:00:01.100086 dest=3437797877.098231 2008/12/09 16:51:17.098231 o = 1958924.001963615  d = 0.000216484
    LI=0 VN=4 Mode=4 St=1 orig=3437797877.198915 2008/12/09 16:51:17.198915 recv=3439756801.200988 2009/01/01 09:00:01.200988 trans=3439756801.201059 2009/01/01 09:00:01.201059 dest=3437797877.199197 2008/12/09 16:51:17.199197 o = 1958924.001967430  d = 0.000210762
    LI=0 VN=4 Mode=4 St=1 orig=3437797877.299913 2008/12/09 16:51:17.299913 recv=3439756801.301984 2009/01/01 09:00:01.301984 trans=3439756801.302056 2009/01/01 09:00:01.302056 dest=3437797877.300195 2008/12/09 16:51:17.300195 o = 1958924.001965761  d = 0.000210285
    LI=0 VN=4 Mode=4 St=1 orig=3437797877.400913 2008/12/09 16:51:17.400913 recv=3439756801.402982 2009/01/01 09:00:01.402982 trans=3439756801.403050 2009/01/01 09:00:01.403050 dest=3437797877.401187 2008/12/09 16:51:17.401187 o = 1958924.001966238  d = 0.000206470
    LI=0 VN=4 Mode=4 St=1 orig=3437797877.501912 2008/12/09 16:51:17.501912 recv=3439756801.503981 2009/01/01 09:00:01.503981 trans=3439756801.504057 2009/01/01 09:00:01.504057 dest=3437797877.502195 2008/12/09 16:51:17.502195 o = 1958924.001965523  d = 0.000206947
    ntp-test.example.com    1958924.376965857 2.089e-04 4.895e-01 2.095e-05
    

    ※以下は 2005/12/31 閏秒挿入時に書いたものである。参考までに。

    --------------------------------------

    ntpd は NTP の参照実装で、2003 年 10 月に version 4.2.0 がリリースされている。 ntpd には参照クロックドライバがいくつか用意されており、 原子時計 や GPS や 電波時計などから、時刻を入力できるようになっている。 参照クロックドライバは、ntpd のカーネルへと時刻を伝えるが (関数 refclock_process())、 そこで与える時刻は、年月日時分秒で表すことになっている。 ntpd カーネルはその時刻を NTP time に変換した上で(関数 clocktime())、 処理を続ける。 この関数 clocktime() は、UNIX の標準関数である mktime(3) は使用せず、 自前で変換アルゴリズムを用意している。 そのアルゴリズムでは、うるう秒は考慮されていない。

    NTP は、うるう秒調整日には、 パケットの Leap Indicator (LI) をセットすることになっている。 上位の NTP サーバが LI をセットすれば、 下位の NTP サーバは、それを順次伝えて行く。 では最上位 (Stratum 1) の NTP サーバに、うるう秒調整日を教えるのはだれか? 実は、それも各参照クロックドライバにまかされているのである。 そして、LI を設定する参照クロックドライバは、全体の 3 割だけだ。 7 割のドライバは LI をセットしない(うるう秒に対応していない)。 (例えば GPS で一般的に使われている NMEA フォーマット用のドライバは、 LI をセットしない。) また、たとえドライバがうるう秒に対応していたとしても、 接続する機器がうるう秒を正しく処理するかどうかはわからない。

    LI がセットされていたとして、 それを理解して、内部に保持する NTP time を調整するのは NTP クライアントの仕事である。 実はStratum 1 の NTP サーバも、 参照クロックドライバから疑似的な NTP パケットを受信する NTP クライアントである。 ところが、ntpd 4.2.0 には LI を処理するコードが含まれていない。 従ってドライバが LI を設定しても、 ntpd の保持する NTP time には、うるう秒調節が行われない。

    ドライバが LI を設定しない場合どうなるか。

    1. 2006/01/01 08:59:59 までは、正しい NTP time を返す。
    2. 2006/01/01 08:59:60 も正しい NTP time を返す。
    3. 2006/01/01 09:00:00 以降、NTP time は 1 秒大きい値を返す。
    4. 一定時間経過すると、GPS に対する offset が -1 秒になる。 NTP time は 1 秒大きい値を返す。
    5. さらに一定時間経過すると、時刻修正を行い時刻を 1 秒もどす。 NTP time 正しい値を返すようになる。 同時に UNIX time も調整される。
    --------------------------------------
  8. 望ましい対処

  9. おまけ: FreeBSD とうるう秒

    FreeBSD 4 以降の場合、標準ではうるう秒を考慮しない設定になっている。 うるう秒を考慮するようにするには、
    # cd /usr/src/share/zoneinfo/
    # vi leapseconds
    Leap 1998 の行の下に、以下の行を挿入する。
    Leap    2005    Dec     31      23:59:60        +       S
    
    # make clean
    # make LEAPSECONDS=yes install
    # cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
    
    とする。 元に戻すには
    # cd /usr/src/share/zoneinfo/
    # make clean
    # make install
    # cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
    
    とする。 これは mktime(3), gmtime(3) 等の関数の動作に影響を与えるが、 各コマンドは起動時に /etc/localtime を参照するだけなので、 動作中のコマンドには影響しない。

    うるう秒を考慮する /etc/localtime と、考慮しない /etc/localtime をそれぞれ /etc/localtime.with_leap (73 バイト), /etc/localtime.without_leap (257 バイト) などとコピーしておけば、

    # cp /etc/localtime.with_leap /etc/localtime   (うるう秒を考慮するようにする。)
    # cp /etc/localtime.without_leap /etc/localtime   (うるう秒を考慮しないようにする。)
    
    のように簡単に切替えが可能になる。
  10. うるう秒の時の ntpd の動作

    当方で管理している ntpd は何一つうるう秒対応らしいことをしていない。 2005/12/31 UTC うるう秒挿入時、その ntpd の動作を検証した。 (ちなみに参照クロックはジュピター GPS)

[戻る]