Функции даты и времени в PostgreSQL

Функции даты и времени в PostgreSQL

Есть несколько полезных функций, позволяющих работать с датами и временем в PostgreSQL.

DATE_PART в PostgreSQL — извлечение частей даты и времени.

DATE_PART извлекает отдельное поле из даты, времени или интервала: год, месяц, день, час и другие значения. Функция полезна для календарных отчётов и группировки записей по периодам.

Синтаксис


DATE_PART(field, source)


Оба аргумента обязательны. field — текстовое название поля в одинарных кавычках, например 'year'. source — значение типа timestamp, timestamptz, time, timetz или interval. Значение date автоматически преобразуется в timestamp.

Результат имеет тип double precision, даже если выглядит как целое число. При NULL в аргументах функция возвращает NULL. Допустимые поля зависят от типа источника; неподдерживаемое поле вызывает ошибку.


SELECT DATE_PART('year', DATE '2026-10-12') AS year;


-- Результат: 2026

Основные поля

В последнем столбце приведены результаты для TIMESTAMP '2026-10-12 18:25:30.5'.

Поле Что возвращает Пример
year     Календарный год 2026
quarter     Квартал года от 1 до 4 4
month     Месяц года от 1 до 12 10
day     День месяца от 1 до 31 12
hour     Час 18
minute     Минута     25
second     Секунды с дробной частью 30.5
dow     День недели от 0 до 6, воскресенье — 0 1
isodow     День недели от 1 до 7, понедельник — 1 1
doy     Порядковый день года от 1 до 365 или 366 285
week     Номер недели по ISO 8601 от 1 до 53 42
isoyear     Год по системе ISO-недель 2026

Для привычной нумерации дней недели с понедельника используйте isodow. У dow и isodow различается только номер воскресенья: 0 и 7 соответственно.

Дополнительные поля

Поле     Что возвращает Пример
century     Номер века для даты или timestamp; 2001 год относится к XXI веку 21
decade     Целая часть года, делённого на 10; для 2026 года 2026
millennium     Номер тысячелетия для даты или timestamp; для 2026 года 3
milliseconds Поле секунд целиком, умноженное на 1000; для 30.5 секунды 30500
microseconds     Поле секунд целиком, умноженное на 1 000 000; для 30.5 секунды 30500000
epoch     Число секунд от начала эпохи или в интервале  
timezone     Смещение от UTC в секундах; для +03:00 10800
timezone_hour Часовая часть смещения от UTC; для +03:00 3
timezone_minute Минутная часть смещения от UTC; для +03:30 30
julian     Юлианская дата; у timestamp время даёт дробную часть  

Поля timezone, timezone_hour и timezone_minute применяют к значениям с часовым поясом. Для timestamptz смещение определяется часовым поясом сессии, а не исходной записью значения.

ISO-недели на границе года

ISO-неделя начинается в понедельник. Первая неделя года содержит 4 января. Поэтому дата в начале января может относиться к последней неделе предыдущего ISO-года, а дата в конце декабря — к первой неделе следующего.


SELECT
    date_part('year', DATE '2021-01-01') AS year,
    date_part('isoyear', DATE '2021-01-01') AS iso_year,
    date_part('week', DATE '2021-01-01') AS iso_week;


-- Результат: year = 2021, iso_year = 2020, iso_week = 53

В недельных отчётах используйте week вместе с isoyear. Сочетание week и календарного year может неправильно распределить записи на границе года.

Интервалы и общая длительность


SELECT date_part('month', INTERVAL '2 years 3 months');


-- Результат: 3


SELECT date_part('epoch', INTERVAL '2 hours 30 minutes');


-- Результат: 9000

Для interval функция извлекает компонент, а не переводит весь интервал в выбранную единицу. В первом примере month возвращает 3, а не 27 месяцев. Аналогично day возвращает компонент дней, а не общую длительность в днях.

Поле epoch даёт общую длительность в секундах. Для интервалов с месяцами и годами это условный перевод: точное количество секунд календарного периода зависит от конкретных дат.

Часовой пояс и поле epoch

При извлечении календарных полей из timestamptz PostgreSQL использует часовой пояс текущей сессии. Один и тот же момент может иметь разные часы и даже разные даты. Чтобы получить поле в нужном поясе, укажите его явно.


SELECT date_part('hour',
    TIMESTAMPTZ '2026-10-12 20:00:00+00'
    AT TIME ZONE 'Europe/Moscow'
);


-- Результат: 23

Для timestamptz поле epoch — число секунд с 1 января 1970 года 00:00:00 UTC. Для date и timestamp без часового пояса отсчёт номинальный: часовой пояс и переходы на летнее время не учитываются. Такое значение не следует автоматически трактовать как Unix-время конкретного события.

DATE_PART и EXTRACT

Функции извлекают те же поля, но различаются синтаксисом и типом результата. В PostgreSQL 14 и новее EXTRACT возвращает numeric; DATE_PART — double precision.


SELECT date_part('month', DATE '2026-10-12');
SELECT extract(month FROM DATE '2026-10-12');


-- В обоих случаях значение месяца: 10

Для нового кода официальная документация рекомендует EXTRACT: результат numeric позволяет избежать потери точности, возможной при double precision. DATE_PART полезно знать для чтения существующих запросов и работы с названием поля как текстовым аргументом.

DATE_PART возвращает число. Если нужно получить начало месяца как дату и время, используйте DATE_TRUNC; если нужна строка определённого вида — TO_CHAR.

Пример календарного отчёта

Пусть в таблице orders есть столбец created_at типа timestamp без часового пояса. Запрос считает заказы по годам и месяцам:


SELECT date_part('year', created_at) AS year,
       date_part('month', created_at) AS month,
       count(*) AS orders_count
FROM orders
GROUP BY 1, 2
ORDER BY 1, 2;


Группировка только по month объединит одинаковые месяцы разных лет. Для created_at типа timestamptz сначала определите часовой пояс отчёта и используйте его при извлечении обоих полей.