Получение секунд между двумя Oracle Timestamps
Tom Kyte предлагает использовать EXTRACT
для получите разницу:
extract( day from (x-y) )*24*60*60+
extract( hour from (x-y) )*60*60+
...
Кажется, что труднее читать и медленнее, чем это, например:
( CAST( x AS DATE ) - CAST( y AS DATE ) ) * 86400
Итак, каков способ получить разницу между двумя отметками времени в секундах? Спасибо!
Ответы
Ответ 1
"Лучшая практика"
Что бы вы ни делали, оберните его в функцию, например. seconds_between (from_date, to_date)
- не имеет значения, как он это делает (выберите наиболее эффективный метод) - тогда будет совершенно очевидно, что делает ваш код.
Производительность
Я протестировал два метода на 11gR1 на своем ноутбуке (WinXP) с тестовым примером ниже. Кажется, что опция CAST самая быстрая. (t1 - базовая линия, t2 - метод extract
, t3 - метод cast
)
t1 (nothing) 3
t2 (extract) 338
t3 (cast) 101
t1 (nothing) 3
t2 (extract) 336
t3 (cast) 100
Тест script
declare
x TIMESTAMP := SYSTIMESTAMP;
y TIMESTAMP := TRUNC(SYSDATE);
n PLS_INTEGER;
lc CONSTANT PLS_INTEGER := 1000000;
t1 PLS_INTEGER;
t2 PLS_INTEGER;
t3 PLS_INTEGER;
begin
t1 := DBMS_UTILITY.get_time;
for i in 1..lc loop
n := i;
end loop;
t1 := DBMS_UTILITY.get_time - t1;
t2 := DBMS_UTILITY.get_time;
for i in 1..lc loop
n := extract(day from (x-y))*24*60*60
+ extract(hour from (x-y))*60*60
+ extract(minute from (x-y))*60
+ extract(second from (x-y));
end loop;
t2 := DBMS_UTILITY.get_time - t2;
t3 := DBMS_UTILITY.get_time;
for i in 1..lc loop
n := ( CAST( x AS DATE ) - CAST( y AS DATE ) ) * 86400;
end loop;
t3 := DBMS_UTILITY.get_time - t3;
dbms_output.put_line('t1 (nothing) ' || t1);
dbms_output.put_line('t2 (extract) ' || t2);
dbms_output.put_line('t3 (cast) ' || t3);
end;
Ответ 2
Альтернатива:
Я нашел, что это тоже работает, чтобы получить разницу в секундах, включая миллисекунды.
Он даже экономит время-зоны с "летним днем", в то время как метод extract будет иметь проблему.
К сожалению, разница между t1 и t2 ограничена, чтобы результат был правильным. Формат времени от даты до даты не является вариантом, потому что теряются доли секунд.
select (sysdate + (t2 - t1)*1000 - sysdate) * 86.4 from
(select
to_timestamp('2014-03-30 01:00:10.111','YYYY-MM-DD HH24:MI:SS.FF') at time zone 'MET' t1,
to_timestamp('2014-03-30 03:00:10.112','YYYY-MM-DD HH24:MI:SS.FF') at time zone 'MET' t2
from dual);
Ответ 3
Я всегда использовал второй способ, то есть сравните DATE (что дает вам разницу в днях с дробной частью) и умножьте на коэффициент, который вы хотите дать вам количество часов, минут, секунд или что угодно.
Я думаю, что это хорошо и легко читать.
Ответ 4
Лично я нахожу:
extract(day from (x-y))*24*60*60 + ... + extract(second from (x-y))
понятнее, чем...
( CAST( x AS DATE ) - CAST( y AS DATE ) ) * 86400
чтобы получить разницу в секундах.
Метод Tom принимает еще несколько нажатий клавиш, но цель понятна.
Ответ 5
для быстрого и удобного использования:
extract( day from(t2 - t1)*24*60*60)
Пример:
with dates as (
select
to_timestamp('2019-06-18 22:50:00', 'yyyy-mm-dd hh24:mi:ss') t1
, to_timestamp('2019-06-19 00:00:38', 'yyyy-mm-dd hh24:mi:ss') t2
from dual
)
select
extract( day from(t2 - t1)*24*60*60) diff_in_seconds
from dates
;
Выход:
DIFF_IN_SECONDS
---------------
638
Ответ 6
to_number(to_char(t2, 'yyyymmddhh24missff')) - to_number(to_char(t1, 'yyyymmddhh24missff'))