Страницы

Поиск по вопросам

Показаны сообщения с ярлыком timezone. Показать все сообщения
Показаны сообщения с ярлыком timezone. Показать все сообщения

четверг, 5 марта 2020 г.

Преобразование TIMESTAMP WITH TIME ZONE в Oracle 12c

#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.

четверг, 13 февраля 2020 г.

Как получить время из PostgreSQL в том же самом часовом поясе, в котором и было изначально загружено в БД, вместо UTC?

#python #django #postgresql #timezone



Есть данные, которые через Django загружаются в базу в формате “2015-10-31 17:00:00+03”
(aware форма времени).
PostgreSQL имеет свойство сохранять время в UTC.
В pgAdmin-е я вижу время не в UTC, а в том виде, в котором было изначально загружено
значение, т.е. “2015-10-31 17:00:00+03”.


К примеру я загружаю новые данные, но перед заливкой в БД нужно сравнить эти данные
со значениями, которые уже есть в БД.
Новая порция идет в формате: 

"2015-10-31 17:00:00+03“,
а значения из БД вытягиваются уже в UTC, т.е. 

”2015-10-31 14:00:00+00".

Как сделать так, чтоб значение вытягивалось из БД не в UTC, а в том же часовом поясе,
в котором и было залито?

test = Shows.objects.get(name='Test')
test.date_time # выдает в UTC, а нужно чтоб было +3


П.С Хардкодить нельзя. Нужно получать именно тот часовой пояс из БД, что и был залит
изначально со значением, так как заливаться значения могут с разным часовым поясом.
    


Ответы

Ответ 1



Документация django говорит, что PostgreSQL преобразует местное время (время c часовой зоной, указанной для текущего соединения с базой данной) в UTC при сохранении и наоборот преобразует из UTC в местное время при чтении. Как сделать так, чтоб значение вытягивалось из БД не в UTC, а в том же часовом поясе, в котором и было залито? Если USE_TZ=True, то для соединения используется UTC временна́я зона, то есть postgresql видит только UTC. Если Вы сохраняете время, принадлежащее нескольким временны́м зонам, то дополнительно к самому времени с типом timestamptz, сохраняйте также и имя временно́й зоны (например, 'Europe/Kiev' или 'Europe/Moscow'). Если важно получить тоже самое локальное время, даже если правила изменились (если другая версия tzdata используется), то сохраняйте также явно текущий utc offset в минутах и другую необходимую информацию отдельно. Зная, UTC время и имя зоны, можно получить желаемое время (используя текущие правила (tzdata version)) в Питон коде: import pytz # $ pip install pytz local = utc.astimezone(pytz.timezone('Europe/Kiev')) Чтобы запросить время из базы данных напрямую в заданной временно́й зоне: select your_date at time zone 'Europe/Kiev' from your_table Зная, UTC время и utc offset в минутах: local = utc.astimezone(pytz.FixedOffset(120)) Чтобы получить время в текущей временно́й зоне для django (зона, которая используется для показа в шаблонах): from django.utils import timezone local = timezone.localtime(utc)

Ответ 2



Воспользуйтесь pytz >>> from datetime import datetime, timedelta >>> from pytz import timezone >>> import pytz >>> utc = pytz.utc >>> utc.zone 'UTC' >>> eastern = timezone('US/Eastern') >>> eastern.zone 'US/Eastern' >>> amsterdam = timezone('Europe/Amsterdam') >>> fmt = '%Y-%m-%d %H:%M:%S %Z%z' >>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0)) >>> print loc_dt.strftime(fmt) 2002-10-27 06:00:00 EST-0500 >>> ams_dt = loc_dt.astimezone(amsterdam) >>> ams_dt.strftime(fmt) '2002-10-27 12:00:00 CET+0100'

пятница, 24 января 2020 г.

Как высчитывать разницу во времени, учитывая часовые зоны?

#javascript #время #timezone #momentjs


Мне нужно сделать таймер обратного отсчета до какого-то события при помощи библиотеки
MomentJS.

Сервер мне присылает время (назовем его eventTime), до которого должен идти отсчет,
я выясняю разницу между текущим и вывожу в HTML. Здесь все просто. 
Проблема в том, что сервер присылает время по МСК и преобразование eventTime = moment.utc(time)
в функции таймера мне ничего не дает.

Как мне высчитывать разницу во времени, учитывая часовые зоны? 
    


Ответы

Ответ 1



В идеале конечно получать от сервера время в UTC. Но если это невозможно, преобразовывайте из московского времени с помощью moment timezone: var t = moment.tz("2013-11-18 11:55", 'Europe/Moscow'); И не забывайте обновлять библиотеку moment timezone каждый раз, когда вступит в силу новый закон о летнем времени в зоне 'Europe/Moscow' (и ребята из moment timezone обновят сборку). Альтернативный вариант - присылать с сервера сразу оставшееся время (например в секундах) до нужного события. В этом случае будет не важно, какое время у клиента (в том числе, если оно вообще неправильно выставлено, как иногда бывает когда пытаются продлить триальные версии некоторых программ).

пятница, 10 января 2020 г.

Android Как получить время, отображаемое в StatusBar

#java #android #время #calendar #timezone


Здравствуйте! 

Некоторые пользователи при переходе на постоянное зимнее время отключили синхронизацию
времени и часового пояса по сети и вручную перевели время на час назад. 

Сейчас у них на телефонах, к примеру, установлен часовой пояс, в котором 14:00, а
на телефоне отображается текущее время 13:00. 

При получении времени методами 

System.currentTimeMillis(), Calendar.getInstance().getTimeInMillis()


возвращает 14:00. Как получить время пользователя правильно?
    


Ответы

Ответ 1



Всё, что я смог найти, сведено вот в этот пост. Резюме: без использования дополнительных запросов к серверу и/или получения собственных координат (которые не всегда могут быть доступны), невозможно получить необходимую разницу во времени. Это же относится и к отменённому летнему времени: часть устройств всё ещё считает, что летом часовой пояс Москвы GMT+4, часть - уже знает, что GMT+3. И кроме запроса на сервер в общем случае никаким образом их не синхронизировать.

Ответ 2



Нет возможности проверить, но думаю нужно получить таймзону и посчитать с ней? TimeZone tz = TimeZone.getDefault(); или попробовать другой способы: Time now = new Time(); now.setToNow(); http://developer.android.com/reference/android/text/format/Time.html

Ответ 3



Calendar.getInstance().getTimeInMillis() возвращает количество миллисекунд в часовом поясе UTC. Как вы проверяете что это соответвует 14:00? Может быть, пользователь не переводил время, а поставил себе соседний часовой пояс? В любом случае попробуйте проверить какой час возвращается если использовать Calendar.getInstance().get(Calendar.HOUR_OF_DAY)

вторник, 19 марта 2019 г.

Как высчитывать разницу во времени, учитывая часовые зоны?

Мне нужно сделать таймер обратного отсчета до какого-то события при помощи библиотеки MomentJS.
Сервер мне присылает время (назовем его eventTime), до которого должен идти отсчет, я выясняю разницу между текущим и вывожу в HTML. Здесь все просто. Проблема в том, что сервер присылает время по МСК и преобразование eventTime = moment.utc(time) в функции таймера мне ничего не дает.
Как мне высчитывать разницу во времени, учитывая часовые зоны?


Ответ

В идеале конечно получать от сервера время в UTC. Но если это невозможно, преобразовывайте из московского времени с помощью moment timezone
var t = moment.tz("2013-11-18 11:55", 'Europe/Moscow');
И не забывайте обновлять библиотеку moment timezone каждый раз, когда вступит в силу новый закон о летнем времени в зоне 'Europe/Moscow' (и ребята из moment timezone обновят сборку).
Альтернативный вариант - присылать с сервера сразу оставшееся время (например в секундах) до нужного события. В этом случае будет не важно, какое время у клиента (в том числе, если оно вообще неправильно выставлено, как иногда бывает когда пытаются продлить триальные версии некоторых программ).