FirebirdSQL logo
 Структура языка SQLОбщие элементы языка 

Региональная семантика TIME WITH TIME ZONE

По определению региональные часовые пояса зависят от момента (дата и время — или timestamp), чтобы узнать его смещение UTC относительно GMT.Но Firebird также поддерживает региональные часовые пояса в значениях TIME WITH TIME ZONE.

При построении значения TIME WITH TIME ZONE из литерала или его преобразования, значение UTC должно быть вычислено и не может быть изменено, поэтому текущая дата может не использоваться.В этом случае используется фиксированная дата 2020-01-01.Таким образом, при сравнении TIME WITH TIME ZONE с различными часовыми поясами сравнение выполняется аналогично тому, как они представляют собой значения TIMESTAMP WITH TIME ZONE на заданную дату.

Однако при преобразовании между типами TIMESTAMP в TIME WITH TIME ZONE эта фиксированная дата не используется,в противном случае могут наблюдаться некоторые странные преобразования, когда текущая дата имеет другое смещение (из-за изменений летнего времени), чем в 2020-01-01.В этом случае при преобразовании TIME WITH TIME ZONE в TIMESTAMP WITH TIME ZONE сохраняется часть времени (если это возможно).Например, если текущая дата 2020-05-03, эффективное смещение в часовом поясе America/Los_Angeles равно -420, а его эффективное смещениев 2020-01-01 равно -480, но cast(time '10:00:00 America/Los_Angeles' as timestamp with time zone) даст в результате 2020-05-03 10:00:00.0000 America/Los_Angeles вместо корректировки временной части.

Но в дату, когда начинается летнее время, пропущен час, например, для часового пояса America/Los_Angeles в 2021-03-14 нет времени с 02:00:00 до 02:59:59.В этом случае преобразование выполняется как построение литерала, и час корректируется до следующего допустимого значения.Например, в 2021-03-14 cast(time '02:10:00 America/Los_Angeles' as timestamp with time zone) даст результат 2021-03-14 03:10:00.0000 America/Los_Angeles.

Литералы даты и времени

Для записи литералов даты и времени в Firebird используются сокращённые "C-style" выражения.Строковое представление даты и времени должно быть в одном из разрешённых форматов.

Синтаксис
<date_literal> ::= DATE <date>

<time_literal> ::= TIME <time>

<timestamp_literal> ::= TIMESTAMP <timestamp>

<date> ::=
  [YYYY<p>]MM<p>DD |
  MM<p>DD[<p>YYYY] |
  DD<p>MM[<p>YYYY] |
  MM<p>DD[<p>YY] |
  DD<p>MM[<p>YY]


<time> := HH[:mm[:SS[.NNNN]]] [<time zone>]

<timestamp> ::= <date> <time>

<time zone> ::=
    <time zone region> |
    [+/-] <hour displacement> [: <minute displacement>]

<p> ::= whitespace | . | : | , | - | /
Table 1. Описание формата даты и времени
Аргумент Описание

datetime

Строковое представление даты-времени.

date

Строковое представление даты.

time

Строковое представление времени.

YYYY

Год из четырёх цифр.

YY

Последние две цифры года (00-99).

MM

Месяц.Может содержать 1 или 2 цифры (1-12 или 01-12). В качестве месяца допустимо также указывать трёх буквенное сокращение или полное наименование месяца на английском языке, регистр не имеет значение.

DD

День.Может содержать 1 или 2 цифры (1-31 или 01-31).

HH

Час.Может содержать 1 или 2 цифры (0-23 или 00-23).

mm

Минуты.Может содержать 1 или 2 цифры (0-59 или 00-59).

SS

Секунды.Может содержать 1 или 2 цифры (0-59 или 00-59).

NNNN

Десятитысячные доли секунды.Может содержать от 1 до 4 цифр (0-9999).

p

Разделитель, любой из разрешённых символов, лидирующие и завершающие пробелы игнорируются.

time zone region

Один из часовых поясов связанных с регионом.

hour displacement

Смещение времени для часов относительно GMT.

minute displacement

Смещение времени для минут относительно GMT.

Правила:

  • В формате Год-Месяц-День, год обязательно должен содержать 4 цифры;

  • Для дат в формате с завершающим годом, если в качестве разделителя дат используется точка ".", то дата интерпретируется в форме День-Месяц-Год, для остальных разделителей она интерпретируется в форме Месяц-День-Год;

  • Если год не указан, то в качестве года берётся текущий год;

  • Если указаны только две цифры года, то для получения столетия Firebird использует алгоритм скользящего окна. Задача заключается в интерпретации двух символьного значения года как ближайшего к текущему году в интервале предшествующих и последующих 50 лет;

  • Если в строковом представлении времени присутствует часовой пояс или смещение времени, то тип литерала будет WITH TIME ZONE, в противном случае WITHOUT TIME ZONE;

  • Если не указан один из элементов времени, то оно принимается равным 0.

Tip

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

Example 1. Примеры литералов дат и времени
SELECT
  date '04.12.2014' AS d1, -- DD.MM.YYYY
  date '12-04-2014' AS d2, -- MM-DD-YYYY
  date '12/04/2014' AS d3, -- MM/DD/YYYY
  date '04.12.14'  AS d4,   -- DD.MM.YY
  -- DD.MM в качестве года берётся текущий
  date '04.12' AS d5,
  -- MM/DD в качестве года берётся текущий
  date '12/4' AS d6,
  date '2014/12/04'  AS d7, -- YYYY/MM/DD
  date '2014.12.04'  AS d8, -- YYYY.MM.DD
  date '2014-12-04'  AS d9, -- YYYY-MM-DD
  time '11:37' AS t1, -- HH:mm
  time '11:37:12' AS t2, -- HH:mm:ss
  time '11:31:12.1234' AS t3, -- HH:mm:ss.nnnn
  -- HH:mm:ss.nnnn +hh
  time '11:31:12.1234 +03' AS t4,
  -- HH:mm:ss.nnnn +hh:mm
  time '11:31:12.1234 +03:30' AS t5,
  -- HH:mm:ss.nnnn tz
  time '11:31:12.1234 Europe/Moscow' AS t5,
  -- HH:mm tz
  time '11:31 Europe/Moscow' AS t6,
  -- DD.MM.YYYY HH:mm
  timestamp '04.12.2014 11:37' AS dt1,
  -- MM/DD/YYYY HH:mm:ss
  timestamp '12/04/2014 11:37:12' AS dt2,
  -- DD.MM.YYYY HH:mm:ss.nnnn
  timestamp '04.12.2014 11:31:12.1234' AS dt3,
  -- YYYY-MM-DD HH:mm:ss.nnnn +hh:mm
  timestamp '2014-12-04 11:31:12.1234 +03:00' AS dt4,
  -- DD.MM.YYYY HH:mm:ss.nnnn tz
  timestamp '04.12.2014 11:31:12.1234 Europe/Moscow' AS dt5
FROM rdb$database
Note

Обратите внимание, что эти сокращённые выражения вычисляются сразу же во время синтаксического анализа (подготовки запроса или компиляции процедуры, функции или триггера). До Firebird 4.0 сокращённые выражения позволялись также для специальных строковых литералов 'NOW', 'TODAY', 'TOMORROW', 'YESTERDAY'. Использование таких выражений в компилируемом PSQL приводило к тому, что значение "замораживалось" на момент компиляции, и возвращалось не актуальное значение.Поэтому в Firebird 4.0 сокращённые выражения для таких строковых литералов запрещены, однако вы можете использовать их при приведении типа оператором CAST.