5 ответов:
SELECT DATE_PART('days', DATE_TRUNC('month', NOW()) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL )Заменить
NOW()на любую другую дату.
Обратите внимание, что ожидаемый выход для day_in_month(2) может быть 29 из-за високосных лет. Возможно, вы захотите передать дату вместо int.
Кроме того, остерегайтесь перехода на летнее время: удалите часовой пояс, иначе некоторые вычисления месяцев могут быть неправильными (следующий пример в CET / CEST):
SELECT DATE_TRUNC('month', '2016-03-12'::timestamptz) + '1 MONTH'::INTERVAL - DATE_TRUNC('month', '2016-03-12'::timestamptz) ; ------------------ 30 days 23:00:00 SELECT DATE_TRUNC('month', '2016-03-12'::timestamp) + '1 MONTH'::INTERVAL - DATE_TRUNC('month', '2016-03-12'::timestamp) ; ---------- 31 days
Используя умный "трюк", чтобы извлечь частьдня из последнего числа месяца, какпродемонстрировал квасной . Но это может быть немного проще / быстрее:
SELECT extract(days FROM date_trunc('month', now()) + interval '1 month - 1 day');Обоснование
extractявляется стандартным SQL, поэтому, возможно, предпочтительнее, но он разрешает ту же функцию внутренне, что иdate_part(). руководство:Функция
date_partмоделируется на традиционном языке Ingres, эквивалентном стандартной функции SQLextract:Но нам нужно только добавить A single
interval. Postgres позволяет использовать несколько единиц времени одновременно. руководство:
intervalзначения могут быть записаны с использованием следующего подробного синтаксиса:
[@]quantity unit[quantity unit...] [direction]Где
quantityэто число (возможно, подписанное);unitismicrosecond,millisecond,second,minute,hour,day,week,month,year,decade,century,millennium, либо аббревиатуры или множественное число этих единиц;ISO 8601 или стандартный формат SQL также принимаются. В любом случае, руководство снова :
Внутренние значения
intervalхранятся в виде месяцев, дней и секунд. Это делается потому, что количество дней в месяце меняется, а день может иметь 23 или 25 часов, если регулировка летнего времени является вовлеченный. Поля месяцы и дни являются целыми числами, в то время как секунды поле может хранить десятые доли.(вывод / отображение зависит от настройки
IntervalStyle.)В приведенном выше примере используется формат Postgres по умолчанию :
interval '1 month - 1 day'. Они также действительны (хотя и менее читабельны):interval '1 mon - 1 d' -- unambiguous abbreviations of time units are allowedIS0 8601 формат :
interval '0-1 -1 0:0'Стандартный формат SQL :
Все то же самое.interval 'P1M-1D';
Это тоже работает.
WITH date_ AS (SELECT your_date AS d) SELECT d + INTERVAL '1 month' - d FROM date_;Или просто:
SELECT your_date + INTERVAL '1 month' - your_date;Эти два возвращают интервал, а не целое число.
SELECT cnt_dayofmonth(2016, 2); -- 29 create or replace function cnt_dayofmonth(_year int, _month int) returns int2 as $BODY$ -- ZU 2017.09.15, returns the count of days in mounth, inputs are year and month declare datetime_start date := ('01.01.'||_year::char(4))::date; datetime_month date := ('01.'||_month||'.'||_year)::date; cnt int2; begin select extract(day from (select (datetime_month + INTERVAL '1 month -1 day'))) into cnt; return cnt; end; $BODY$ language plpgsql;
Comments