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.
Диапазон значений 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 не хранит информацию о часовом поясе в каждой строке данных. Вместо этого используется следующий механизм:
- При хранении: все входные значения времени преобразуются в UTC (всемирное координированное время).
- При выполнении запроса: в соответствии с часовым поясом сеанса (заданным переменной
time_zone) время UTC автоматически преобразуется в соответствующий часовой пояс для отображения.
Таким образом, 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 поддерживают взаимное преобразование с соответствующей корректировкой часового пояса. TIMESTAMPTZ поддерживает неявное преобразование в DATETIME, что позволяет функциям, которые напрямую не поддерживают 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 |
+---------------------------------------------------------+