我正在尝试在Postgres中获取以下内容:
select day_in_month(2);
预期产出:
28
Postgres中是否有任何内置方法可以做到这一点?
SELECT
DATE_PART('days',
DATE_TRUNC('month', NOW())
+ '1 MONTH'::INTERVAL
- '1 DAY'::INTERVAL
)
将NOW()
替换为任何其他日期。
使用智能"技巧"从该月的最后一个日期中提取日期部分,如Quassnoi所示。但它可以更简单/更快一些:
SELECT extract(days FROM date_trunc('month', now()) + interval '1 month - 1 day');
理由
extract
是标准的SQL,所以也许更可取,但它在内部解析为与date_part()
相同的功能。手册:
date_part
函数以传统的安格尔为模型,相当于SQL标准函数extract
:
但是我们只需要添加一个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
值存储为月、日和秒。这样做是因为一个月中的天数不同,而一天如果夏令时调整为涉及。月份和天数字段是整数,而秒字段可以存储分数。
(输出/显示取决于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';
都一样。
请注意,由于闰年,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
这也行得通。
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;
你可以编写一个函数:
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;