如何从leap年或正常年份获得一致的周数

时间:2018-06-24 07:14:12

标签: sql postgresql

使用PostgreSQL 9.4.18版,PostGIS 2.2版 我正在使用此功能,并且正在使用WW,因为不需要ISO周数...仅从1月1日开始的周数:

CREATE FUNCTION f_woy(timestamp with time zone) RETURNS int LANGUAGE sql
IMMUTABLE AS $$SELECT to_char($1, 'WW')::int$$; 

当我运行以下查询时,每隔4年,星期数就会更改为a年。我试图在某个日期每年都获得一致的周数。例如,当我跑步时

SELECT f_woy(('2007-06-24 14:19:46.502-07'::timestamp at time zone 'UTC' at 
time zone 'america/los_angeles')::date) 

在2004年,2005年,2006年和2007年,我得到了:

woy integer
25

但是当我以以下方式运行它时:

SELECT f_woy(('2008-06-24 14:19:46.502-07'::timestamp at time zone 'UTC' at 
time zone 'america/los_angeles')::date) 

我知道

woy integer
26

有没有一种方法可以忽略the年,并使所有内容保持一致,因此所有06-24都将是第25周。我看到了一些有关确定是否为a年的帖子,但我有很难集成该逻辑,以便将其应用于检查周数的所有查询。

1 个答案:

答案 0 :(得分:1)

您可以使用CASE WHEN表达式来检查今年是不是<>> le年

  1. 今年是 le年返回结果减1.。
  2. 今年不是 le年返回结果。

判断leap年公式为

  

(年%4 = 0)和(年%100 <> 0)或(年%400 = 0)

CASE WHEN条件下添加此公式即可

看起来像这样。

CREATE FUNCTION f_woy(timestamp with time zone) 
RETURNS int AS $$  
SELECT CASE WHEN (date_part('year',$1)::int % 4 = 0) AND ((date_part('year',$1)::int % 100 <> 0) OR (date_part('year',$1)::int % 400 = 0)) 
         THEN to_char($1, 'WW')::int -1 
       ELSE to_char($1, 'WW')::int
END
$$ LANGUAGE sql IMMUTABLE STRICT; 

使用f_woy功能时,of年的星期与正常年份的星期相同。

SELECT f_woy(('2007-06-24 14:19:46.502-07'::timestamp at time zone 'UTC' at 
time zone 'america/los_angeles')::date), 
       f_woy(('2008-06-24 14:19:46.502-07'::timestamp at time zone 'UTC' at 
time zone 'america/los_angeles')::date) 

结果

f_woy   f_woy
25      25

sqlfiddle:https://dbfiddle.uk/?rdbms=postgres_9.6&fiddle=b43eb6f9c2accde5fc74ebe980a039d7

编辑

Le年意味着今年将添加2月29日,因此您可以尝试使用它。

IsLeapYear函数将今年定为leap年或不是leap年。

create or replace function IsLeapYear(int)
returns boolean as $$
    select $1 % 4 = 0 and ($1 % 100 <> 0 or $1 % 400 = 0)
$$ LANGUAGE sql IMMUTABLE STRICT; 

f_woy函数获取当前星期数。

create or replace function f_woy(date)
returns int language plpgsql as $$
declare
    currentYear int = extract (year from $1);
    LeapYearShift int = 1 + (IsLeapYear(currentYear) and $1 > make_date(currentYear, 2, 28))::int;
begin
    return ((extract(doy from $1)::int)- LeapYearShift) / 7+ 1;
end;
$$;

注意

  • 1 + (IsLeapYear(currentYear) and $1 > make_date(currentYear, 2, 28))::int表示,如果今年是 LeapYear ,则需要减少一天的时间(2月29日)。让 LeapYear 的天数与正常年份相同。

SQLFIDDLE