web-dev-qa-db-ja.com

真夜中の終了時間を表すにはどうすればよいですか?

時間範囲を表すテーブルがあります。

_   Column    |            Type             |                                Modifiers                                 
-------------+-----------------------------+--------------------------------------------------------------------------
 id          | bigint                      | not null default nextval('exploded_recurring_sessions_id_seq'::regclass)
 schedule_id | bigint                      | 
 start_time  | time without time zone      | 
 end_time    | time without time zone      | 
_

次に、次のようなクエリを実行します。

_select from my_table where localtime >= start_time and localtime < end_time;
_

ここでのビジネスロジックは、end_timeが真夜中の場合に意味があります。これは、範囲にはstart_timeが含まれ、end_timeは含まれないと考えているためです。

もちろん、end_timeが00:00:00の場合、localtimeが<end_timeになることはないため、このクエリは実際には機能しません。

これには2つの解決策が考えられます。

  1. _00:00:00_の代わりに、真夜中は_'00:00:00'::time without time zone - interval '1 microsecond'_を使用します。このすべてが誤った計算を引き起こす可能性は、おそらく決して起こらないほど十分に低いです。そして、たとえそれが年に数回発生したとしても、少なくとも私のシステムでは、その影響は本質的に存在しません。ただし、これは醜い解決策であり、このような誤ったデータを使用すると、将来的に他の結果が生じる可能性があります。
  2. select from my_table where localtime >= start_time and (localtime < end_time or end_time == '00:00:00')。これは簡単なようですが、1つ以上の特別なインデックスを作成する必要があります。それが唯一の解決策である場合は問題ありませんが、可能であれば回避する価値のある欠点のように感じます。

これについて他に方法はありますか?この計算に対応するある種の特別な日時関数ですか?データを表現するより良い方法は?

3
John Bachir

コミュニティwikiの回答

これについて他に方法はありますか?この計算に対応するある種の特別な日時関数ですか?データを表現するより良い方法は?

'24:00:00'::timeの何が問題になっていますか?

24:00:0000:00:00翌日(PostgreSQLの場合)に変換されるため、2018-03-07 24:00:002018-03-08 00:00:00と同じです。

1
user126897

前書き

23:59:59.999は現在の日付に属していると考えることもできます。 00:00:00.000は、ある日から次の日への移行と見なされます。説明させてください...

参照:真夜中 (Wikepedia)


24時間表記

24時間表記または12時間am/pm表記のどちらを使用しているかに応じて、以下の情報のビットも同様に興味深いかもしれません。

正午/昼食

11:59:59.999から12:00:00.000以降、12:00:00.001までのステップは時間形式に影響しないため、正午は24時間表記では問題になりません。

真夜中

真夜中の時間を見ると、23:59:59.999はまだ同じ日ですが、00:00:00.001は翌日に属していることがわかります。このロジックに従って、静的値00:00:00.000はどちらの日に属していてはなりません。それが移行のポイントです。

ただし、一部のRDBMSシステムは、0.001 s2018-03-07 23:59:59.999に追加するときに日付を切り替えます。


12時間表記

正午/昼食

12時間表記の正午は、時計がamでもpmでもないクロックが11:59:59.999から12:00:00.000にジャンプするとすぐにPM=が追加される傾向があります。正午には、静的な場合、単一のmが追加されます。 a.m.ante-meridiemとして定義されていることを確認すると、before middayに変換され、p.m.post-merdiemに変換されます。 =は正午以降に変換されます。

真夜中

これは、真夜中の12時間表記にも同様に有効です。 11:59:59.999 p.mは深夜0時です。 12:00:00.001 a.m.は真夜中過ぎです。 12:00:00 a.m./p.m.は午前0時で、正午からちょうど12時間後または新しい正午より前です。

ただし、ほとんどのシステムは、時計が真夜中の12時に到達するとすぐにa.m.を追加することを決定します。


PostgreSQL

ミリ秒をtimestamp値に追加します。

入力:

postgres=# select TIMESTAMP '2018-03-07 23:59:59.999' + interval '1 ms';

出力:

 2018-03-08 00:00:00

SQLサーバー

ミリ秒をdatetime値に追加します。

入力:

select dateadd(ms,001,cast('2018-03-07 23:59:59.999' as datetime))

出力:

2018-03-08 00:00:00.000

推奨事項

例を見るとわかるように、テストされた両方のRDBMSシステムは、00:00:00.000を真夜中(翌日以降)の時間として決定します。

  1. 日付と時刻を併用しない場合は、00:00:00.000(または23:59:59.999)の翌日の真夜中の表記として11:59:59.999 p.m.を使用しないでください。これはソリューション番号1に対応します。

  2. 日付と時刻を一緒に使用している場合は、2018-03-07 11:59:59.999または2018-03-07 11:59:59.999 p.m.にマイクロ秒を追加するときにRDBMSがサポートする表記を確認してください。


完全な参照リスト

5