postgresql - requerimientos - ¿Cómo obtener el número de días en un mes?
postgresql requerimientos (6)
Esto también funciona.
WITH date_ AS (SELECT your_date AS d)
SELECT d + INTERVAL ''1 month'' - d FROM date_;
O solo:
SELECT your_date + INTERVAL ''1 month'' - your_date;
Estos dos intervalos de retorno, no enteros .
Estoy tratando de obtener lo siguiente en Postgres:
select day_in_month(2);
Rendimiento esperado:
28
¿Hay alguna forma incorporada en Postgres para hacer eso?
Puedes escribir una función:
CREATE OR REPLACE FUNCTION get_total_days_in_month(timestamp)
RETURNS decimal
IMMUTABLE
AS $$
select cast(datediff(day, date_trunc(''mon'', $1), last_day($1) + 1) as decimal)
$$ LANGUAGE sql;
Tenga en cuenta que la salida esperada para day_in_month (2) puede ser 29 debido a años bisiestos. Es posible que desee pasar una fecha en lugar de un int.
Además, tenga cuidado con el horario de verano: elimine la zona horaria o, de lo contrario, algunos cálculos de mes podrían estar equivocados (el siguiente ejemplo es 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
Usando el "truco" inteligente para extraer la parte del día de la última fecha del mes, como lo demostró Quassnoi . Pero puede ser un poco más simple / rápido:
SELECT extract(days FROM date_trunc(''month'', now()) + interval ''1 month - 1 day'');
Razón fundamental
extract
es SQL estándar, por lo que es preferible, pero se resuelve internamente en la misma función que date_part()
. El manual:
La función
date_part
se basa en el tradicional Ingres equivalente alextract
función estándar de SQL:
Pero solo tenemos que añadir un único interval
. Postgres permite múltiples unidades de tiempo a la vez. El manual:
interval
valores deinterval
se pueden escribir utilizando la siguiente sintaxis detallada:
[@]
quantity unit
[
quantity unit
...] [
direction
]
donde
quantity
es un número (posiblemente firmado);unit
esmicrosecond
,millisecond
,second
,minute
,hour
,day
,week
,month
,year
,decade
,century
,millennium
o abreviaturas o plurales de estas unidades;
ISO 8601 o el formato estándar de SQL también son aceptados. De cualquier manera, el manual de nuevo :
Los valores de
interval
interno se almacenan como meses, días y segundos. Esto se hace porque la cantidad de días en un mes varía, y un día puede tener 23 o 25 horas si se trata de un ajuste del horario de verano. Los campos de meses y días son enteros, mientras que el campo de segundos puede almacenar fracciones.
(La salida / visualización depende de la configuración de IntervalStyle
).
El ejemplo anterior utiliza el formato predeterminado de Postgres : interval ''1 month - 1 day''
. Estos también son válidos (aunque menos legibles):
interval ''1 mon - 1 d'' -- unambiguous abbreviations of time units are allowed
Formato IS0 8601 :
interval ''0-1 -1 0:0''
Formato SQL estándar :
interval ''P1M-1D'';
Todos iguales.
SELECT
DATE_PART(''days'',
DATE_TRUNC(''month'', NOW())
+ ''1 MONTH''::INTERVAL
- ''1 DAY''::INTERVAL
)
Sustituye NOW()
con cualquier otra fecha.
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;