我想在Postgres中获得以下内容:
select day_in_month(2);
预期产出:
28
Postgres有没有内置的方法来做到这一点?
答案 0 :(得分:33)
SELECT
DATE_PART('days',
DATE_TRUNC('month', NOW())
+ '1 MONTH'::INTERVAL
- '1 DAY'::INTERVAL
)
将NOW()
替换为任何其他日期。
答案 1 :(得分:2)
使用智能"技巧"从月份的最后一天开始提取天部分,为demonstrated by Quassnoi。但它可以更简单/更快:
SELECT extract(days FROM date_trunc('month', now()) + interval '1 month - 1 day');
extract
是标准SQL,因此可能更好,但它在内部解析为与date_part()
相同的函数。 The manual:
date_part
函数模仿传统的Ingres,相当于SQL标准函数extract
:
但我们只需添加 a 单 interval
。 Postgres允许一次使用多个时间单位。 The manual:
可以使用以下详细语法编写
interval
个值:
[@]
quantity unit
[
quantity unit
...] [
direction
]
其中
quantity
是一个数字(可能已签名);unit
是microsecond
,millisecond
,second
,minute
,hour
,day
,week
,month
,year
,{{ 1}},decade
,century
或这些单位的缩写或复数形式;
ISO 8601 or standard SQL format也被接受。无论哪种方式,the manual again:
内部
millennium
值存储为月,日和秒。 这样做是因为一个月中的天数变化,一天变化 如果夏令时调整,可以有23或25小时 参与其中。月份和日期字段是整数,而秒数 字段可以存储分数。
(输出/显示取决于setting of IntervalStyle
。)
以上示例使用默认Postgres格式:interval
。这些也是有效的(虽然可读性较差):
interval '1 month - 1 day'
IS0 8601格式:
interval '1 mon - 1 d' -- unambiguous abbreviations of time units are allowed
标准SQL格式:
interval '0-1 -1 0:0'
都一样。
答案 2 :(得分:1)
请注意,由于闰年,day_in_month(2)的预期输出可能是29。您可能希望传递日期而不是int。
另外,请注意夏令时:删除时区或者某些monthes计算可能是错误的(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
答案 3 :(得分: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;
这两个返回 interval ,而不是整数。
答案 4 :(得分:0)
您可以编写一个函数:
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;
答案 5 :(得分:-1)
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;