Часовые пояса: TIMESTAMP и TIMESTAMPTZ
Разберитесь с различиями между TIMESTAMP и TIMESTAMPTZ, конвертируйте значения с помощью AT TIME ZONE и храните время в UTC для переносимых приложений
«Часовые пояса: TIMESTAMP и TIMESTAMPTZ» — бесплатный урок SQL Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.
Два типа меток времени
В PostgreSQL есть TWO типа меток времени:
TIMESTAMP— «наивная» метка времени без информации о часовом поясеTIMESTAMPTZ— метка времени с часовым поясом (внутри хранится в UTC)
Практическое правило: предпочитайте TIMESTAMPTZ для событий, а TIMESTAMP используйте для полностью абстрактного времени, например «рабочие часы с 9:00 AM».
Как работает TIMESTAMPTZ
Внутри значение всегда хранится в UTC. При выполнении INSERT введённое значение преобразуется из часового пояса сеанса в UTC. При выполнении SELECT результат преобразуется обратно в часовой пояс сеанса.
SET TIME ZONE 'Europe/Berlin';
INSERT INTO events (ts) VALUES ('2024-03-15 12:00:00');
-- stored as 2024-03-15 11:00:00 UTC (Berlin is UTC+1 in winter)
SET TIME ZONE 'UTC';
SELECT ts FROM events;
-- 2024-03-15 11:00:00+00TIMESTAMP теряет информацию
Обычный TIMESTAMP не знает часовой пояс. Значение «2024-03-15 12:00:00» может означать любое местное время. При смене пользователем часового пояса смысл значения теряется.
AT TIME ZONE
Преобразуйте значения между часовыми поясами для отображения:
SELECT ts AT TIME ZONE 'America/New_York' AS ny_time FROM events;
SELECT ts AT TIME ZONE 'Asia/Tokyo' AS tokyo_time FROM events;Хранение UTC и отображение местного времени
Рекомендуемый подход: храните TIMESTAMPTZ, преобразуйте его в часовой пояс пользователя в SELECT и никогда не делайте наоборот.
SELECT id,
ts AT TIME ZONE COALESCE(u.tz, 'UTC') AS local_ts
FROM events e
JOIN users u ON u.id = e.user_id;ЧАСОВОЙ ПОЯС СЕАНСА
Его можно задать для отдельного сеанса, пользователя или глобально:
-- Session:
SET TIME ZONE 'Europe/Berlin';
-- Per-user (PG):
ALTER ROLE alice SET timezone TO 'Europe/Berlin';
-- Server default in postgresql.conf:
-- timezone = 'UTC'УКАЗАНИЕ ЧАСОВОГО ПОЯСА В LITERAL
Встройте часовой пояс в литерал:
SELECT TIMESTAMPTZ '2024-03-15 12:00:00 Europe/Berlin';
SELECT '2024-03-15 12:00:00+02'::TIMESTAMPTZ;NOW() возвращает TIMESTAMPTZ
NOW() и CURRENT_TIMESTAMP всегда возвращают TIMESTAMPTZ. Их смешивание со столбцами типа TIMESTAMP — распространённая ошибка.
Когда подходит TIMESTAMP (без часового пояса)
Для абстрактного или местного времени, которое действительно не зависит от часового пояса, например «магазин открывается в 09:00», используйте TIMESTAMP (или TIME).
CREATE TABLE store_hours (
store_id BIGINT,
open_at TIME NOT NULL,
close_at TIME NOT NULL
);Переходы на летнее время
TIMESTAMPTZ автоматически учитывает переходы на летнее время. Прибавление INTERVAL работает в часах на циферблате, если только вы не пересекаете границу перехода на летнее время — тогда смещение может составить 23 или 25 часов.
SELECT TIMESTAMPTZ '2024-03-30 23:00:00 Europe/Berlin' + INTERVAL '5 hours';
-- Result accounts for the DST transition on March 31Храните названия часовых поясов, а не смещения
Смещение вроде +02:00 не сообщает, когда начинается переход на летнее время. Название часового пояса, например Europe/Berlin, сообщает. Если вы храните домашний часовой пояс пользователя, сохраняйте название IANA.
Повторение
Для событий по умолчанию используйте TIMESTAMPTZ.
- Хранится как UTC, отображается в часовом поясе сеанса
- Для отображения выполняйте преобразование с помощью AT TIME ZONE
- Используйте TIMESTAMP без часового пояса только для абстрактного местного времени
Быстрая проверка
Вы создаёте глобальный сервис SaaS, который записывает события пользователей. Какой тип метки времени следует использовать для столбца occurred_at?
Часто задаваемые вопросы
Урок «Часовые пояса: TIMESTAMP и TIMESTAMPTZ» бесплатный?
Да — полный текст урока «Часовые пояса: TIMESTAMP и TIMESTAMPTZ» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.
Чему я научусь в уроке «Часовые пояса: TIMESTAMP и TIMESTAMPTZ»?
Разберитесь с различиями между TIMESTAMP и TIMESTAMPTZ, конвертируйте значения с помощью AT TIME ZONE и храните время в UTC для переносимых приложений Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Academy?
Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Часовые пояса: TIMESTAMP и TIMESTAMPTZ»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Academy?
Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Арифметика дат и INTERVAL
- EXTRACT, DATE_TRUNC, AGE
- Часовые пояса: TIMESTAMP и TIMESTAMPTZ
- Распространённые отчёты по датам (MTD, WoW, YoY)