Kiedy odejmujesz jeden znacznik czasu od drugiego, wynikiem jest wewnętrzny przedział danych, ale możesz traktować to jako „przedział z dnia na sekundę”:
select
(localtimestamp - to_timestamp(us.STARTDATETIME,'hh24:mi:ss')) as HoursPassed
from random us;
HOURSPASSED
-------------------
+08 15:26:54.293892
„+08” (w mojej strefie czasowej sesji) to liczba dni, a nie przesunięcie UTC; jest to wartość, ponieważ gdy konwertujesz ciąg na datę lub znacznik czasu i podajesz tylko część czasu, część daty jest domyślnie ustawiana na pierwszy dzień bieżącego miesiąca:
Domyślne wartości dat są określane w następujący sposób:
- Rok jest rokiem bieżącym, zwracanym przez SYSDATE.
- Miesiąc jest bieżącym miesiącem, zwracanym przez SYSDATE.
- Dzień to 01 (pierwszy dzień miesiąca).
- Godzina, minuta i sekunda to 0.
Te wartości domyślne są używane w zapytaniu, które żąda wartości dat, gdy sama data nie jest określona...
Więc naprawdę porównuję:
select localtimestamp, to_timestamp(us.STARTDATETIME,'hh24:mi:ss')
from random us;
LOCALTIMESTAMP TO_TIMESTAMP(US.STARTDATET
-------------------------- --------------------------
2017-08-09 23:26:54.293892 2017-08-01 08:00:00.000000
Nie możesz bezpośrednio sformatować interwału, ale możesz wyodrębnić elementy czasu i sformatować je oddzielnie i połączyć je.
select to_char(extract(hour from (localtimestamp
- to_timestamp(us.STARTDATETIME, 'hh24:mi:ss'))), 'FM00')
||':'|| to_char(extract(minute from (localtimestamp
- to_timestamp(us.STARTDATETIME, 'hh24:mi:ss'))), 'FM00')
||':'|| to_char(extract(second from (localtimestamp
- to_timestamp(us.STARTDATETIME, 'hh24:mi:ss'))), 'FM00')
as hourspassed
from random us;
HOURSPASSED
-----------
15:26:54
Wielokrotne obliczanie tego samego interwału wydaje się trochę marnotrawne i trudne do zarządzania, więc możesz to zrobić w widoku wbudowanym lub CTE:
with cte (diff) as (
select localtimestamp - to_timestamp(us.STARTDATETIME, 'hh24:mi:ss')
from random us
)
select to_char(extract(hour from diff), 'FM00')
||':'|| to_char(extract(minute from diff), 'FM00')
||':'|| to_char(extract(second from diff), 'FM00')
as hourspassed
from cte;
HOURSPASSED
-----------
15:26:54
Możesz także użyć dat zamiast znaczników czasu; odejmowanie daje różnicę jako liczbę, z dniami pełnymi i ułamkowymi:
select current_date - to_date(us.STARTDATETIME, 'hh24:mi') as hourspassed
from random us;
HOURSPASSED
-----------
8.64368056
Najprostszym sposobem formatowania jest dodanie go do znanej godziny północy, a następnie użycie to_char()
:
select to_char(date '1970-01-01'
+ (current_date - to_date(us.STARTDATETIME, 'hh24:mi')),
'HH24:MI:SS') as hourspassed
from random us;
HOURSPAS
--------
15:26:54
Utknąłem z current_date
jako najbliższe dopasowanie do localtimestamp
; możesz rzeczywiście chcieć systimestamp
i/lub sysdate
. (Więcej o różnicach tutaj.)