Oke, saya biasanya tidak menjawab pertanyaan saya sendiri tetapi setelah sedikit mengutak-atik, saya telah menemukan secara pasti bagaimana Oracle menyimpan hasil pengurangan DATE.
Saat Anda mengurangi 2 tanggal, nilainya bukan tipe data ANGKA (seperti yang Anda yakini oleh manual Referensi Oracle 11.2 SQL). Nomor tipe data internal dari pengurangan DATE adalah 14, yang merupakan tipe data internal yang tidak didokumentasikan (NUMBER adalah tipe data internal nomor 2). Namun, sebenarnya disimpan sebagai 2 angka bertanda komplemen dua yang terpisah, dengan 4 byte pertama digunakan untuk mewakili jumlah hari dan 4 byte terakhir digunakan untuk mewakili jumlah detik.
Contoh pengurangan DATE yang menghasilkan selisih bilangan bulat positif:
select date '2009-08-07' - date '2008-08-08' from dual;
Hasil dalam:
DATE'2009-08-07'-DATE'2008-08-08'
---------------------------------
364
select dump(date '2009-08-07' - date '2008-08-08') from dual;
DUMP(DATE'2009-08-07'-DATE'2008
-------------------------------
Typ=14 Len=8: 108,1,0,0,0,0,0,0
Ingatlah bahwa hasilnya direpresentasikan sebagai 2 komplemen dua terpisah yang ditandatangani dengan angka 4 byte. Karena tidak ada desimal dalam kasus ini (tepatnya 364 hari dan 0 jam), 4 byte terakhir semuanya 0 dan dapat diabaikan. Untuk 4 byte pertama, karena CPU saya memiliki arsitektur little-endian, byte dibalik dan harus dibaca sebagai 1,108 atau 0x16c, yang merupakan desimal 364.
Contoh pengurangan DATE yang menghasilkan selisih bilangan bulat negatif:
select date '1000-08-07' - date '2008-08-08' from dual;
Hasil dalam:
DATE'1000-08-07'-DATE'2008-08-08'
---------------------------------
-368160
select dump(date '1000-08-07' - date '2008-08-08') from dual;
DUMP(DATE'1000-08-07'-DATE'2008-08-0
------------------------------------
Typ=14 Len=8: 224,97,250,255,0,0,0,0
Sekali lagi, karena saya menggunakan mesin little-endian, byte dibalik dan harus dibaca sebagai 255.250.97.224 yang sesuai dengan 11111111 11111010 01100001 11011111. Sekarang karena ini adalah dalam penyandian angka biner bertanda komplemen dua, kita tahu bahwa jumlahnya adalah negatif karena digit biner paling kiri adalah 1. Untuk mengubahnya menjadi bilangan desimal, kita harus membalikkan komplemen 2 (kurangi 1 lalu lakukan komplemen satu) sehingga menghasilkan:00000000 00000101 10011110 00100000 yang sama dengan -368160 seperti yang diduga.
Contoh pengurangan DATE yang menghasilkan selisih desimal:
select to_date('08/AUG/2004 14:00:00', 'DD/MON/YYYY HH24:MI:SS'
- to_date('08/AUG/2004 8:00:00', 'DD/MON/YYYY HH24:MI:SS') from dual;
TO_DATE('08/AUG/200414:00:00','DD/MON/YYYYHH24:MI:SS')-TO_DATE('08/AUG/20048:00:
--------------------------------------------------------------------------------
.25
Selisih antara 2 tanggal tersebut adalah 0,25 hari atau 6 jam.
select dump(to_date('08/AUG/2004 14:00:00', 'DD/MON/YYYY HH24:MI:SS')
- to_date('08/AUG/2004 8:00:00', 'DD/MON/YYYY HH24:MI:SS')) from dual;
DUMP(TO_DATE('08/AUG/200414:00:
-------------------------------
Typ=14 Len=8: 0,0,0,0,96,84,0,0
Sekarang kali ini, karena perbedaannya adalah 0 hari dan 6 jam, diharapkan 4 byte pertama adalah 0. Untuk 4 byte terakhir, kita dapat membalikkannya (karena CPU adalah little-endian) dan mendapatkan 84,96 =01010100 01100000 basis 2 =21600 dalam desimal. Mengonversi 21600 detik ke jam memberi Anda 6 jam yang merupakan perbedaan yang kami harapkan.
Semoga ini bisa membantu siapa saja yang bertanya-tanya bagaimana sebenarnya pengurangan DATE disimpan.