年龄(日期,日期)不一致的行为

时间:2014-04-09 17:28:43

标签: postgresql

age(date, date)功能如何运作?以下示例中的输出似乎与我不一致。

查询1:

select 
    extract(epoch from ('sept 10 2013'::timestamp - 'july 1 2013'::timestamp)),     
    extract(epoch from 'sept 10 2013'::timestamp) - extract(epoch from 'july 1 2013'::timestamp),
    extract(epoch from age('sept 10 2013', 'july 1 2013'))

输出1:

6134400 | 6134400 | 5961600

这是2天的差异:

 (6134400 - 5961600) / 60 / 60 / 24 = 2

查询2:

select 
    extract(epoch from ('sept 10 2013'::timestamp - 'sept 1 2013'::timestamp)),
    extract(epoch from 'sept 10 2013'::timestamp) - extract(epoch from 'sept 1 2013'::timestamp),
    extract(epoch from age('sept 10 2013', 'sept 1 2013'))

输出2:

777600 | 777600 | 777600

1 个答案:

答案 0 :(得分:2)

通过查看时期/时间戳而不是基础时间间隔,您会让自己感到困惑。如果我们抛弃时代,事情可能会变得更加清晰:

=> select '2013-09-10'::timestamp - '2013-07-01'::timestamp, age('2013-09-10', '2013-07-01');
 ?column? |      age      
----------+---------------
 71 days  | 2 mons 9 days

时间戳减法和age都会给你interval,但是减法只给出了几天的间隔,而age调用给你一个单独的月和日的间隔组件。如果我们将时间间隔应用于时间戳,则可以看到差异:

=> select current_timestamp + interval '71 days', current_timestamp + interval '2 mons 9 days';
           ?column?            |           ?column?            
-------------------------------+-------------------------------
 2014-06-19 11:37:59.698558-07 | 2014-06-18 11:37:59.698558-07

因为过了几个月而有一天的差异。

age docs说:

  

减去参数,产生一个"符号"使用年数和月数的结果

这正是你得到的。 timestamp subtraction docs没有明确告诉您您将获得什么样的间隔但是您确实需要几天而不是单独的年,月和日组件:

=> select '2014-09-10'::timestamp - '2013-07-01'::timestamp;
 ?column? 
----------
 436 days

age为您提供的时间间隔将涵盖时间戳减法为您提供的与时间间隔不同的时间跨度,因为并非所有月份都具有相同的天数。

extract(epoch ...)对间隔做了什么?好吧,fine manual说:

  

[...] interval值,间隔中的总秒数

这有点模棱两可。间隔中的秒数可以取决于间隔开始时间和结束时间:您可以越过DST边界,一个月中的秒数取决于您在哪个月(以及2月情况下的年份)。重看,......

extract(epoch ...)上使用interval并非如果你的间隔有月份成分非常有用,所以extract(epoch from age(...))不是一个好主意。