48

データベースにイベントを保存しています。「開始」と「終了」の日時、「tickets_start」と「tickets_end」があります (実際のイベントの開始/終了ではなく、チケットの販売が実際に開始/終了したとき)。

これまでのところ、保存する前に日付/時刻を GMT に変換してから、それぞれのタイムゾーンに戻して表示するなど、すべての楽しいことを行うメソッドを作成しました。

「America/New_York」のような値を持つ varchar フィールドにタイムゾーンを保存しています。

しかし、ユーザーがイベントの繰り返しを許可したい場合は、対処を開始する必要があります。以前にやったことがありますが、それほど大したことではありませんが、複数のタイムゾーンにまたがることはありません.

最初は大したことではないと思っていましたが、最初の開始日が (例として) 7 月で、1 年間毎月繰り返される場合、ある時点でサマータイムが開始されることに気付きました。 GMT からの変換では時刻が異なるように変更されます。ある月、12:00 を変換すると -5 に変更され、次の月には DST のために -4 に変更されます。

私の現在の考えでは、DST 中に開始日/終了日が入力されたかどうかを示す「dst」 tinyint(1) を保存し、必要に応じて時間を 1 時間変更するメソッドを作成します。

しかし、おそらくこれには「通常」があるか、私が考えていない簡単なことがあるのではないかと期待して、ここで尋ねたいと思いました.

(cakephp 2.4.x)

4

1 に答える 1

135

まず、現代の用語では GMT ではなく UTC を使用する必要があることを認識してください。UTCがより正確に定義されていることを除いて、それらはほとんど同等です。GMT という用語は、オフセット UTC+0 を持つ冬の月に有効な英国のタイム ゾーンの部分を指すために予約してください。

今あなたの質問に。UTC は、すべての日付と時刻の値を格納するための最適な方法であるとは限りません。過去のイベントや将来の絶対的なイベントでは特にうまく機能しますが、将来のローカルイベント、特に将来の定期的なイベントではうまく機能しません。

最近別の回答でこれについて書きましたが、これは現地時間が UTC よりも理にかなっている数少ない例外ケースの 1 つです。主な議論は「目覚まし時計の問題」です。UTC で目覚まし時計を設定すると、DST 移行の日に 1 時間早くまたは遅く起きます。これが、ほとんどの人が目覚まし時計を現地時間で設定する理由です。

もちろん、世界中のデータを扱う場合は、ローカル タイムだけを保存することはできません。いくつかの異なるものを保存する必要があります。

  • 「08:00」などの定期的なイベントの現地時間
  • "America/New_York" など、現地時間を表すタイム ゾーン
  • 毎日、隔週、または月の第 3 木曜日など、アプリケーションに適した形式の繰り返しパターン。
  • 射影できる限りにおいて、次の直近のUTC の日付と時刻に相当します。
  • おそらく、常にではありませんが、将来のイベント UTC の日付と時刻のリストは、事前に定義された将来の期間 (ニーズに応じて、おそらく 1 週間、おそらく 6 か月、おそらく 1 年または 2 年) を予測します。

最後の 2 つについては、そのタイム ゾーンを担当する政府が何かを変更することを決定した場合、現地の日付/時刻に相当する UTC が変更される可能性があることを理解してください。毎年複数のタイム ゾーン データベースの更新があるため、更新のアナウンスを購読し、タイム ゾーン データベースを定期的に更新する計画を立てることをお勧めします。タイムゾーン データを更新するたびに、将来のすべてのイベントの UTC 相当時間を再計算する必要があります。

複数のタイム ゾーンにまたがるイベントのリストを表示する予定がある場合は、UTC に相当するものを用意することが重要です。これらは、そのリストを作成するために照会する値です。

考慮すべきもう 1 つの点は、イベントが DST フォールバック移行中に発生する現地時間にスケジュールされている場合、そのイベントが最初のインスタンス (通常) で発生するか、2 番目のインスタンス (場合によって) で発生するかを決定する必要があることです。またはその両方 (まれに) を作成し、必要な場合を除き、イベントが 2 回発生しないようにするメカニズムをアプリケーションに組み込みます。

簡単な答えを探していた場合は、申し訳ありませんが、答えはありません。タイム ゾーンを越えて将来のイベントをスケジュールするのは複雑な作業です。

代替アプローチ

スケジューリングに UTC 時間を使用する手法を何人かの人に教えてもらいました。つまり、開始日を現地時間で選択し、それを UTC に変換して保存し、タイム ゾーン ID も保存します。次に、実行時に、タイム ゾーンを適用して元の UTC 時間を現地時間に変換し、その現地時間を使用して、最初に上記のように保存されたものであるかのように、他の繰り返しを計算します。

この手法は機能しますが、欠点は次のとおりです。

  • 最初のインスタンスが実行される前に現地時間を変更するタイム ゾーンの更新がある場合、スケジュール全体が無効になります。これは、2 番目のインスタンスが実際には最初のインスタンスになるように、「最初の」インスタンスに過去の時間を選択することで軽減できます。

  • 時間が実際にユーザーを追跡する「浮動時間」である場合 (携帯電話の目覚まし時計など)、最初に作成されたゾーンのタイム ゾーン情報を保存する必要があります。それはあなたが走りたいゾーンではありません。

  • 何のメリットもなく、複雑さが増します。この手法は、タイム ゾーンのサポートを後付けしようとしている UTC のみのスケジューラを使用している可能性がある状況のために取っておきます。

于 2013-10-28T04:47:39.083 に答える