web-dev-qa-db-ja.com

夏時間を考慮して繰り返し日付を保存する方法

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

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

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

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

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

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

しかし、私はここに尋ねると考えました。多分これには「普通の」または私が考えていない簡単なものがあるのではないかと期待しています。

(cakephp 2.4.x)

39
Dave

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

さてあなたの質問に。 UTCは、必ずしもすべての日付と時刻の値を格納するための最良の方法ではありません。 過去イベント、または将来の絶対イベントで特にうまく機能します、しかし、それは将来のlocalイベントにはそれほどうまく機能しません-特に将来recurringイベント。

私はこれについて書きました 別の答えで 最近、現地時間が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回発生しないようにします。

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

代替アプローチ

私は数人に、doがスケジュールにUTC時間を使用するテクニックを見せてくれました。つまり、現地時間で開始日を選択します。これをUTCに変換して保存し、タイムゾーンIDも保存します。次に、実行時に、タイムゾーンを適用して元のUTC時刻を現地時間に変換し、その現地時間を使用して、上記のように最初に格納されたものと同じように他の繰り返しを計算します。

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

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

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

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

112