【问题标题】:Error calculating the number of days between two dates in PostgreSQL在 PostgreSQL 中计算两个日期之间的天数时出错
【发布时间】:2026-02-12 11:35:02
【问题描述】:

我正在使用date_part PostgreSQL 函数来计算两个日期之间经过的(包括)天数。

select date_part('day', '2019-12-31 00:00:00'::timestamp - '2019-1-1 00:00:00'::timestamp);

在 DBeaver 中运行此查询返回比预期少 1 天:

date_part|
---------+
    364.0|

这就像在结果中添加+1 一样简单,但是下面的句子将返回1 天,这显然是错误的:

select 1 + date_part('day', '2019-1-1 00:00:00'::timestamp - '2019-1-1 00:00:00'::timestamp);

?column?|
--------+
     1.0|

有没有更好的方法来获得可信的解决方案?

【问题讨论】:

    标签: postgresql sql-date-functions


    【解决方案1】:

    如果您想包含两个日期边界,添加+ 1 实际上是正确的做法。根据您自己的定义,“2019-1-1”和“2019-1-1”之间有一天

    由于您说的是日期,而不是时间戳,因此有一种更简单的方法:

    SELECT date '2019-12-31' - date '2019-1-1' + 1;
    
     ?column? 
    ----------
          365
    

    减去日期返回integer
    如果您的输入是timestamp 值,只需转换为日期即可截断时间部分:

    SELECT ts1::date - ts2::date + 1;
    

    【讨论】:

    • 谢谢@Erwin。你是对的,一如既往! :-) 我在要求两个相同日期的差异为 0 时不一致。
    【解决方案2】:

    你可能是说

    select date_part('day', '2020-01-01 00:00:00'::timestamp - '2019-1-1 00:00:00'::timestamp);
    

    因为这是绝对正确的,即在 12 月 31 日 00:00:00 - 12 月 30 日 23:59:59 之后 - 仅过去了 364 天。

    【讨论】:

    • 是的,我看到即使剩下 1 秒也足以在 select date_part('day', '2019-1-31 23:59:59'::timestamp - '2019-1-1 00:00:00'::timestamp); 中得到错误的 30 天值
    • 使用日期也无济于事:select '2019-12-31'::date - '2019-1-1 00:00:00'::date; 364 因为我很确定日期会转换为午夜的时间戳。
    • 我想,投射到日期意味着将时间设置为“00:00:00”。
    • 我也找到了这句话,但是对于正常的年份也呈现364天select date '2019-12-31' - date '2019-1-1';
    • 再次:这其实是 364天,第365天 - 2019-12-31 - 不在那个范围内
    【解决方案3】:

    绕道:

    select 
       count(*) AS days 
    from 
       generate_series('2019-1-1 00:00:00'::timestamp, 
                       '2019-12-31 00:00:00'::timestamp, '1 day');
     days 
    ------
      365
    
    

    【讨论】:

    • 很好的尝试阿德里安,但对于两个相同的日期或两个相近的日期都失败了。检查select count(*) AS days from generate_series('2019-1-1 00:00:00'::timestamp, '2019-1-1 00:00:00'::timestamp, '1 day');
    • 我假设条件 if 对于两个相同的日期可能是不可避免的。
    • 基本上这个想法是计算两个日期的doy(一年中的一天)并取这两个整数之间的差。如果您打算有一个包容性的解决方案,您应该在该差异上添加 +1,但是当两个相同日期的情况无法呈现 1 时。您可能需要在 plpgsql 中使用 where 子句或 if 子句的条件
    • 抱歉,我指的是when,而不是where