我应该如何表示午夜结束时间?

Joh*_*hir 3 postgresql datetime time

我有一个代表时间范围的表格。

   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      | 
Run Code Online (Sandbox Code Playgroud)

然后我会做一个这样的查询:

select from my_table where localtime >= start_time and localtime < end_time;
Run Code Online (Sandbox Code Playgroud)

在 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 >= start_time and (localtime < end_time or end_time == '00:00:00'). 这看起来很简单,但需要创建一个或多个特殊索引。如果这是唯一的解决方案,那不是问题,但如果可能的话,感觉像是一个值得避免的缺点。

有没有其他方法可以解决这个问题?某种特殊的日期时间函数可以适应这种计算?表示数据的更好方法?

Joh*_* N. 5

介绍

您可能要考虑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.999到 时立即添加 PM 12:00:00.000。中午实际上应该m在静态时添加一个单一的,看到它a.m.被定义为ante-merdiem,它转换为正午之前,而p.m.这是后午后转换为正午之后

午夜

这对于午夜前后的 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';
Run Code Online (Sandbox Code Playgroud)

输出:

 2018-03-08 00:00:00
Run Code Online (Sandbox Code Playgroud)

数据库服务器

datetime值添加毫秒。

输入:

select dateadd(ms,001,cast('2018-03-07 23:59:59.999' as datetime))
Run Code Online (Sandbox Code Playgroud)

输出:

2018-03-08 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

建议

正如您在示例中看到的那样,两个经过测试的 RDBMS 系统都确定00:00:00.000是午夜时间(之后或回旋处),但在第二天。

  1. 如果您不将日期与时间一起使用,请避免将其00:00:00.000用作同一天之后23:59:59.999(或11:59:59.999 p.m.)午夜的表示法。这对应于您的解决方案编号 1。

  2. 如果您使用的日期与时代一起,然后找出你的符号RDBMS支持加时一微秒要么2018-03-07 11:59:59.9992018-03-07 11:59:59.999 p.m.


完整参考列表