Есть несколько полезных функций, позволяющих работать с датами и временем в 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_countFROM ordersGROUP BY 1, 2ORDER BY 1, 2;
Группировка только по month объединит одинаковые месяцы разных лет. Для created_at типа timestamptz сначала определите часовой пояс отчёта и используйте его при извлечении обоих полей.