0Pricing
SQL Academy · Урок

Часовые пояса: 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+00

TIMESTAMP теряет информацию

Обычный 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 — локальная установка не требуется.

Все уроки этого курса

  1. Арифметика дат и INTERVAL
  2. EXTRACT, DATE_TRUNC, AGE
  3. Часовые пояса: TIMESTAMP и TIMESTAMPTZ
  4. Распространённые отчёты по датам (MTD, WoW, YoY)
← Назад к SQL Academy