システムがうるう秒を含めているかどうかの判定
実のところ「うるう秒を使わない」とすることが現状では一番の安全策である。
(うるう秒が入るときには時計の時刻を増減させて対応する。)
よって、以下の話は、うるう秒を使う場合、または、うるう秒が入ってしまわないかの確認のためのものとなる。
実質的には以下の3システムがあることになるが、TAIとUTC(うるう秒非対応)は区別が付かない。(実測値との比較が必要になる。)
UTC(うるう秒非対応(一般的))
経過時間はUTC(正確にはepochからの経過時刻にうるう秒を含まない)、表示時刻はUTC
UTC(うるう秒対応)
経過時間はTAI(正確にはepochからの経過時刻にうるう秒を含む)、表示時刻はUTC
TAI(まず存在しないが、うるう年非対応のシステムをTAIに同期させるとこうなってしまう。)
経過時間はTAI、表示時刻はTAI
NTPは、経過時間で UTC になっている。うるう秒はインジケーターのみになっている。
本来は単純に判定用フラグで取得されるべき情報だが、残念ながら標準的な方法がどこにもない。
よって、以下のいずれかの方法になる。
システム依存の既存の設定ファイルなどを確認する。
システム依存の既存の時間APIを通して確認する。
ユーザーに設定ファイルを書いてもらう。
アプリケーション提供者が決め打ちする。
これがずれていると、時刻がずれるトラブルが発生してしまう。
一般的なシステムでは少なくとも1970年以降を計算可能なはず。
(一部のシステムでは2000年以降しか考慮されていないケースがある模様)
ISO 8601では、2000年1月1日を曜日の起点とし、土曜日としている。
tz database を正しく取り込めていない可能性があるため、2000年の直近のうるう秒挿入時を確かめるのが安全。
カレンダーを現在時刻の周辺しか持っていない可能性からすると、さらに安全な判定は直近のうるう秒挿入時になるが、
一方で、カレンダーの更新が行われず、古いうるう秒データベースを参照している可能性がある。
C言語では time_t の基準時刻(epoch)は定義されていない。(要注意)
POSIX では time_t の基準時刻(epoch)を "00:00:00 GMT, January 1, 1970" と定義している。
https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap03.html
POSIX では経過時間にうるう秒を含むかどうかは定義していない。(要注意)
2005-12-31 23:59:59 UTC と 2006-01-01 00:00:00 UTC との間が2秒ならうるう秒挿入あり、1秒ならうるう秒挿入なしになる。
C言語
なぜか mktime はローカル時刻からの変換しかないため、環境変数 TZ を UTC に設定してから処理を行う。
timegm
関連
うるう秒
うるう秒に対する各OSの対応