我试图在 Postgres 中获得以下内容:
select day_in_month(2);
预期输出:
28
Postgres 中是否有任何内置方法可以做到这一点?
我试图在 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 标准函数的传统 Ingres 为模型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
值存储为月、日和秒。这样做是因为一个月中的天数不同,如果涉及夏令时调整,一天可以有 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';
都一样。
请注意,由于闰年,day_in_month(2) 的预期输出可能为 29。您可能想要传递日期而不是 int。
另外,请注意夏令时:删除时区,否则某些月份计算可能是错误的(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;