我有从20161到201640的所有周数。我想知道第31周的开始日期和结束日期。
我怎么能写查询在postgresql得到的?
要获得开始日期,只需使用to_date()
如果您使用的是ISO星期数,请使用:
select to_date('201643', 'iyyyiw');
否则使用:
select to_date('201643', 'yyyyww');
只需在结果日期上加上6天就可以得到一周的结束日期:to_date('201643', 'iyyyiw') + 6
SELECT date '2016-01-01' + interval '1 day' * ((7 - EXTRACT(DOW FROM DATE '2016-01-01')) + 29*7) AS start_date,
date '2016-01-01' + interval '1 day' * ((7 - EXTRACT(DOW FROM DATE '2016-01-01')) + 29*7 + 6) AS end_date,
如果你允许一年的第一周和最后一周少于7天,那么处理周可能会很棘手。
这是我使用ISO周(第一天是星期一,dow = 1)的两美分。它们返回一年中一周的第一个和最后一个日期以及周索引。
注意一年有365/7 = 52,142857142857143周,或366/7 = 52,285714285714286周,取决于它的长度。因此,周的范围总是在[0,52]内。我不得不在第52周使用if
,因为它不能计算为7-d
。
create or replace function first_date_of_isoweek(y int, w int)
returns date
language sql as $$
select to_date(concat(y, to_char(w, 'fm00')), 'iyyyiw');
$$;
create or replace function last_date_of_isoweek(y int, w int)
returns date
language plpgsql as $$
declare
d1 date;
d2 date;
d smallint;
begin
-- Calculate first date of an isoweek
d1 = to_date(concat(y, to_char(w, 'fm00')), 'iyyyiw');
-- Year's last week needs an speacial treatment
if w = 52 then
return to_date(concat(y, '1231'), 'yyyyMMdd');
else
-- Calculate the dow of the first date
d = extract(isodow from d1);
-- Calculate the last date out of the first date
return d1 + interval '1 day' * (7-d);
end if;
end $$;
2021测试如下:
select first_date_of_isoweek(2021, 0);
first_date_of_isoweek|
---------------------+
2021-01-01|
select last_date_of_isoweek(2021, 0);
last_date_of_isoweek|
--------------------+
2021-01-03|
select first_date_of_isoweek(2021, 1);
first_date_of_isoweek|
---------------------+
2021-01-04|
select last_date_of_isoweek(2021, 1);
last_date_of_isoweek|
--------------------+
2021-01-10|
select first_date_of_isoweek(2021, 52);
first_date_of_isoweek|
---------------------+
2021-12-27|
select last_date_of_isoweek(2021, 52);
last_date_of_isoweek|
--------------------+
2021-12-31|