Porque você está fazendo uma conversão explícita desnecessária de string para data, o que está fazendo um implícito conversão de data para string com base em suas configurações de NLS.
O que você deve fazer é apenas:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen
Porque
sysdate-7
já é uma data, você não deveria estar chamando to_date()
em torno disso, com qualquer formato. Como o to_date()
função recebe um argumento de string, seu sysdate-7
expressão deve ser convertida implicitamente em uma string primeiro. Então você está realmente fazendo:select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
que está usando seu valor NLS_DATE_FORMAT para o
to_char()
interno implícito call, então se for dizer 'DD-MON-RR'
você está realmente fazendo:select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
Para ver o que está acontecendo lá você precisa ver qual é a data completa gerada, então para isso vou alterar o NLS_DATE_FORMAT para a sessão mostrar o ano completo:
alter session set nls_date_format = 'SYYYY-MM-DD';
select sysdate - 7 as raw_date,
to_char(sysdate - 7, 'DD-MON-RR') as implicit_string,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YY') as implcit_yy,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY') as implcit_yyyy
from dual;
RAW_DATE IMPLICIT_STRING IMPLCIT_YY IMPLCIT_YYY
----------- ------------------ ----------- -----------
2017-04-30 30-APR-17 2017-04-30 0017-04-30
Observe os diferentes anos nos dois últimos valores. A documentação tem uma seção sobre correspondência de modelo de formato . A string que você está criando implicitamente no meio tem um ano de 2 dígitos. Quando você converte a string
'30-APR-17'
voltar para uma data usando um YY
model, ele assume 'utilmente' o século atual, então a data termina em 2017. Mas quando você converte a mesma string usando um YYYY
modelo ele acha que você realmente quis dizer o valor que você passou e então não assume um século - e você passou 17, então você acaba com o ano 17; ou seja, 0017 e não 2017. (Você também teria a resposta que esperava usando RRRR
, mas é muito melhor ficar com YYYY
e usar anos de 4 dígitos em todos os lugares - se você realmente precisa usar uma string.) Essencialmente:não confie em configurações NLS ou conversões implícitas de datas em strings ou vice-versa.
Neste caso, você não precisa de nenhum conversões, então use a instrução mais simples na parte superior desta resposta.