Как узнать количество дней в месяце?



Я пытаюсь получить следующее в Postgres:



select day_in_month(2);


Ожидаемый результат:



28


Есть ли в Postgres какой-либо встроенный способ сделать это?
1701   5  

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, эквивалентном стандартной функции SQL extract:

Но нам нужно только добавить A single interval. Postgres позволяет использовать несколько единиц времени одновременно. руководство:

interval значения могут быть записаны с использованием следующего подробного синтаксиса:

[@]quantity unit[quantity unit...] [direction]

Где quantity это число (возможно, подписанное); unit is microsecond, 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 allowed

IS0 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

    Ничего не найдено.