Как получить правильный номер недели ISO от даты, используя Oracle Sql - PullRequest
0 голосов
/ 09 января 2019

Я попытался использовать следующий фрагмент кода, чтобы извлечь правильный номер недели iso для этого года, например, 01/01/2019, используя следующий код, но он по-прежнему возвращает номер недели, который является календарем, а не основанным на iso, то есть неделя 1, а не неделя 2. Честно говоря, озадачен. NLS_TERRITORY установлен в UK, если это имеет какое-то значение?

to_number(to_char(to_date(date_created,'DD/MM/YYYY'),'IW')) as WEEK_PRODUCED

Заранее благодарим за предоставленную помощь.

1 Ответ

0 голосов
/ 09 января 2019

Это происходит из-за неявного преобразования даты - при условии, что date_created на самом деле является DATE столбцом, а не строкой. Если в настройках NLS отображаются даты с двузначными годами, например формат по умолчанию 'DD-Mon-RR', преобразование значения даты в строку и обратно теряет столетие. В качестве демонстрации укажите значение даты через CTE:

alter session set nls_date_format = 'DD-Mon-RR';

with your_table (date_created) as (
  select date '2019-01-07' from dual
)
select
  to_char(date_created) as nls_date,
  to_char(date_created, 'YYYY-MM-DD') as iso_date,
  to_char(to_date(to_char(date_created), 'DD/MM/YYYY'), 'YYYY-MM-DD') as conv_date,
  to_number(to_char(to_date(date_created,'DD/MM/YYYY'),'IW')) as WEEK_PRODUCED
from your_table;

NLS_DATE  ISO_DATE   CONV_DATE  WEEK_PRODUCED
--------- ---------- ---------- -------------
07-Jan-19 2019-01-07 0019-01-07             1

Обратите внимание, что conv_date, который был преобразован в строку с использованием двухзначной модели года NLS, а затем обратно к дате с использованием четырехзначной модели года, потерял свой век; с литералами ты выглядишь так же:

select to_char(to_date('01/07/19', 'DD/MM/YYYY'), 'YYYY-MM-DD') from dual;

TO_CHAR(TO
----------
0019-07-01

потому что 19 год, ну 19 год; здесь нет ни намека, ни механизма, чтобы предположить, что вы имели в виду этот век. (Вот для чего нужна модель формата RRRR.)

Итак, вы получаете номер недели ISO для 7 января 19 года, а не 2019 года, и в этом году это была неделя 1 ISO.

Если бы ваша сессия имела четырехзначную модель года, она бы работала:

alter session set nls_date_format = 'DD/MM/YYYY';

with your_table (date_created) as (
  select date '2019-01-07' from dual
)
select
  to_char(date_created) as nls_date,
  to_char(date_created, 'YYYY-MM-DD') as iso_date,
  to_char(to_date(to_char(date_created), 'DD/MM/YYYY'), 'YYYY-MM-DD') as conv_date,
  to_number(to_char(to_date(date_created,'DD/MM/YYYY'),'IW')) as WEEK_PRODUCED
from your_table;

NLS_DATE   ISO_DATE   CONV_DATE  WEEK_PRODUCED
---------- ---------- ---------- -------------
07/01/2019 2019-01-07 2019-01-07             2

Неявно сгенерированная строка теперь имеет четырехзначный год, поэтому преобразование ее обратно сохраняет первоначальный век. (Конечно, у вас все еще будут проблемы с датами BCE ...)

Но вы вообще не должны конвертировать исходную дату. Просто сделай:

to_number(to_char(date_created,'IW')) as WEEK_PRODUCED

как и в том же CTE:

with your_table (date_created) as (
  select date '2019-01-07' from dual
)
select
  to_number(to_char(date_created,'IW')) as WEEK_PRODUCED
from your_table;

WEEK_PRODUCED
-------------
            2

, который будет работать независимо от ваших настроек NLS, так как больше не будет никакого неявного преобразования.

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