日期postgres之间的双精度月数
Double precision number of months between dates postgres
是否可以将两个日期之间的月数计算为双精度而不是整数?例如,2016-05-04
和 2015-03-21
之间的差异类似于 13.42
或 13.43
个月?
有很多方法可以计算类似的东西,根据您用于计算的规则,您会得到不同的结果。
以下方法为您提供了两个日期之间给定时间段内一年中的十二分之一:
select (date'2016-05-04' - date'2015-03-21') / 365.0 * 12
以上结果为 13.48。
以下方法给出了一个可能更准确的数字 (13.47),尽管要复杂得多,并且导致的差异很小:
select extract('years' from age) * 12 + extract('months' from age) + extract('days' from age) / 30
from (select age('2016-05-04'::timestamp, '2015-03-21'::timestamp)) a
对于那些对精确计算感兴趣的人,我写了下面的函数来计算两个日期之间的月差,包括小数部分:
CREATE FUNCTION
MONTH_FRACTION(
from_date DATE
, to_date DATE
)
RETURNS REAL
AS
$$
WITH
aux_1 AS ( -- Auxiliary table
SELECT
AGE(to_date, from_date) AS duration
)
, aux_2 AS ( -- Auxiliary table
SELECT
(from_date + DATE_TRUNC('MONTH', duration))::DATE AS to_date_floor
, (from_date + DATE_TRUNC('MONTH', duration + INTERVAL '1 MONTH'))::DATE AS to_date_ceil
FROM
aux_1
)
SELECT
CASE WHEN
to_date >= from_date
THEN
(12 * EXTRACT(YEAR FROM duration) + EXTRACT(MONTH FROM duration) + (to_date - to_date_floor)::REAL / (to_date_ceil - to_date_floor)::REAL)::REAL
ELSE
NULL
END
FROM
aux_1, aux_2
$$
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
是否可以将两个日期之间的月数计算为双精度而不是整数?例如,2016-05-04
和 2015-03-21
之间的差异类似于 13.42
或 13.43
个月?
有很多方法可以计算类似的东西,根据您用于计算的规则,您会得到不同的结果。
以下方法为您提供了两个日期之间给定时间段内一年中的十二分之一:
select (date'2016-05-04' - date'2015-03-21') / 365.0 * 12
以上结果为 13.48。
以下方法给出了一个可能更准确的数字 (13.47),尽管要复杂得多,并且导致的差异很小:
select extract('years' from age) * 12 + extract('months' from age) + extract('days' from age) / 30
from (select age('2016-05-04'::timestamp, '2015-03-21'::timestamp)) a
对于那些对精确计算感兴趣的人,我写了下面的函数来计算两个日期之间的月差,包括小数部分:
CREATE FUNCTION
MONTH_FRACTION(
from_date DATE
, to_date DATE
)
RETURNS REAL
AS
$$
WITH
aux_1 AS ( -- Auxiliary table
SELECT
AGE(to_date, from_date) AS duration
)
, aux_2 AS ( -- Auxiliary table
SELECT
(from_date + DATE_TRUNC('MONTH', duration))::DATE AS to_date_floor
, (from_date + DATE_TRUNC('MONTH', duration + INTERVAL '1 MONTH'))::DATE AS to_date_ceil
FROM
aux_1
)
SELECT
CASE WHEN
to_date >= from_date
THEN
(12 * EXTRACT(YEAR FROM duration) + EXTRACT(MONTH FROM duration) + (to_date - to_date_floor)::REAL / (to_date_ceil - to_date_floor)::REAL)::REAL
ELSE
NULL
END
FROM
aux_1, aux_2
$$
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;