Postgresql

我應該如何表示午夜結束時間?

  • March 7, 2018

我有一個代表時間範圍的表格。

  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。

我能想到兩種解決方案。

  1. 而不是00:00:00,'00:00:00'::time without time zone - interval '1 microsecond'用於午夜。這每一個導致錯誤計算的可能性可能低到永遠不會發生。即使它確實每年發生幾次,後果基本上不存在,至少就我現在的系統而言。然而,這是一個醜陋的解決方案,使用這樣的錯誤數據可能會產生其他後果。
  2. select from my_table where localtime &gt;= start_time and (localtime &lt; end_time or end_time == '00:00:00'). 這看起來很簡單,但是有必要創建一個或多個特殊索引。如果它是唯一的解決方案,這不是問題,但如果可能的話,感覺像是一個值得避免的缺點。

還有其他方法可以解決這個問題嗎?某種特殊的日期時間函式可以適應這種計算?表示數據的更好方法?

社區維基回答

還有其他方法可以解決這個問題嗎?某種特殊的日期時間函式可以適應這種計算?表示數據的更好方法?

有什麼問題'24:00:00'::time

24:00:00轉換為00:00:00 第二天(在 PostgreSQL 中),因此2018-03-07 24:00:002018-03-08 00:00:00.

介紹

您可能要考慮23:59:59.999屬於當天。00:00:00.000被認為是從一天到下一天的過渡。讓我解釋…

參考: 午夜(維基百科)。


24 小時制

根據您使用的是 24 小時表示法還是 12 小時上午/下午表示法,以下資訊可能同樣有趣。

中午/午餐

中午不是 24 小時制的問題,因為從11:59:59.99912:00:00.000的步長12:00:00.001對時間格式沒有影響。

午夜

看看午夜前後的時間,你會發現那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.999PM 12:00:00.000。Midday 實際上應該m在靜態時添加一個,看到它a.m.被定義為ante-meridiem轉換為正午之前,而p.m.post -merdiem轉換為正午之後

午夜

這對於午夜前後的 12 小時表示法同樣有效。11:59:59.999 p.m已接近午夜。12:00:00.001 a.m.就在午夜過後。12:00:00 a.m./p.m.是午夜,正好是中午之後的 12 小時或新的中午之前。

但是,大多數係統決定a.m.在時鐘到達午夜 12 點時添加一個。


例子

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之後的午夜的表示法。這與您的解決方案編號 1 相對應。23:59:59.999``11:59:59.999 p.m.
  2. 如果您將日期與時間一起使用,那麼在將微秒添加到2018-03-07 11:59:59.9992018-03-07 11:59:59.999 p.m.

完整參考列表

引用自:https://dba.stackexchange.com/questions/199564