我尝试使用下面的代码来提取今年正确的iso周号,例如2019年7月1日使用以下代码,但它仍返回基于日历而不是基于iso的周号,即第1周而不是第2周。说实话。 NLS_TERRITORY是否设置为UK会有所不同?
to_number(to_char(to_date(date_created,'DD/MM/YYYY'),'IW')) as WEEK_PRODUCED
在此先感谢您提供的帮助。
答案 0 :(得分:3)
这似乎是由于隐式日期转换-假设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 2位数字年份模型转换为字符串,然后使用4位数字年份模型转换为日期,已经失去了世纪。您似乎与文字相同:
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
格式模型的作用。)
因此,您将获得19年1月7日的ISO周编号,而不是2019年,而那一年是ISO周1。
如果您的会话使用4位数字的年份模型,那么它将起作用:
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
隐式生成的字符串现在具有4位数字的年份,因此将其转换回保留原始的世纪。 (当然,您还有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设置如何,它都将起作用,因为不再存在任何隐式转换。