Перейти к содержимому
Последнее обновление

TIMESTAMPTZ

Описание​

TIMESTAMPTZ — тип данных в Doris для хранения даты и времени с учётом часового пояса, соответствующий TIMESTAMP WITH TIME ZONE в стандарте SQL.

В разных системах баз данных типы временных меток с учётом часового пояса называются по-разному:

  • В PostgreSQL и Oracle используется TIMESTAMP WITH TIME ZONE
  • В SQL Server используется DATETIMEOFFSET
  • В некоторых других базах данных используется TIMESTAMP WITH LOCAL TIME ZONE

Согласно стандартам SQL, тип TIMESTAMP без дополнительных уточнений не должен содержать информацию о часовом поясе (то есть он эквивалентен TIMESTAMP WITHOUT TIME ZONE). Учитывая привычки пользователей и удобство использования, Doris использует более краткое имя TIMESTAMPTZ для обозначения типа временной метки с часовым поясом. В Doris нет отдельного типа TIMESTAMP: используйте DATETIME для значений без учёта часового пояса с широким диапазоном дат или TIMESTAMP_NS для значений без учёта часового пояса с фиксированной наносекундной точностью.

Диапазон TIMESTAMPTZ совпадает с диапазоном DATETIME: [0000-01-01 00:00:00.000000, 9999-12-31 23:59:59.999999]. TIMESTAMPTZ позволяет задавать точность в формате TIMESTAMPTZ(p), где p обозначает точность и может принимать значения из диапазона [0, 6]; значение по умолчанию равно 0. Иными словами, TIMESTAMPTZ эквивалентен TIMESTAMPTZ(0). Формат вывода по умолчанию: 'yyyy-MM-dd HH:mm:ss.SSSSSS +XX:XX', где +XX:XX обозначает смещение часового пояса (обратите внимание, что количество цифр в SSSSSS определяется точностью p).

Тип TIMESTAMPTZ можно использовать для первичного ключа, столбца партиционирования и столбца бакетирования.

Принцип работы​

Реализация TIMESTAMPTZ не хранит информацию о часовом поясе в каждой строке данных, а использует следующий механизм:

  1. При сохранении: все входные значения времени преобразуются в UTC (всемирное координированное время).
  2. При выполнении запроса: время UTC автоматически преобразуется для отображения в часовой пояс сеанса, заданный переменной time_zone.

Таким образом, TIMESTAMPTZ можно рассматривать как тип DATETIME с возможностью преобразования часовых поясов, которое Doris выполняет автоматически.

Правила обработки часовых поясов​

  • Если входные строки содержат информацию о часовом поясе (например, "2020-01-01 00:00:00 +03:00"), Doris использует эту информацию для преобразования.
  • Если входные строки не содержат информации о часовом поясе (например, "2020-01-01 00:00:00"), Doris использует для преобразования часовой пояс текущего сеанса.

Начиная с 4.1.5, при выводе исторические смещения часовых поясов IANA сохраняются с точностью до секунды в формате +HH:MM:SS. Ограничения для числовых смещений во входных временных метках отличаются от ограничений для фиксированных смещений часового пояса сеанса: во входных данных часы должны быть меньше 24, а минуты и секунды должны быть меньше 60; фиксированные смещения сеанса по-прежнему ограничены диапазоном от -12:00 до +14:00. Преобразование в часовой пояс сеанса завершается ошибкой, если полученный год по местному времени выходит за пределы диапазона от 0 до 9999.

Начиная с 4.1.5, объекты Catalog всегда сопоставляют внешние типы временных меток с учётом часового пояса с TIMESTAMPTZ. Установка свойства совместимости enable.mapping.timestamp_tz=false не позволяет восстановить прежнее сопоставление с DATETIME. Arrow Flight SQL передаёт моменты времени в виде значений Arrow Timestamp с аннотацией часового пояса; в схемах запросов используется часовой пояс сеанса (Z нормализуется в UTC). Для DATETIME используется Timestamp без аннотации часового пояса.

Хранение и использование​

В Doris поле типа TIMESTAMPTZ занимает 8 байт.

TIMESTAMPTZ поддерживает преобразования в DATETIME и TIMESTAMP_NS и обратно с соответствующей корректировкой часового пояса. TIMESTAMPTZ поддерживает неявное преобразование в DATETIME, что позволяет функциям, которые напрямую не поддерживают TIMESTAMPTZ, обрабатывать данные этого типа. При преобразовании TIMESTAMP_NS в TIMESTAMPTZ значения с наносекундной точностью округляются до целевой точности TIMESTAMPTZ.

Примеры​

-- Using the current time zone (assuming +08:00) to convert a time string without time zone information
select cast("2020-01-01 00:00:00" as timestamptz);
+--------------------------------------------+
| cast("2020-01-01 00:00:00" as timestamptz) |
+--------------------------------------------+
| 2020-01-01 00:00:00 +08:00 |
+--------------------------------------------+
-- TIMESTAMPTZ supports microseconds
select cast("2020-01-01 00:00:00.123456" as timestamptz(5));
+------------------------------------------------------+
| cast("2020-01-01 00:00:00.123456" as timestamptz(5)) |
+------------------------------------------------------+
| 2020-01-01 00:00:00.12345 +08:00 |
+------------------------------------------------------+
-- Using a time string with time zone information
select cast("2020-01-01 00:00:00 +03:00" as timestamptz);
+---------------------------------------------------+
| cast("2020-01-01 00:00:00 +03:00" as timestamptz) |
+---------------------------------------------------+
| 2020-01-01 05:00:00 +08:00 |
+---------------------------------------------------+
-- Converting TIMESTAMPTZ to DATETIME (with time zone conversion based on current time zone)
select cast(cast("2020-01-01 00:00:00 +03:00" as timestamptz) as datetime);
+---------------------------------------------------------------------+
| cast(cast("2020-01-01 00:00:00 +03:00" as timestamptz) as datetime) |
+---------------------------------------------------------------------+
| 2020-01-01 05:00:00 |
+---------------------------------------------------------------------+
-- Converting DATETIME to TIMESTAMPTZ
select cast(cast('2023-01-02 01:00:00' as datetime) as timestamptz);
+--------------------------------------------------------------+
| cast(cast('2023-01-02 01:00:00' as datetime) as timestamptz) |
+--------------------------------------------------------------+
| 2023-01-02 01:00:00 +08:00 |
+--------------------------------------------------------------+
-- Using TIMESTAMPTZ in functions
select HOUR(cast("2020-01-01 00:00:00 +03:00" as timestamptz));
+---------------------------------------------------------+
| HOUR(cast("2020-01-01 00:00:00 +03:00" as timestamptz)) |
+---------------------------------------------------------+
| 5 |
+---------------------------------------------------------+