Ладно, я обычно не отвечаю на свои вопросы, но после некоторой переделки я определил, как Oracle хранит результат вычитания ДАТЫ.
Когда вы вычитаете 2 даты, значениене является типом данных NUMBER (как вы могли бы поверить Справочное руководство по Oracle 11.2 SQL ).Внутренний номер типа вычитания DATE равен 14, что является недокументированным внутренним типом данных (NUMBER внутренний тип данных 2 ).Однако на самом деле он хранится в виде двух отдельных чисел с двумя дополнительными знаками, причем первые 4 байта используются для представления количества дней, а последние 4 байта используются для представления количества секунд.
Пример DATEвычитание, приводящее к положительной разнице в целых числах:
select date '2009-08-07' - date '2008-08-08' from dual;
Результат:
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
Напомним, что результат представлен в виде двоичного числа с двумя дополнительными двумя, дополненного 4-значными числами.Поскольку в этом случае десятичные дроби отсутствуют (ровно 364 дня и 0 часов), последние 4 байта равны нулю и могут быть проигнорированы.Для первых 4 байтов, поскольку мой ЦП имеет архитектуру с прямым порядком байтов, байты меняются местами и должны читаться как 1,108 или 0x16c, что является десятичным числом 364.
Пример вычитания ДАТЫ, приводящего к отрицательному значениюразница целых чисел:
select date '1000-08-07' - date '2008-08-08' from dual;
Результат:
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
Опять же, поскольку я использую машину с прямым порядком байтов, байты меняются местами и должны читаться как 255,250,97,224, что соответствует11111111 11111010 01100001 11011111. Теперь, так как это двоичное двоичное числовое кодирование со знаком дополнения до двух, мы знаем, что число является отрицательным, потому что крайняя левая двоичная цифра - 1. Чтобы преобразовать это в десятичное число, мы должны были бы повернуть дополнение до 2 (вычтите 1, затем выполните дополнение), в результате чего: 00000000 00000101 10011110 00100000, что соответствует -368160, как и предполагалось.
Пример вычитания ДАТЫ, приводящего к десятичной разнице:
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
разница между этими двумя датами составляет 0,25 дня или 6 часов.
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
Нетw на этот раз, поскольку разница составляет 0 дней и 6 часов, ожидается, что первые 4 байта равны 0. Для последних 4 байтов мы можем обратить их (поскольку ЦП имеет младший порядок) и получить 84,96 = 0101010001100000 основание 2 = 21600 в десятичном виде.Преобразование 21600 секунд в часы дает вам 6 часов, что является той разницей, которую мы ожидали.
Надеюсь, что это поможет любому, кто интересуется, как на самом деле сохраняется вычитание ДАТЫ.