Как получить постоянный номер недели от високосного или обычного года? - PullRequest
0 голосов
/ 24 июня 2018

Использование PostgreSQL версии 9.4.18, PostGIS версии 2.2 Я использую эту функцию и использую WW, потому что не хочу номера недель ISO ... только номер недели, начинающийся с 1 января:

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

Когда я запускаю следующий запрос, каждые 4 года номер недели меняется, это високосный год.Я пытаюсь получить последовательные номера недели из года в год на определенную дату.Так, например, когда я запускаю

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

как woy для 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

Есть ли способ, которым я могу игнорировать високосные годы и сохранять все согласованным, чтобы все 06-24 были неделей номер 25. Я видел несколько сообщений об определениибыл ли это високосный год или нет, но мне трудно интегрировать эту логику, чтобы я мог применить ее ко всем запросам, где я проверяю номера недель.

1 Ответ

0 голосов
/ 24 июня 2018

Вы можете использовать выражение CASE WHEN, чтобы проверить, является или нет этот год високосным годом

  1. Этот год високосным годом результат возвратаминус 1.
  2. Этот год не високосный год результат возврата.

Формула для високосного года равна

(год% 4 = 0) И (год% 100 <> 0) ИЛИ (год% 400 = 0)

Добавьте эту формулу в условие CASE WHEN, чтобы она выглядела

this.

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 неделя високосного года будет такой же, как и у недели нормального года.

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

РЕДАКТИРОВАТЬ

високосный год означает, что добавится 29 февраля в этом годуТаким образом, вы можете попробовать это, чтобы сделать это.

IsLeapYear функция получает этот год или не является високосным годом.

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 нужно минус больше на один день (29 февраля),Пусть дни LeapYear совпадают с обычным годом.

SQLFIDDLE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...