Час изменения летнего времени в базе данных Oracle, кажется, 1:00 вместо 2:00. - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь преобразовать время UTC в BST в Oracle - однако, похоже, что время изменения данных в oracle составляет 1 час вместо 2 часов утра. Или что мне здесь не хватает? Я использовал следующий код, чтобы проиллюстрировать и проверить проблему:

WITH time1 AS (select cast('2020-03-29 01:00:00 UTC' ASTIMESTAMP WITH TIME ZONE) AS UTC_time FROM dual)
SELECT UTC_time, (UTC_time AT TIME ZONE 'Europe/London') AS bst FROM time1

И в 1:00:00 UTC время BST - 2:00:00 - и оно должно быть 1: 00: 00

1 Ответ

2 голосов
/ 15 мая 2019

Оракул прав, ваши ожидания кажутся неверными. Вы можете увидеть изменения DST в Европе / Лондоне здесь .

База данных часовых поясов IANA имеет следующее для Европы / Лондона:

# See EU for rules starting in 1996.
...
# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Europe/London   -0:01:15 -      LMT     1847 Dec  1  0:00s
                         0:00   GB-Eire %s      1968 Oct 27
                         1:00   -       BST     1971 Oct 31  2:00u
                         0:00   GB-Eire %s      1996
                         0:00   EU      GMT/BST

поэтому с 1996 года Великобритания придерживается правил ЕС, а именно:

# Europe

# The following rules are for the European Union and for its
# predecessor organization, the European Communities.
# For brevity they are called "EU rules" elsewhere in this file.

# Rule  NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
Rule    EU      1977    1980    -       Apr     Sun>=1   1:00u  1:00    S
Rule    EU      1977    only    -       Sep     lastSun  1:00u  0       -
Rule    EU      1978    only    -       Oct      1       1:00u  0       -
Rule    EU      1979    1995    -       Sep     lastSun  1:00u  0       -
Rule    EU      1981    max     -       Mar     lastSun  1:00u  1:00    S
Rule    EU      1996    max     -       Oct     lastSun  1:00u  0       -

Итак ... в Великобритании (и в остальной части ЕС) DST применяется с последнего воскресенья марта в 01:00 UTC, которое в следующем году 2020-03-29 01:00:00 UTC. И он остается в DST до последнего воскресенья октября в 01:00 UTC, которое в следующем году будет 2020-10-25 01:00:00 UTC.

Oracle следует этим правилам:

with time1 (utc_time) as (
            select timestamp '2020-03-29 00:00:00.000 UTC' FROM dual
  union all select timestamp '2020-03-29 00:59:59.999 UTC' FROM dual
  union all select timestamp '2020-03-29 01:00:00.000 UTC' FROM dual
  union all select timestamp '2020-03-29 01:59:59.999 UTC' FROM dual
  union all select timestamp '2020-03-29 02:00:00.000 UTC' FROM dual
  --
  union all select timestamp '2020-10-25 00:00:00.000 UTC' FROM dual
  union all select timestamp '2020-10-25 00:59:59.999 UTC' FROM dual
  union all select timestamp '2020-10-25 01:00:00.000 UTC' FROM dual
  union all select timestamp '2020-10-25 01:59:59.999 UTC' FROM dual
  union all select timestamp '2020-10-25 02:00:00.000 UTC' FROM dual
)
select utc_time,
  utc_time at time zone 'Europe/London' as london_time,
  to_char(utc_time at time zone 'Europe/London', 'TZD') as "DST?"
from time1
order by utc_time;

UTC_TIME                          LONDON_TIME                                 DST?  
--------------------------------- ------------------------------------------- ------
2020-03-29 00:00:00.000000000 UTC 2020-03-29 00:00:00.000000000 EUROPE/LONDON GMT   
2020-03-29 00:59:59.999000000 UTC 2020-03-29 00:59:59.999000000 EUROPE/LONDON GMT   
2020-03-29 01:00:00.000000000 UTC 2020-03-29 02:00:00.000000000 EUROPE/LONDON BST   
2020-03-29 01:59:59.999000000 UTC 2020-03-29 02:59:59.999000000 EUROPE/LONDON BST   
2020-03-29 02:00:00.000000000 UTC 2020-03-29 03:00:00.000000000 EUROPE/LONDON BST   
2020-10-25 00:00:00.000000000 UTC 2020-10-25 01:00:00.000000000 EUROPE/LONDON BST   
2020-10-25 00:59:59.999000000 UTC 2020-10-25 01:59:59.999000000 EUROPE/LONDON BST   
2020-10-25 01:00:00.000000000 UTC 2020-10-25 01:00:00.000000000 EUROPE/LONDON GMT   
2020-10-25 01:59:59.999000000 UTC 2020-10-25 01:59:59.999000000 EUROPE/LONDON GMT   
2020-10-25 02:00:00.000000000 UTC 2020-10-25 02:00:00.000000000 EUROPE/LONDON GMT   

В центральной Европе летнее время применяется с того же времени UTC, но, конечно, местное время отличается:

with time1 (utc_time) as (
  ...
)
select utc_time,
  utc_time at time zone 'Europe/Paris' as paris_time,
  to_char(utc_time at time zone 'Europe/Paris', 'TZD') as "DST?"
from time1
order by utc_time;

UTC_TIME                          PARIS_TIME                                 DST?  
--------------------------------- ------------------------------------------ ------
2020-03-29 00:00:00.000000000 UTC 2020-03-29 01:00:00.000000000 EUROPE/PARIS CET   
2020-03-29 00:59:59.999000000 UTC 2020-03-29 01:59:59.999000000 EUROPE/PARIS CET   
2020-03-29 01:00:00.000000000 UTC 2020-03-29 03:00:00.000000000 EUROPE/PARIS CEST  
2020-03-29 01:59:59.999000000 UTC 2020-03-29 03:59:59.999000000 EUROPE/PARIS CEST  
2020-03-29 02:00:00.000000000 UTC 2020-03-29 04:00:00.000000000 EUROPE/PARIS CEST  
2020-10-25 00:00:00.000000000 UTC 2020-10-25 02:00:00.000000000 EUROPE/PARIS CEST  
2020-10-25 00:59:59.999000000 UTC 2020-10-25 02:59:59.999000000 EUROPE/PARIS CEST  
2020-10-25 01:00:00.000000000 UTC 2020-10-25 02:00:00.000000000 EUROPE/PARIS CET   
2020-10-25 01:59:59.999000000 UTC 2020-10-25 02:59:59.999000000 EUROPE/PARIS CET   
2020-10-25 02:00:00.000000000 UTC 2020-10-25 03:00:00.000000000 EUROPE/PARIS CET   

Возможно , поэтому вы ожидали, что не увидите изменения времени до 02:00, но если это так, вы путаете UTC и местное время, и / или Великобританию и центральную Европу.


Не имеет непосредственного отношения к вашему вопросу, но в моем CTE я переключился с приведения строки к тимсэмпу на использование литерала метки времени . Кроме того, что он немного меньше печатает, формат однозначен. Когда вы используете приведение, вы полагаетесь на настройки NLS сеанса, соответствующие заданному вами формату строки, поэтому, хотя приведение работает для вас, оно может не сработать для того, кто выполняет ваш код. Если вы не хотите (или не можете) использовать литералы, тогда безопаснее использовать to_timestamp_tz() с явной маской формата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...