postgresql 如何计算一个月的天数?

58wvjzkj  于 12个月前  发布在  PostgreSQL
关注(0)|答案(7)|浏览(121)

我想在Postgres中得到以下内容:

select day_in_month(2);

字符串
预期产出:

28


Postgres中有没有内置的方法可以做到这一点?

mgdq6dx1

mgdq6dx11#

SELECT  
    DATE_PART('days', 
        DATE_TRUNC('month', NOW()) 
        + '1 MONTH'::INTERVAL 
        - '1 DAY'::INTERVAL
    )

字符串
NOW()替换为任何其他日期。

pn9klfpd

pn9klfpd2#

使用聪明的“技巧”从月份的最后一个日期中提取 day 部分,作为demonstrated by Quassnoi。但它可以更简单/更快一点:

SELECT extract(days FROM date_trunc('month', now()) + interval '1 month - 1 day');

字符串

基本原理

extract是标准的SQL,所以可能更好,但它在内部解析为与date_part()相同的函数。手册:
date_part函数是在传统的Ingres上建模的,相当于SQL标准函数extract
但我们只需要添加a * 单个 * interval。Postgres允许一次使用多个时间单位。手册:
interval值可以使用以下详细语法编写:
[@]quantity unit[quantity unit...] [direction]
其中 * quantity * 是一个数字(可能签署);* unit * 为microsecondmillisecondsecondminutehourdayweekmonthyeardecadecenturymillennium,或这些单元的缩写或复数;
ISO 8601或标准SQL格式也被接受。无论哪种方式,手册再次:
interval的值在内部存储为月、日和秒。这样做是因为一个月中的天数不同,如果涉及夏令时调整,一天可以有23或25小时。月和日字段是整数,而秒字段可以存储分数。
(输出/显示取决于IntervalStyle的设置。)
上面的例子使用default Postgres formatinterval '1 month - 1 day'。这些也是有效的(虽然可读性较差):

interval '1 mon - 1 d' -- unambiguous abbreviations of time units are allowed

IS 0 8601格式

interval '0-1 -1 0:0'

标准SQL格式

interval 'P1M-1D';


都一样

yjghlzjz

yjghlzjz3#

注意,由于闰年的原因,day_in_month(2)的预期输出可能是29。您可能希望传递一个日期而不是整数。
此外,要注意夏令时:删除时区,否则某些月份的计算可能是错误的(下一个例子在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

字符串

mv1qrgav

mv1qrgav4#

SELECT
    (
        timestamp '2024-01-01' + INTERVAL '1 month'
    ) - timestamp '2024-01-01' AS days
-- 31 days

字符串
减去两个时间戳总是会产生一个以天为单位的时间间隔,我们不会得到一个以月或年为单位的答案,因为这些时间段的长度是可变的。

olqngx59

olqngx595#

这个也行。

WITH date_ AS (SELECT your_date AS d)
SELECT d + INTERVAL '1 month' - d FROM date_;

字符串
或者只是:

SELECT your_date + INTERVAL '1 month' - your_date;


这两个函数返回 interval,而不是 integer

kzipqqlq

kzipqqlq6#

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;

字符串

ippsafx7

ippsafx77#

你可以写一个函数:

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;

字符串

相关问题