Cuando resta una marca de tiempo de otra, el resultado es un tipo de datos de intervalo interno, pero puede tratarlo como 'intervalo día a segundo':
select
(localtimestamp - to_timestamp(us.STARTDATETIME,'hh24:mi:ss')) as HoursPassed
from random us;
HOURSPASSED
-------------------
+08 15:26:54.293892
El '+08' (en la zona horaria de mi sesión) es el número de días, no un desplazamiento UTC; ese es el valor porque cuando convierte una cadena en una fecha o marca de tiempo y solo proporciona la parte de la hora, la parte de la fecha se establece de forma predeterminada en el primer día del mes actual:
Los valores de fecha predeterminados se determinan de la siguiente manera:
- El año es el año actual, tal como lo devuelve SYSDATE.
- El mes es el mes actual, tal como lo devuelve SYSDATE.
- El día es 01 (el primer día del mes).
- La hora, el minuto y el segundo son todos 0.
Estos valores predeterminados se usan en una consulta que solicita valores de fecha donde la fecha en sí no se especifica...
Así que realmente estoy comparando:
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
No puede formatear directamente un intervalo, pero puede extraer los elementos del tiempo y formatearlos por separado y concatenarlos.
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
Calcular repetidamente el mismo intervalo parece un poco inútil y difícil de administrar, por lo que puede hacerlo en una vista en línea o un 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
También puede usar fechas en lugar de marcas de tiempo; la resta te da la diferencia como un número, con días enteros y fraccionarios:
select current_date - to_date(us.STARTDATETIME, 'hh24:mi') as hourspassed
from random us;
HOURSPASSED
-----------
8.64368056
La forma más sencilla de formatear eso es agregarlo a una hora de medianoche conocida y luego usar 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
Me he quedado con current_date
como la coincidencia más cercana a localtimestamp
; es posible que desee systimestamp
y/o sysdate
. (Más información sobre la diferencia aquí).