Подсчитать месяцы между двумя временными метками на postgresql?

Я хочу подсчитать количество месяцев между двумя датами.

Выполнение:

SELECT TIMESTAMP '2012-06-13 10:38:40' - TIMESTAMP '2011-04-30 14:38:40';

Возврат: 0 лет 0 монов 409 дней 20 часов 0 мин 0.00 сек.

и так:

SELECT extract(month from TIMESTAMP '2012-06-13 10:38:40' - TIMESTAMP '2011-04-30 14:38:40');

возвращает 0.

Ответ 1

age(timestamp1, timestamp2) => returns interval

мы пытаемся извлечь из месяца и месяца из интервала и добавить их соответственно.

выберите экстракт (год из возраст (timestamp1, timestamp2)) * 12 + экстракт (месяц из возраст (timestamp1, timestamp2))

Ответ 2

age функция дает обоснованный интервал для работы с:

SELECT age(TIMESTAMP '2012-06-13 10:38:40', TIMESTAMP '2011-04-30 14:38:40');

возвращается 1 year 1 mon 12 days 20:00:00, и с этим вы можете легко использовать EXTRACT чтобы подсчитать количество месяцев:

SELECT EXTRACT(YEAR FROM age) * 12 + EXTRACT(MONTH FROM age) AS months_between
FROM age(TIMESTAMP '2012-06-13 10:38:40', TIMESTAMP '2011-04-30 14:38:40') AS t(age);

Ответ 3

Если вы сделаете это несколько раз, вы можете определить следующую функцию:

CREATE FUNCTION months_between (t_start timestamp, t_end timestamp)
    RETURNS integer
    AS $$
        SELECT
            (
                12 * extract('years' from a.i) + extract('months' from a.i)
            )::integer
        from (
            values (justify_interval($2 - $1))
        ) as a (i)
    $$
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT;

так что вы можете тогда просто

SELECT months_between('2015-01-01', now());

Ответ 4

Дает разницу между месяцами двух дат

   SELECT ((extract( year FROM TIMESTAMP '2012-06-13 10:38:40' ) - extract( year FROM TIMESTAMP '2011-04-30 14:38:40' )) *12) + extract(MONTH FROM TIMESTAMP '2012-06-13 10:38:40' ) - extract(MONTH FROM TIMESTAMP '2011-04-30 14:38:40' );

Результат: 14

Приходится извлекать месяцы отдельно для обеих дат, а затем разницу обоих результатов

Ответ 5

SELECT date_part ('year', f) * 12
      + date_part ('month', f)
FROM age ('2015-06-12', '2014-12-01') f

Результат: 6 месяцев

Ответ 6

У меня была такая же проблема когда-то, и я написал это... это довольно уродливо:

postgres=>  SELECT floor((extract(EPOCH FROM TIMESTAMP '2012-06-13 10:38:40' ) - extract(EPOCH FROM TIMESTAMP '2005-04-30 14:38:40' ))/30.43/24/3600);
 floor 
-------
    85
(1 row)

В этом решении "один месяц" определяется как 30,43 дня, поэтому он может дать некоторые неожиданные результаты в более короткие периоды времени.

Ответ 7

Попробуйте это решение:

SELECT extract (MONTH FROM age('2014-03-03 00:00:00'::timestamp, 
'2013-02-03 00:00:00'::timestamp)) + 12 * extract (YEAR FROM age('2014-03-03   
00:00:00'::timestamp, '2013-02-03 00:00:00'::timestamp)) as age_in_month;

Ответ 8

SELECT floor(extract(days from TIMESTAMP '2012-06-13 10:38:40' - TIMESTAMP
'2011-04-30 14:38:40')/30.43)::integer as months;

Дает приблизительное значение, но позволяет избежать дублирования временных меток. Это использует подсказку из ответа tobixen, чтобы разделить на 30.43 вместо 30, чтобы быть менее неправильным для длинных временных интервалов во время вычисления месяцев.

Ответ 9

Пытаться;

select extract(month from  age('2012-06-13 10:38:40'::timestamp, '2011-04-30 14:38:40'::timestamp)) as my_months;