私は最近UNIX Timeについて多くを読みましたが、そのほとんどは一貫しておらず矛盾していました。 UNIX Time(以下、UXT)、TAI、UTC間の変換を調整しようとしていますが、そのためにはUXTを正しく理解する必要があります。問題は、これを行う他の人が見つからないことです。
以下は、厳しい研究を通じて、数多くのソースから再構成された最良の説明です。何か間違ったこともあります。 以下の包括的な分析と点別検証/反論を求めています。デフォルトで正しく機能するには、次の内容を修正してください。
TAIは鍛造の増加時間標準です。 SI秒単位で測定され、DSTとうるう秒を無視します。
UTCはTAIと同じですが、天文の場合、基準UT1の0.9SI秒以内になるように整数潤滑SI秒(60秒で反映される時間文字列に変換)に変更されます。
UXTはカウントです。UNIX秒1970年1月1日00:00:00 UTCから。一日は常に正確に86400秒です。ただし、UXTはUTCに関連しています。
どうやってこれができますか?素晴らしい、UNIX秒はSI秒と異なる必要があります。、うるう秒は完全に規則的ではないため、UNIX秒は明確に定義された時間長にすることはできません。
UTCからUXTへの変換UNIX仕様セクション4.15異なるUTC時間を同じUXTタイムスタンプにエイリアスとして割り当てます。UNIX秒をSI秒と効果的に等しくします(2つのSI秒、UNIXうるう秒を除く)。。
実際に何が起こっているのかはさまざまです。ほとんどのコンピュータはリモートサーバーに基づいて同期するため、同期中にうるう秒の更新を暗黙的に処理します。この意味は、各個別のUXTタイムスタンプをUTCに簡単に変換できることです(次を使用)。
gmtime
あるいは、それぞれ§4.15)、何も調べるために算術を実行するために実際に使用することはできません。特に、difftime
UNIX 秒を返します。したがって、関連するうるう秒がすべてどこにあるかを知らない限り、他のタイムスタンプに追加することを含めることはできません。
ここまでは理解したようです。
- しかし、今実際のコードを見ると、これらのことはまったく行われません。私は人々が測定された期間を使用し
difftime
、それが十分に良いことを望む(または問題があることを知らずに)理解することができますが、タイミングライブラリも間違っています。
例として、libtai
tai_now.c:7
次のようにUXTからTAI()への変換を提供しますTAI := 4,611,686,018,427,387,914 + UXT
。 TAIはSI秒を計算し、UXTはUNIX秒を計算するため、これを行うことはできません。しかし、libtai
うるう秒は明示的に扱われるので、これが不注意なエラーであると見るのは合理的ではありません。
に限定されませんlibtai
。この現象はどこでも見ることができます。
したがって、ポイント1~6はポイント7と一致しない。つまり、既存のコードの多くは、それが表す時間基準と矛盾します。 何が間違っていますか?
答え1
問題は、ほとんどの文書があいまいな文章なしで時間スケールを区別できる語彙を使用しないことです。私はお勧めしますhttp://www.ucolick.org/~sla/leapsecs/picktwo.htmlこの問題の紹介として、歴史的使用法には互いに関連しない2種類の秒があります。 1つは地球の居住者のカレンダー日のセグメンテーションで、もう1つは特定の基準フレームで測定された一定の期間です。 1970年前後の日付にわたるすべてのタイムライブラリは、両方の秒を利用しようとし、最終的にarcsin(-2)を提供すると主張する関数と同様の答えを提供します。重要。
答え2
素晴らしい。 。 。あなたの将来の自己はここにあり、終結感のために書いています。
あなたがこの質問を書いてから数年が経ちましたが、今日になる数年前、あなたはこう書いています。巨大なチュートリアルこれで問題が解決しました。これは、TAIからUTC、オフセット、UXTまでの現代の時間基準の完全なガイドで構成されています。
あなたの質問に関しては、番号1-6が実際には基本的に正しいようです。あなたのポイント7は「ソフトウェア不可能本当にできませんよね? 」
スポイラー警告:それはできる。 libtaiに関する具体的な苦情は良い例ではありません。ライブラリには、うるう秒が含まれていますが、見ている単一の機能だけでなく、適切な機能を組み合わせる必要があります。私たちにとって、これは大きな(そして明らかに混乱した)欠陥のように感じられ、それが正解になっても(それなら誰が知っていますか)、この種のことは非常に一般的であるため、それについてハーフムーンをすることは役に立ちません。ほとんどのソフトウェアは実際に問題が発生するだけでなく、ソフトウェアは異なる互換性のない方法で問題が発生します!
こんな、文書デフォルトのUXTプリミティブではtime(...)
明確ではありません。標準C文書(引用)、(引用)、POSIX規格に準拠(一部)(引用)これがepoch以降の秒数であるとしましょう。しかし、POSIX規格の他の場所では(引用)、これは秒数ではなく、エポック以降の秒数です。うるう秒を除く、これは正しい表現です。計算をより簡単にする意図ですが、減算のため計算がより困難になることは明らかです。動作しません垂直線に不連続性を導入するとき。difftime(...)
たとえば、使用されるすべての手順は不正確な場合があります。
ここで重要な精神モデルは、SI秒とUNIX秒が異なるということです。これはPOSIX仕様の他の部分で最も明確です。(引用)。このセクションでは、日時変換を介してUXTをUTCに接続します。 UTCにはうるう秒が含まれていますが、このセクションでは返品指定された日付の長さは86,400秒です。私たちはこれをどのように調和させることができますか?重要な悟りは、一部のUNIX秒の長さが2SI秒で、一部が0(明らかにほとんどは1)です。まだ混乱していますか?行ってチュートリアルを読んでください!実際のコードがあまりにも汚れているのは当然です。
残念ながら、コーディングを通じて読者を案内することはできません。独自のタイミングライブラリを作成しましたが、これは複雑で強力で、まだ実際に生産する準備ができていません。
time(...)
まず、POSIXエポックの相対数であるUNIX秒を取得し、220 924 790を減算してから(テーブルから)うるう秒を追加して、SI秒のTAIエポック相対数を取得する呼び出しをしたいと思います。復帰するには逆順で実行してください。 (注:TAI時代は少しあいまいです。私は1977-01-01 00:00:00 TAI(例:1976-12-31 23:59:45 UTC)を選択しました。これは標準化されたTAIであるJD TAIの時代です。だからです。(引用).)
C++20ではstd::chrono::tai_clock
、時代は1958-01-01 00:00:00 TAI(つまり、1957-12-31 23:59:50 UTC)です。うまくいけば、これは正確であり、私たちはこれらすべての醜いことを私たちの後ろに置くことができます。
答え3
あなたは正しいです。この混乱はひどいです。私の結論:
UXTは、うるう秒の間を除いてUTCと同じです。ここで、UTCは60まで計算され、UTXは1秒間「停止」します。
答え4
精神的健康のための最良の方法は、1日に例外なく86,400秒があると仮定することです。これはほとんどの人にとって十分な時間です。今の時間を計算して5,000 x 86,400秒を除くと、5,000日前とまったく同じ時、分、秒が出ます。
Posix時間はUTCですが、うるう秒が削除されました。つまり、常にUT1(太陽時)に非常に近く、最大0.9秒差があります。最良の精神モデルは、うるう秒がUTCに追加または削除されるたびに、Posix時間で2秒の長さの秒になるか、0秒の長さの秒になるということです。うるう秒が発生する正確な瞬間にストップウォッチを使用すると、Posixによると、ストップウォッチに応じて特定の分は61秒または59秒かかります。または、コンピュータに秒が表示された時計が表示されている場合、秒数は1秒間静止しているか、任意のポイントで2秒間ジャンプします。うるう秒が取り除かれた瞬間以外は観察できません。 Posix システムにはこれらの変更の兆候はありません。
これはいつ間違っていますか?適切な時間に100mのレースがあり、Posix時間に基づいて開始と終了時間を記録すると、誰かが開始後9.317秒でレースを完了できます。実際には10.317秒になります。したがって、実際のデータがある場合、時間間隔が1秒ずつずれることがあります。
どうすれば解決できますか?この問題を解決できる唯一の方法は、うるう秒を挿入するテーブルを作成し、これを利用して「うるう秒のないUTC」をTAIに変えることです。
Posix時間はそうではありません。本物UTCにはうるう秒はありませんが、システムにはUTCに関する最高の情報があります。コンピュータの時計を「手動」に変更でき、Posix時間はオフになります。コンピュータの時計は多少不正確であり、タイムサーバーによって変更される可能性があります。この場合、再修正される前に1日2秒ずつUTCから外れることがあります。
この問題を抱えているアプリがありますが、iOS(通常はPosixにある)に開始時刻を返すsysctl呼び出しがあります。時計が変更されると、この関数は変更されたすべての秒を除いて変更された日付を返します。コンピュータを再起動すると、変更された日付も返されます。したがって、最後に既知の値を保存してブート時間が変更された場合は、タイムサーバーに問い合わせることができます。