#sql #oracle #timezone
По каким-то причинам не получается правильно преобразовать TIMESTAMP WITH TIMEZONE
из одной временной зоны в другую, пример:
SELECT SYSTIMESTAMP,
DBTIMEZONE,
CURRENT_TIMESTAMP
SESSIONTIMEZONE
FROM DUAL;
=============================================================================================================================================================================================================
| SYSTIMESTAMP | DBTIMEZONE
| CURRENT_TIMESTAMP |
SESSIONTIMEZONE |
=============================================================================================================================================================================================================
| 20.07.2017 7:15:33 -04:00 | Europe/Moscow
| 20.07.2017 14:15:33 +03:00 |
+03:00 |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Второй пример:
SELECT
SYSTIMESTAMP,
SYSTIMESTAMP AT TIME ZONE 'Europe/Moscow' Moscow,
SYSTIMESTAMP AT TIME ZONE 'America/New_York' New_York
FROM DUAL
==========================================================================================================================================================
| SYSTIMESTAMP | MOSCOW
| NEW_YORK |
==========================================================================================================================================================
| 20.07.2017 7:09:25 -04:00 | 20.07.2017 11:09:25
+00:00 | 20.07.2017 11:09:25 +00:00 |
----------------------------------------------------------------------------------------------------------------------------------------------------------
В данном случае в результате преобразования часовой пояс вообще сбросился, не смотря
на успешное выполнение преобразования.
Почему в первом примере результат CURRENT_TIMESTAMP отстает на час от реального,
которое должно быть равно 15:15:33, а не 14:15:33?
Почему во втором примере, не смотря на успешное выполнение команды, конвертация не
происходит? Может какие-то параметры базы данных не настроены, или я не понимаю как
AT TIME ZONE работает? Наименования временных зон я брал из V$TIMEZONE_NAMES.
Версия БД: Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
UPD:
Данные из nls_session_parameters
SQL Developer
NLS_LANGUAGE RUSSIAN
NLS_TERRITORY RUSSIA
NLS_CURRENCY ₽
NLS_ISO_CURRENCY RUSSIA
NLS_NUMERIC_CHARACTERS ,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD.MM.RR
NLS_DATE_LANGUAGE RUSSIAN
NLS_SORT RUSSIAN
NLS_TIME_FORMAT HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT DD.MM.RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD.MM.RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY ₽
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
dbForge
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS CHAR
NLS_NCHAR_CONV_EXCP FALSE
Ответы
Ответ 1
К 1-ой части вопроса SYSTIMESTAMP возвращает текущее время и часовой пояс операционной системы машины на которой установлен сервер БД. CURRENT_TIMESTAMP возвращает эти же данные учитывая часовой пояс сессии на клиенте, который определяется клиентом из окружения (установки региона на ОС, переменные) в котором он запущен и может быть изменён непосредственно: setenv ORA_SDTZ="Europe/Moscow" или alter session set time_zone='+03:00'. Посмотреть часовой пояс сессии можно так: select sessiontimezone from dual; В примере разница между Москвой и Нью-Йорком составляет -4 и +3 = 7 часов, что соответствует действительности. Значит время, которое возвращает SYSTIMESTAMP тоже с отставанием, т.е. системное время установленно не верно. Ко 2-ой части вопроса Преобразование даты и времени производится на стороне клиента и зависит от его NLS настроек, часового пояса (см. выше), которые можно посмотреть: select * from nls_session_parameters; Некоторые клиенты, как в данном примере с dbForge\IDEA "потерялся" часовой пояс, или sqlplus не учитывает изменения часового пояса в России с октября 2014 года, выполняют преобразование не всегда верно. Поэтому при сомнении имеет смысл выполнить запрос на различных клиентах. На заметку не в рамках вопроса Oracle рекомендует устанавливать DBTIMEZONE на UTC, если не используются по каким-то специфическим соображениям тип данных TIMESTAMP WITH LOCAL TIME ZONE.
Комментариев нет:
Отправить комментарий