PostgreSQL:两个日期之间的天/月/年

gef*_*fei 75 postgresql date

我正在寻找一种在PostgreSQL中实现SQLServer函数datediff的方法.那是,

此函数返回指定的startdate和enddate之间交叉的指定datepart边界的计数(作为有符号整数值).

datediff(dd, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
datediff(mm, '2010-04-01', '2012-03-05') = 23  // 23 changes of month
datediff(yy, '2010-04-01', '2012-03-05') = 2   // 2 changes of year
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过简单地使用减法来做'dd',但是关于其他两个的任何想法?

meh*_*hdi 109

简单地减去它们:

select '2015-01-12'::date - '2015-01-01'::date;
Run Code Online (Sandbox Code Playgroud)

这会给你:

?column? 
----------
   11
Run Code Online (Sandbox Code Playgroud)

  • 问题不是关于天数,而是关于两个日期之间必须跨越的月份和年份界限的数量。提问者已经知道如何做几天了。 (3认同)
  • 是的,当您需要知道两个日期之间的天数时,此方法适用于PostgreSQL。 (2认同)
  • 再想一想,这是正确的方法.使用此方法获取两个日期之间的天数将计算月和年之间的天数,而接受的`date_part` /`age`答案将提供天数作为两个日期的天数部分的差异.`date_part('day',age('2016-9-05','2015-10-02'))`返回3. (2认同)

Igo*_*nko 96

尝试类似的东西:

select age('2010-04-01', '2012-03-05'),
       date_part('year',age('2010-04-01', '2012-03-05')),
       date_part('month',age('2010-04-01', '2012-03-05')),
       date_part('day',age('2010-04-01', '2012-03-05'));
Run Code Online (Sandbox Code Playgroud)

此功能将为您提供两个日期之间的完整年,月,日.... 对于更改日期的数量 - 我们链接,由revoua提供:http://www.sqlines.com/postgresql/how-to/datediff

  • 这不会占数月+年等.它只是进行滚动日检查 - 即`SELECT date_part('day',age('2016-10-05','2015-10-02'))`返回` 3` (26认同)
  • 由于年龄函数+1,但我认为它的参数是错误的顺序:) (8认同)
  • 这绝对不应该是答案。显然,这只是在没有进行测试的情况下就被接受了——正如其他几条评论所指出的那样,没有一个测试实际上有效。不要使用这个。 (3认同)
  • `select date_part('month',age('2010-04-01','2012-03-05'));`给`-11`.这几个月不是正确的差异 (2认同)
  • 这是不正确的。`select date_part('month',age('2010-04-01', '2012-03-05'))` 返回 -11 而不是 OP 要求的 23。您忽略了年份。 (2认同)

Web*_*rer 36

我花了一些时间寻找最好的答案,我想我有它.

这个sql会给你两个日期之间的天数integer:

SELECT
    (EXTRACT(epoch from age('2017-6-15', now())) / 86400)::int
Run Code Online (Sandbox Code Playgroud)

..which,今天运行时(2017-3-28),为我提供:

?column?
------------
77
Run Code Online (Sandbox Code Playgroud)

对接受的答案的误解:

select age('2010-04-01', '2012-03-05'),
   date_part('year',age('2010-04-01', '2012-03-05')),
   date_part('month',age('2010-04-01', '2012-03-05')),
   date_part('day',age('2010-04-01', '2012-03-05'));
Run Code Online (Sandbox Code Playgroud)

..你将获得日期字符串部分之间的字面差异,而不是两个日期之间的时间量.

IE:

Age(interval)=-1 years -11 mons -4 days;

Years(double precision)=-1;

Months(double precision)=-11;

Days(double precision)=-4;

  • 这应该是公认的答案.我建议的唯一调整是使用ceil()而不是转换为int(以整理部分天,而不是截断). (4认同)
  • 这种方法可能会被英国的夏令时绊倒——一年中会有一天只有 23 小时,而另一天有 25 小时。 (3认同)
  • 好点@Rob。读者应注意这一点。我可以认为这更像是一种偏好。我认为在我的大多数情况下,我希望将我的值截断为日期之间的字面天数,但我可以看到应该在何处使用四舍五入的天数。 (2认同)
  • 这个评论考虑了 postgres 中的相对日期——我一直想出今天和昨天的 0 天,因为它的计算方式是一整天,而不是除以 24.00 的小时;(EXTRACT(来自年龄的纪元(date_id::timestamp at time zone 'America/Los_Angeles', current_timestamp at time zone 'America/Los_Angeles') / 86400)::int ) (2认同)

Rik*_*avi 9

几乎与您需要的功能相同(基于atiruz的答案,从这里缩短版本的UDF )

CREATE OR REPLACE FUNCTION datediff(type VARCHAR, date_from DATE, date_to DATE) RETURNS INTEGER LANGUAGE plpgsql
AS
$$
DECLARE age INTERVAL;
BEGIN
    CASE type
        WHEN 'year' THEN
            RETURN date_part('year', date_to) - date_part('year', date_from);
        WHEN 'month' THEN
            age := age(date_to, date_from);
            RETURN date_part('year', age) * 12 + date_part('month', age);
        ELSE
            RETURN (date_to - date_from)::int;
    END CASE;
END;
$$;
Run Code Online (Sandbox Code Playgroud)

用法:

/* Get months count between two dates */
SELECT datediff('month', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 10 */

/* Get years count between two dates */
SELECT datediff('year', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 1 */

/* Get days count between two dates */
SELECT datediff('day', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 323 */

/* Get months count between specified and current date */
SELECT datediff('month', '2015-02-14'::date, NOW()::date);
/* Result: 47 */
Run Code Online (Sandbox Code Playgroud)

  • 答案是正确的,因为最初的问题是关于 PostgreSQL,而不是 MS SQL。 (3认同)

ati*_*ruz 6

SELECT date_part ('year', f) * 12
     + date_part ('month', f)
FROM age ('2015-06-12'::DATE, '2014-12-01'::DATE) f
Run Code Online (Sandbox Code Playgroud)

结果:6


She*_* Li 6

@WebWanderer 的答案非常接近使用 SQL Server 的 DateDiff,但不准确。这是因为使用了age()函数。

例如,“2019-07-29”和“2020-06-25”之间的天数应返回 332,但是,使用age()函数它将返回 327。因为age()返回“10 mons 27 days”并且它对待每个月为 30 天,这是不正确的。

您应该使用时间戳来获得准确的结果。例如

ceil((select extract(epoch from (current_date::timestamp - <your_date>::timestamp)) / 86400))