システムで時間が重要な役割を果たしていますか? あなたのユーザー/コンポーネントは世界中に分布していますか、それとも少なくとも私たちの広大な故郷ですか? したがって、タイムゾーンが必要です。 まあ、それは簡単です。 あなたがしなければならない最も難しいことは、混乱しないことです。 これについてお話します。 まず、正しく考えることを学ぶ必要があります。 正しく考えると、他のすべては自明であるか、あなたにとって十分に単純なものになります。
時計から始めましょう。 私たちは皆、壁の時計を見ることで時間を決定することに慣れています。 タイムゾーンを使用する場合、この時間は
Wall clock timeと呼ばれます。 原則として、何も問題はありません。同時に地球上の異なる場所でのみ、時計は異なる時間を表示します。 目標を設定すると、ウォールクロック時間をあるタイムゾーンから別のタイムゾーンに変換するためのアルゴリズムを思い付くことができます。 通常、夏時間/冬時間への移行の瞬間を除いて、タイムゾーン間の時間の差を加算/減算する必要があります。 移行が始まると、計算が非常に複雑になります。
整数など、シンプルで防弾的なものが必要です。
これは、1970年1月1日00:00:00から経過した秒数(Javaではミリ秒単位)である、インスタントインタイム(インスタントインタイム、Unix時間、POSIX時間、(unix)エポックからの時間)の概念の表示方法です。 GMT 時間は世界中で同じです。誰かが「一時停止」をクリックして時間の流れが止まったと想像すると、地球全体の時間に対応する数字はタイムゾーンに関係なく同じになります。 グリニッジが新しい1970を開始してから1時間後に誰かが一時停止した場合、地球全体の時点は3,600,000を示します。 そして今、例えば、これはすでに番号1 280 720 431.859です。
ですから、その瞬間は、時間計算の普遍的な転換通貨です。 それは、うーん、時間、瞬間のみに依存します(それぞれ、どのイベントが早く発生したか、後で発生したかを判断するために)。これには、地理的位置、タイムゾーン、クロック転送に関連するナンセンスは含まれません。そのような計算の信頼性。 実際、これは時間の処理がJava(バージョン1.1以降)で実装される方法です。ここで、java.util.Dateは時間の長いラッパー(負のlongは1970年以前の日付に対応)であり、比較可能であり、すべての人間のカレンダー変換CalendarクラスとDateFormatクラスを別々に移動しました。
変換について。 1 280 720 431.859という数字は普通の人にはほとんど言いません(ただし、好奇心reader盛な読者はこれらの行を書いたときにそれから時間を計算できます)ので、時間の瞬間を壁時計の時間に変換できる必要があります時間内に。 しかし、これらの変換では、すでにタイムゾーンを知る必要があり、これらの計算は決して簡単ではありません。 事実、異なる国/地域/場所では、GMT(GMT)に関して異なるオフセットを行うだけでなく、これらのオフセットのルールは歴史的に数回変更され、変更を続けています(夏時間の導入/キャンセル、ベルトの組み合わせ-聞いたおそらく、私たちが持っているそのようなイニシアチブについてですか?または、たとえば、90年代初頭にGMT + 7からGMT + 6に移動したノヴォシビルスクの故郷を思い出してください。 、異なる銀行には異なるベルトがありました)。 要するに、気が狂わないように、この歴史的情報はすべて、アーサー・デイビッド・オルソンの創始者にちなんで名付けられた
オルソン・ツッツ・データベースの形で注意深く管理されてい
ますが、編集者はポール・エッガートです。 このデータベースでは、各大規模な集落はコードに対応しており(ノボシビルスク、たとえばアジア/ノボシビルスクはこのデータベースによって呼び出されます)、1970年から始まるすべての冒険のタイムゾーンごとのリストです。 このデータベースは多くの(すべて?)Linux / Unix / BSDシステムで使用されますが、Windows、Javaランタイム環境(たとえば、tzデータベースの更新のみに関連するいくつかの更新があります)などについては言いません。一般に、
ウィキペディアを参照してください。 このデータベースへの/からの時間変換アルゴリズムは考慮せず、準備ができていると仮定します。 実際、彼はほとんどどこでも準備ができています。
そのため、いくつかのタイムゾーンで実行されるプログラムで時間を処理するためのルールを策定します。
- プログラム内では、特定の時点でのみ機能します。
- 日付の入力/出力中にのみ、時刻を実時間に変換します。 タイムゾーンは常に(常に!)この変換に関係しているため、どのタイムゾーンを追跡する必要があることに注意してください(デフォルトでは現在のタイムゾーンが使用されるため、常に表示されるとは限りません)。
- 壁時計時間が必要なもう1つのケースは、カレンダーの変換です(翌日の始まりを計算するなど)。 ここでも、これらの変換が正しいタイムゾーンで発生することを確認する必要があります。
- 日付/時刻をデータベースに保存するときは、UTCタイムゾーンでこれを行います。
上記の最後の項目は従わないため、個別に分析します。 データベースを操作するとき(私はOracleとsqlite3の経験しかありません)、つまり、何らかの理由でデータベースの保存/読み取りを行うとき、タイムゾーンが必要です。 そしてこれは、保存/読み取り後、データを台無しにすることができることを意味します。 甘やかす方法 夏時間(+1)から冬時間(2002年10月27日02:00-03:00など)への移行に関連する不快な機能が1つあります。1時間の移行中、各壁時計の時間値は2つの時点(時間2回は02:01、02:02、02:03などを示しますが、これらは異なる時点です)。 つまり、夏時間か冬時間かはわからないため、2002年10月27日の壁時計時間02:30で何時かを明確に判断することはできません。 特定の瞬間を取得して、2002年10月27日の02:30に変換すると、逆変換を一意に実行できなくなります。
この問題のさまざまな解決策を考え出すことができます-属性L / Cを別の列に保存し、時間の瞬間をNUMBER型の列に保存しますが、日付/時刻をUTCで保存するのは最も過激で簡単なようです。 UTCタイムゾーンには夏時間がないため、時刻変換の壁時計時刻は常に明確に実行されます。 このアプローチにより、クロック転送を含むすべての瞬間をデータベースに確実に保存できることに加えて、次のこともできます。
- 規律(変換のどこかでタイムゾーンを指定するのを忘れた場合、少なくともUTCに住んでいない場合は、何かが正しくないことがすぐにわかります)。
- データベース内の情報が異なるタイムゾーンから取得される日付/時刻で混乱しないようにします-データベースでは、時刻は常にUTCです。
- 時刻をデータベースに変換したり、データベースから変換したりするとき、タイムゾーンについて考えることができないため、コードは単純化されます。これは常に同じです。
最後に、Pythonでタイムゾーンを操作する場合のいくつかの言葉。 Pythonでは、datetime.datetimeクラスを使用して日付を処理し、同じOlson tzデータベースに基づくpytzモジュールを使用してタイムゾーンを処理します。 直接的なタイムポイントはありません。代わりに、タイムゾーン対応の日時と単純な日時の2つの概念があります。 もちろん、1つ目は指定されたタイムゾーンの日付時刻であり、2つ目は純粋な形式の単純な日付時刻であり、これらの壁時計が掛かっている場所を指定しません。 日時は、「年月日時分秒マイクロ秒」構造に加えて、tz対応日時のtzinfoオブジェクトの形式で格納されます。 時間の瞬間はtime.time()を介してのみ取得でき、フロートであり、[1970、2038]のようなものに制限されます。つまり、一部の計算では簡単に十分ではありません。 つまり、(私が理解している限り、おそらく私を修正しますか?)日付時刻では、あるタイムゾーンから別のタイムゾーンに直接変換するための同じアルゴリズムのようなものが、瞬間なしで実装されますが、理論的には誰でも1から9999年。
Naiveは、次のメソッドを使用してtz対応日時に変換されます。
tzaware_datetime = some_timezone.localize(some_naive_datetime, is_dst=True)
(2番目のパラメータに注意してください。あいまいな変換のためだけに必要です)、または
another_tzaware_datetime = tzaware_datetime.astimezone(another_tz)
(tz対応の日時を別のタイムゾーンに変換します)。
これらはすべて同じdatetime.datetimeクラスとtzinfoプロパティの可用性の違いによって実装されるため、日付がタイムゾーンとそうでない場所を混同しないように気を付ける必要があります。 ここで、PythonはJavaよりも悪いです。印刷するとき、欲しい、したくない、しかし、DateFormatを作成し、タイムゾーンをPythonで指定する必要があります。 そして、印刷、素朴な日付のために行うことができます。 複雑なアプリケーションでは、すべての日付がタイムゾーンになっていることに注意することをお勧めします。アプリケーションのある時点でそれが存在しないことが判明した場合は、すでにイチジクとそこに何があるべきかがわかります。 そして、ベルトと日付が正しく比較され、印刷され、一般的になります。 さらに、データベースからの読み取り/書き込み時に単純な部分(年月日時分秒マイクロ秒)のみが保存されるため、これを操作する唯一の賢明な方法は、データベースにUTCで単純な表現を持つことです。
ボーナス
カレンダーの日付を扱う人のルール。 覚えておいてください:
- 毎年365日ではありません。
- 毎日24時間ではありません。
- 幸いなことに、1時間は60分です。
- 毎分60秒ではありません(59と61の場合があります。61秒はうるう秒と呼ばれ、6月30日または12月31日に追加されます。その時点でUTCの時計は23:59:60を示します。61秒の追加はスローダウンにより発生します。地球の回転。1秒かかる機会は、地球がより速く回転し始める場合に提供されますが、この機会は決して必要ではありませんでした)。
GMT時間は、太陽がメレディアンを横切る瞬間ではなく、このイベントの平均時間によって計算されます。 経線の実際の交点は、地球の軌道の楕円率のために最大16分まで異なります。
UTCとGMTは非常に似ていますが、まだわずかに異なります。 グリニッジの王立天文台の平均太陽時によってGMTが決定される場合、UTCは原子時計(衛星を介して同期される世界中の70の研究所の200原子時間の加重平均時間)によって測定されます。 GMTとUTCの差は0.9秒を超えてはならず、うるう秒を追加するだけで補正されます。
UNIXシステムで32の符号付きintに日付を保存すると、31ビットのオーバーフローと負の数がその後の瞬間に対応するため、すべての比較方法を破る
2038問題につながると予想されます。 新しい64ビットシステムとプログラムは、すでに64ビットを使用して時間を保存していますが、このようなシステムは2038年までに32ビットシステムを完全に置き換える時間があるでしょうか?