Karena Anda melakukan konversi eksplisit yang tidak perlu dari string hingga saat ini, yang melakukan implisit konversi dari tanggal ke string berdasarkan setelan NLS Anda.
Yang seharusnya Anda lakukan hanyalah:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen
Karena sysdate-7
sudah menjadi tanggal, Anda tidak boleh memanggil to_date()
sekitar itu, dengan format apapun. Sebagai to_date()
fungsi mengambil argumen string, sysdate-7
. Anda ekspresi harus secara implisit dikonversi ke string terlebih dahulu. Jadi Anda benar-benar melakukan:
select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
yang menggunakan nilai NLS_DATE_FORMAT Anda untuk to_char()
. bagian dalam implisit panggilan, jadi jika itu mengatakan 'DD-MON-RR'
yang sebenarnya Anda lakukan:
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
Untuk melihat apa yang terjadi di sana, Anda perlu melihat tanggal yang dihasilkan secara lengkap, jadi untuk itu saya akan mengubah NLS_DATE_FORMAT agar sesi ditampilkan sepanjang tahun:
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
Perhatikan tahun yang berbeda dalam dua nilai terakhir. Dokumentasi memiliki bagian tentang pencocokan model format
. String yang Anda buat secara implisit di tengah memiliki tahun 2 digit. Saat Anda mengonversi string '30-APR-17'
kembali ke tanggal menggunakan YY
model, 'membantu' mengasumsikan abad saat ini, sehingga tanggal berakhir sebagai 2017. Tetapi ketika Anda mengonversi string yang sama menggunakan YYYY
model itu berpikir Anda benar-benar berarti nilai yang Anda berikan dan karenanya tidak menganggap satu abad - dan Anda melewatinya 17, jadi Anda berakhir dengan tahun 17; yaitu, 0017 dan bukan 2017. (Anda juga akan mendapatkan jawaban yang Anda harapkan menggunakan RRRR
, tetapi jauh lebih baik untuk tetap menggunakan YYYY
dan benar-benar menggunakan tahun 4 digit di mana-mana - jika Anda benar-benar perlu menggunakan string sama sekali.)
Intinya:jangan mengandalkan setelan NLS atau konversi implisit tanggal menjadi string atau sebaliknya.
Dalam hal ini Anda tidak memerlukan apa pun konversi, jadi gunakan pernyataan yang lebih sederhana di bagian atas jawaban ini.