2層のエンコーディングがUnix timeを構成しています。 最初の層では、1970年1月1日木曜日00:00:00 UTCから経過した秒数を表すスカラー実数として時刻のポイントをエンコードします。
UTCの標準として、この記事はグレゴリオ暦を使用して日をラベル付けし、時間、分、秒単位で各日中の時間を数えています。
Encoding time as a numberEdit
Unix time is a single signed number that increment every second, which makes it easier to store and manipulate than conventional date systems.
Unix のエポックは 1970 年 1 月 1 日の 00:00:00 UTC の時刻である。 この定義には、UTC が 1972 年まで現在の形で存在しなかったという問題があります。
Unixの時間番号はUnixエポックでは0であり、エポックから1日ごとに正確に86400ずつ増加します。 したがって、エポックから12677日後の2004-09-16T00:00:00Zは、12677×86400=1095292800のUnix時間番号で表されます。 これはエポックから逆方向にも拡張でき、負の数を使用します。エポックから4472日前の1957-10-04T00:00:00Zは、Unix時間番号-4472×86400=-386380800で表されます。
Unix時間はエポックに基づいており、Unixエポックが唯一のエポックであると一般に誤解されているため、Unix時間はエポックタイムと呼ばれることがあります。
うるう秒編集
上記の方式は、86400秒の継続時間を持つ通常のUTC日に、Unix時間の数値が真夜中をまたいで連続的に変化することを意味します。 例えば、上記の例で使用される日の終わりに、時間表現は次のように進行する:
うるう秒が発生すると、UTC日は正確に86400秒ではなく、Unix時間番号(毎日正確に86400で常に増加する)は不連続性を経験する。 うるう秒には正の数と負の数があります。 負のうるう秒はこれまで宣言されていないが、もし宣言された場合、負のうるう秒のある日の終わりに、Unixの時刻番号が次の日の始まりに1だけジャンプアップすることになる。 1年半に1回程度ある正のうるう秒の日は、うるう秒の間、Unixの時刻が翌日まで連続して増加し、うるう秒が終わると1だけ戻って(翌日の始まりに戻る)ジャンプします。 たとえば、1998 年末に POSIX.1 に厳密に準拠したシステムでこのようなことが起こりました。
正のうるう秒の直後の秒数で Unix 時間番号が繰り返される。 つまり、閏秒の開始時刻 (2016-12-31 23:59:60) を指すことも、1 秒後の終了時刻 (2017-01-01 00:00:00) を指すことも可能です。 負のうるう秒が発生する理論的なケースでは、あいまいさは発生しませんが、代わりに UTC 時間の任意のポイントをまったく参照しない Unix 時間番号の範囲が存在します。
UNIX クロックは、しばしばネットワーク時間プロトコル (NTP) と関連した正のうるう秒処理の異なるタイプで実装されています。 これは POSIX 標準に準拠しないシステムを生み出します。
UTC閏秒を含まない期間を扱う場合、2つのUnix時間番号の差は、対応する時間点間の期間の秒数に等しくなります。 これは一般的な計算手法である。 しかし、うるう秒が発生する場合、このような計算では間違った答えが得られます。 このレベルの精度が必要なアプリケーションでは、Unix時間を扱うときにうるう秒の表を参照する必要があり、この問題に悩まされない別の時間エンコーディングを使用することが望ましい場合が多い。
Unix時間番号は、Unix時間番号の商と86400のモジュロを取ることによってUTC時間に簡単に変換して戻すことができる。 商はエポックからの日数で、モジュラスはその日のUTC深夜からの秒数です。 正のうるう秒のために曖昧なUnix時間番号が与えられた場合、このアルゴリズムはそれを真夜中直後の時間として解釈する。 うるう秒の間の時刻を生成することはない。 負のうるう秒のために無効なUnix時間番号が与えられた場合、同様に無効なUTC時間を生成する。
Non-synchronous Network Time Protocol-based variantEdit
一般にMillsスタイルのUnixクロックは、Unixタイムナンバーの変更と同期しないうるう秒の処理で実装されています。 閏秒が発生すべき場所では、最初に時間番号が減少し、閏秒の1秒後に正しい時刻に閏します。 これは実装を容易にするもので、Millsの論文で説明されている。 これは、閏秒の状態変数に注目することで、閏秒がまだ実行されていないかどうかを明確に示すことができ、正しく解読することができる。 状態変数の変化はうるう秒と同期しています。
同様の状況は、負のうるう秒でも発生し、スキップされる秒はわずかに遅すぎます。 ごく短時間、システムは名目上不可能な時間番号を表示するが、これはTIME_DEL状態によって検出され、修正される。
このタイプのシステムでは、Unix時間番号はうるう秒の両方のタイプでPOSIXに違反する。 時刻番号と一緒にうるう秒状態変数を収集することで、明確なデコードが可能になり、必要に応じて正しいPOSIX時刻番号を生成したり、完全なUTC時刻をより適切な形式で保存したりすることができます。 これは、挿入された閏秒の全体にわたってTIME_INS状態を示し、次に秒のカウントを繰り返しながら次の秒の全体にわたってTIME_WAITを示すことによって達成されるであろう。 これには、同期的なうるう秒の処理が必要である。
TAI-based variantEdit
Unix time keepingのもう一つの、はるかにまれな、不適合な変形は、UTCではなくTAIをエンコードすることを含んでいます; いくつかのLinuxシステムはこの方法で構成されています。 TAI にはうるう秒がなく、すべての TAI の日は正確に 86400 秒であるため、このエンコーディングは実際には 1970-01-01T00:00:00 TAI から経過した秒の純粋な線形カウントとなります。 このため、時間間隔の計算が非常に簡単になります。
これらのシステムでは、UTCと擬似Unix時間表現の間を正しく変換するために、うるう秒のテーブルを参照する必要がある。 IANAタイムゾーン・データベースはうるう秒の情報を含んでおり、同じソースから入手できるサンプルコードはその情報を使ってTAIベースのタイムスタンプとローカルタイムとの間の変換を行うものである。 また、1972年に現在のUTCの形式が始まる以前は、変換に定義上の問題がありました(下記のUTCの基礎の項を参照)。
このTAIベースのシステムは、表面的には似ていても、Unix時間ではありません。 これはPOSIXの時刻の値とは数秒異なる値で時刻を符号化する。 このシステムのバージョンはISO Cのtime.h
に含めるよう提案されたが、2011年にUTC部分のみが受け入れられた。 tai_clock
は、しかし、C++20に存在する。
数字を表現する編集
Unix時間番号は、数字を表現できる任意のフォームで表現することができる。 いくつかのアプリケーションでは、数値は単に10進数の文字列としてテキストで表現され、些細な追加問題しか発生しません。
時間のポイントを表す Unix time_t
データ型は、多くのプラットフォームでは、伝統的に 32 ビット (ただし後述) の符号付き整数で、前のセクションで説明したように Unix 時間番号を直接コード化します。 32ビットであることは、合計で約136年の範囲をカバーすることを意味します。 表現可能な最小の日付は1901-12-13金曜日で、表現可能な最大の日付は2038-01-19火曜日である。 03:14:07 UTC 2038-01-19の1秒後に、この表現はオーバーフローする。
いくつかの新しいオペレーティングシステムでは、time_t
は 64 ビットに拡張されました。 これは両方向で約 2,930 億年の時間を表現できるようになり、 一方向では現在の宇宙年齢の 20 倍以上になります。
もともと Unix の time_t
は符号付きか符号なしかで論争がありました。 もし符号なしであれば、将来の範囲は 2 倍になり、32 ビットのオーバーフローを (68 年) 先送りにすることができます。 しかし、その場合、エポック以前の時間を表現することができなくなります。 このため、time_t
を符号付きにすることがコンセンサスとなっており、これが通常の慣行となっている。 QNX オペレーティング システムのバージョン 6 のソフトウェア開発プラットフォームでは、符号なしの 32 ビット time_t
が使用されていますが、古いリリースでは符号付きのタイプが使用されています。
POSIX と Open Group Unix 仕様には C 標準ライブラリがあり、これには <time.h>
ヘッダーファイルで定義された時間タイプと関数が含まれます。 ISO C標準では、time_t
は算術型でなければならないとされているが、特定の型やエンコーディングを義務付けてはいない。 POSIX は time_t
が整数型であることを要求しているが、符号付きか符号なしかは指定していない。
Unix には非整数の Unix 時間数値をバイナリ分数として直接表現する伝統はない。 その代わり、サブ秒の精度を持つ時間は 2 つの整数からなる複合データ型を使用して表現され、最初の整数は time_t
(Unix 時間の整数部分)、2 番目の整数は時間番号の小数部分を百万分の一 (struct timeval
) または億分の一 (struct timespec
) で表します。 これらの構造は10進数ベースの固定小数点データフォーマットを提供し、いくつかのアプリケーションでは有用であり、他のアプリケーションでは変換が簡単である。
UTC basisEdit
うるう秒を含むUTCの現在の形式は、1972年1月1日からのみ定義されている。 それ以前は、1961年1月1日以降、非整数の秒数による時間ステップが時々あるだけでなく、UTC秒がSI秒よりわずかに長く、地球の自転を連続的に近似するために周期的に変化するUTCの古い形式がありました。 1961 年以前には UTC はなく、1958 年以前には原子時計は普及していませんでした。
UTC のエンコーディングとして Unix 時間を正確に定義することは、UTC の現在の形に適用するときだけ議論の余地がありません。 1970年1月1日(Unixエポック)から1972年1月1日(UTCの開始)までの日数は問題ではなく、日数がUnix時間にとって重要なすべてです。
+63072000以下(つまり、1972年1月1日より前)のUnix時間値の意味は正確には定義されていません。 そのような Unix 時間の基本は、UTC の不特定な近似であると理解するのが最もよいでしょう。 当時のコンピューターは、サブ秒のタイムスタンプを提供できるほど正確に時計をセットしていることはほとんどありませんでした。 Unix時間は、秒以下の精度を必要とするアプリケーションで1972年以前の時間を表現するのに適した方法ではありません。そのようなアプリケーションは、少なくとも、使用するUTまたはGMTの形式を定義しなければなりません。
2009年の時点で、市民時間でのうるう秒の使用を終了する可能性が検討されています。 この変更を実行する可能性の高い方法は、国際時間と呼ばれる新しい時間スケールを定義することで、最初はUTCと一致するが、その後は閏秒がないため、TAIから一定のオフセットを保つことができる。 もしそうなれば、Unixの時間は将来的にUTCではなく、この新しい時間スケールで定義される可能性が高いです。 もし、UTCにうるう秒がなければ、結果は同じです
。