時間範囲を表すテーブルがあります。
_ 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つの解決策が考えられます。
00:00:00
_の代わりに、真夜中は_'00:00:00'::time without time zone - interval '1 microsecond'
_を使用します。このすべてが誤った計算を引き起こす可能性は、おそらく決して起こらないほど十分に低いです。そして、たとえそれが年に数回発生したとしても、少なくとも私のシステムでは、その影響は本質的に存在しません。ただし、これは醜い解決策であり、このような誤ったデータを使用すると、将来的に他の結果が生じる可能性があります。select from my_table where localtime >= start_time and (localtime < end_time or end_time == '00:00:00')
。これは簡単なようですが、1つ以上の特別なインデックスを作成する必要があります。それが唯一の解決策である場合は問題ありませんが、可能であれば回避する価値のある欠点のように感じます。これについて他に方法はありますか?この計算に対応するある種の特別な日時関数ですか?データを表現するより良い方法は?
これについて他に方法はありますか?この計算に対応するある種の特別な日時関数ですか?データを表現するより良い方法は?
'24:00:00'::time
の何が問題になっていますか?
24:00:00
は00:00:00
翌日(PostgreSQLの場合)に変換されるため、2018-03-07 24:00:00
は2018-03-08 00:00:00
と同じです。
23:59:59.999
は現在の日付に属していると考えることもできます。 00:00:00.000
は、ある日から次の日への移行と見なされます。説明させてください...
参照:真夜中 (Wikepedia)
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 s
を2018-03-07 23:59:59.999
に追加するときに日付を切り替えます。
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.
を追加することを決定します。
ミリ秒をtimestamp
値に追加します。
postgres=# select TIMESTAMP '2018-03-07 23:59:59.999' + interval '1 ms';
2018-03-08 00:00:00
ミリ秒を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
を真夜中(翌日以降)の時間として決定します。
日付と時刻を併用しない場合は、00:00:00.000
(または23:59:59.999
)の翌日の真夜中の表記として11:59:59.999 p.m.
を使用しないでください。これはソリューション番号1に対応します。
日付と時刻を一緒に使用している場合は、2018-03-07 11:59:59.999
または2018-03-07 11:59:59.999 p.m.
にマイクロ秒を追加するときにRDBMSがサポートする表記を確認してください。