如何获取一个月的天数?

问题描述 投票:0回答:7

我正在尝试在 Postgres 中获取以下内容:

select day_in_month(2);

预期输出:

28

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

postgresql datetime date-arithmetic
7个回答
52
投票
SELECT  
    DATE_PART('days', 
        DATE_TRUNC('month', NOW()) 
        + '1 MONTH'::INTERVAL 
        - '1 DAY'::INTERVAL
    )

用任何其他日期替换

NOW()


11
投票

使用智能“技巧”从该月的最后一个日期中提取day部分,如Quassnoi所示。但它可以更简单/更快一点:

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
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';

都一样。


2
投票

请注意,由于闰年,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

0
投票

这也有效。

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

或者只是:

SELECT your_date + INTERVAL '1 month' - your_date;

这两个返回间隔,而不是整数


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

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


-2
投票
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;

-3
投票

你可以写一个函数:

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;
© www.soinside.com 2019 - 2024. All rights reserved.