sql >> Base de Datos >  >> RDS >> Oracle

Marca de tiempo de Oracle con traducción transparente de valores de zona horaria local

TIMESTAMP WITH LOCAL TIME ZONE funciona así:cuando tiene que trabajar con zonas horarias en su aplicación, un enfoque común es

Así es exactamente como TIMESTAMP WITH LOCAL TIME ZONE funciona - la única diferencia es

Por esa razón no puedes cambiar DBTIMEZONE (con ALTER DATABASE SET TIME_ZONE='...'; ) en su base de datos si la base de datos contiene una tabla con un TIMESTAMP WITH LOCAL TIME ZONE columna y la columna contiene datos.

SYSTIMESTAMP se devuelve en la zona horaria del sistema operativo del servidor de la base de datos. DBTIMEZONE es no la zona horaria de SYSTIMESTAMP o SYSDATE .

DBTIMEZONE define el formato de almacenamiento interno de TIMESTAMP WITH LOCAL TIME ZONE columnas de tipo de datos. Olvida esto, no puedo imaginar ningún caso de uso en el que lo necesites.

En realidad, su tabla es equivalente a esta selección:

select 
   CAST(systimestamp AS timestamp(0) with local time zone) as SYSTIMESTAMP_COL,
   CAST(sysdate AS timestamp(0) with local time zone) as SYSDATE_COL,
   CAST(current_timestamp AS timestamp(0) with local time zone) as CURRENT_TIMESTAMP_COL,
   CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone) as DATE_COL
from dual;

Cuando haces CAST({time without time zone} with local time zone) luego intenta convertir un valor de fecha/hora sin ninguna información de zona horaria a un valor de fecha/hora con zona horaria. En principio, esto no es posible porque Oracle carece de la información de la zona horaria, por lo que Oracle asume una zona horaria. Si realiza dicha conversión, Oracle siempre considera {hora sin zona horaria} como se indica en SESSIONTIMEZONE (en el momento de la conversión).

Así que CAST(sysdate AS timestamp(0) with local time zone) es equivalente a

CAST(FROM_TZ(TO_TIMESTAMP(SYSDATE), SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)` 

resp. CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone) significa

CAST(FROM_TZ(TIMESTAMP '2017-03-15 19:02:00', SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)

Para SYSDATE esto es realmente incorrecto, porque SYSDATE se proporciona en la zona horaria del sistema operativo del servidor de la base de datos, no en SESSIONTIMEZONE. Para el segundo, depende de tu intención si el resultado es correcto o no.

SYSTIMESTAMP devuelve el valor TIMESTAMP WITH TIME ZONE , siempre es independiente de su SESSIONTIMEZONE actual . Pero si convierte a TIMESTAMP WITH LOCAL TIME ZONE se convierte a su zona horaria local actual, por supuesto. También puede usar CURRENT_TIMESTAMP o SYSTIMESTAMP AT LOCAL que hace más o menos lo mismo.

Este código

parece estar mal El resultado debe ser

-- SYSTIMESTAMP_COL                   15/03/2017 16:01:14
-- SYSDATE_COL                        15/03/2017 19:01:14
-- CURRENT_TIMESTAMP_COL              15/03/2017 16:01:14
-- DATE_COL                           15/03/2017 19:02:00

Las diferencias se ven como deberían ser, pero los valores absolutos parecen ser "falsos" (o hay un problema real con su base de datos).