9.9. Функции и операторы даты/времени#

9.9. Функции и операторы даты/времени

9.9. Функции и операторы даты/времени #

Таблица 9.33 показывает доступные функции для обработки значений даты/времени, с подробностями, появляющимися в следующих подразделах. Таблица 9.32 иллюстрирует поведение основных арифметических операторов (+, * и т. д.). Для функций форматирования см. Раздел 9.8. Рекомендуем ознакомиться с общей информацией о типах данных даты/времени из Раздел 8.5.

Кроме того, для типов данных даты/времени доступны обычные операторы сравнения, показанные в Таблица 9.1. Даты и временные метки (с или без часового пояса) могут быть сравниваемыми, в то время как времена (с или без часового пояса) и интервалы могут быть сравниваемыми только с другими значениями того же типа данных. При сравнении временной метки без часового пояса с временной меткой с часовым поясом предполагается, что первое значение задано в часовом поясе, указанном в параметре конфигурации TimeZone, и поворачивается в UTC для сравнения со вторым значением (которое уже находится внутри UTC). Аналогично, значение даты предполагается представлять полночь в зоне TimeZone при сравнении с временной меткой.

Все функции и операторы, описанные ниже, которые принимают входные данные типа time или timestamp, на самом деле имеют два варианта: один принимает time with time zone или timestamp with time zone, а другой принимает time without time zone или timestamp without time zone. В целях краткости эти варианты не показаны отдельно. Также операторы + и * представлены в коммутативных парах (например, как date + integer и integer + date); мы показываем только одну из каждой такой пары.

Таблица 9.32. Операторы даты/времени

Оператор

Описание

Пример(ы)

date + integerdate

Добавление определенного количества дней к дате

date '2001-09-28' + 72001-10-05

date + intervaltimestamp

Добавление интервала к дате

date '2001-09-28' + interval '1 hour'2001-09-28 01:00:00

date + timetimestamp

Добавление времени суток к дате

date '2001-09-28' + time '03:00'2001-09-28 03:00:00

interval + intervalinterval

Добавление интервалов

interval '1 day' + interval '1 hour'1 day 01:00:00

timestamp + intervaltimestamp

Добавление интервала к метке времени

timestamp '2001-09-28 01:00' + interval '23 hours'2001-09-29 00:00:00

time + intervaltime

Добавление интервала к времени

time '01:00' + interval '3 hours'04:00:00

- intervalinterval

Отрицание интервала

- интервал '23 часа'-23:00:00

date - dateinteger

Вычитайте даты, получая количество прошедших дней

date '2001-10-01' - date '2001-09-28'3

date - integerdate

Вычтите определенное количество дней из даты

date '2001-10-01' - 72001-09-24

date - intervaltimestamp

Вычесть интервал из даты

date '2001-09-28' - interval '1 hour'2001-09-27 23:00:00

time - timeinterval

Вычитание времени

time '05:00' - time '03:00'02:00:00

time - intervaltime

Вычесть интервал из времени

time '05:00' - interval '2 hours'03:00:00

timestamp - intervaltimestamp

Вычесть интервал из метки времени

timestamp '2001-09-28 23:00' - interval '23 hours'2001-09-28 00:00:00

interval - intervalinterval

Вычитание интервалов

interval '1 day' - interval '1 hour'1 day -01:00:00

timestamp - timestampinterval

Вычесть метки времени (преобразование 24-часовых интервалов в дни, аналогично justify_hours())

timestamp '2001-09-29 03:00' - timestamp '2001-07-27 12:00'63 days 15:00:00

interval * double precisioninterval

Умножение интервала на скаляр

interval '1 second' * 90000:15:00

interval '1 day' * 2121 days

interval '1 hour' * 3.503:30:00

interval / double precisioninterval

Разделение интервала на скаляр

interval '1 hour' / 1.500:40:00


Таблица 9.33. Функции даты/времени

Функция

Описание

Пример(ы)

age ( timestamp, timestamp ) → interval

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

age(timestamp '2001-04-10', timestamp '1957-06-13')43 years 9 mons 27 days

age ( timestamp ) → interval

Вычтите аргумент из current_date (в полночь)

age(timestamp '1957-06-13')62 years 6 mons 10 days

clock_timestamp ( ) → timestamp with time zone

Текущая дата и время (изменяется во время выполнения оператора); см. Раздел 9.9.5

clock_timestamp()2019-12-23 14:39:53.662522-05

current_datedate

Текущая дата; см. Раздел 9.9.5

current_date2019-12-23

current_timetime with time zone

Текущее время суток; см. Раздел 9.9.5

current_time14:39:53.662522-05

current_time ( integer ) → time with time zone

Текущее время суток с ограниченной точностью; см. Раздел 9.9.5.

current_time(2)14:39:53.66-05

current_timestamptimestamp with time zone

Текущая дата и время (начало текущей транзакции); см. Раздел 9.9.5

current_timestamp2019-12-23 14:39:53.662522-05

current_timestamp ( integer ) → timestamp with time zone

Текущая дата и время (начало текущей транзакции), с ограниченной точностью; см. Раздел 9.9.5.

current_timestamp(0)2019-12-23 14:39:53-05

date_add ( timestamp with time zone, interval [, text ] ) → timestamp with time zone

Добавить interval к timestamp with time zone, вычисляя время суток и корректировки на летнее время в соответствии с часовым поясом, указанным в третьем аргументе, или текущей настройкой TimeZone, если она опущена. Форма с двумя аргументами эквивалентна оператору timestamp with time zone + interval.

date_add('2021-10-31 00:00:00+02'::timestamptz, '1 day'::interval, 'Europe/Warsaw')2021-10-31 23:00:00+00

date_bin ( interval, timestamp, timestamp ) → timestamp

Bin вводится в указанный интервал, выровненный с указанным началом; см. Раздел 9.9.3

date_bin('15 минут', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00')2001-02-16 20:35:00

date_part ( text, timestamp ) → double precision

Получите подполе временной метки (эквивалентно extract); см. Раздел 9.9.1

date_part('hour', timestamp '2001-02-16 20:38:40')20

date_part ( text, interval ) → double precision

Получить подполе интервала (эквивалентно extract); см. Раздел 9.9.1

date_part('month', интервал '2 года 3 месяца')3

date_subtract ( timestamp with time zone, interval [, text ] ) → timestamp with time zone

Вычесть interval из timestamp with time zone, вычисляя время суток и корректировки на летнее время в соответствии с часовым поясом, указанным в третьем аргументе, или текущей настройкой TimeZone, если она опущена. Форма с двумя аргументами эквивалентна оператору timestamp with time zone - interval.

date_subtract('2021-11-01 00:00:00+01'::timestamptz, '1 day'::interval, 'Europe/Warsaw')2021-10-30 22:00:00+00

date_trunc ( text, timestamp ) → timestamp

Сократите до указанной точности; см. Раздел 9.9.2.

date_trunc('hour', timestamp '2001-02-16 20:38:40')2001-02-16 20:00:00

date_trunc ( text, timestamp with time zone, text ) → timestamp with time zone

Усечь до указанной точности в указанном часовом поясе; см. Раздел 9.9.2

date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')2001-02-16 13:00:00+00

date_trunc ( text, interval ) → interval

Сократите до указанной точности; см. Раздел 9.9.2.

date_trunc('hour', interval '2 days 3 hours 40 minutes')2 days 03:00:00

extract ( field from timestamp ) → numeric

Получите подполе временной метки; см. Раздел 9.9.1.

extract(hour from timestamp '2001-02-16 20:38:40')20

extract ( field from interval ) → numeric

Получите подполе интервала; см. Раздел 9.9.1.

extract(month from interval '2 years 3 months')3

isfinite ( date ) → boolean

Тест на конечную дату (не +/-бесконечность)

isfinite(date '2001-02-16')true

isfinite ( timestamp ) → boolean

Тест на конечную временную метку (не +/-бесконечность)

isfinite(timestamp 'infinity')false

isfinite ( interval ) → boolean

Тест для конечного интервала (в настоящее время всегда истинный)

isfinite(interval '4 hours')true

justify_days ( interval ) → interval

Корректировка интервала, преобразование 30-дневных периодов времени в месяцы

justify_days(interval '1 year 65 days')1 year 2 mons 5 days

justify_hours ( interval ) → interval

Настроить интервал, преобразуя 24-часовые периоды времени в дни

justify_hours(interval '50 часов 10 минут')2 days 02:10:00

justify_interval ( interval ) → interval

Измените интервал, используя функции justify_days и justify_hours, с дополнительными корректировками знака.

justify_interval(interval '1 mon -1 hour')29 days 23:00:00

localtimetime

Текущее время суток; см. Раздел 9.9.5

localtime14:39:53.662522

localtime ( integer ) → time

Текущее время суток с ограниченной точностью; см. Раздел 9.9.5.

localtime(0)14:39:53

localtimestamptimestamp

Текущая дата и время (начало текущей транзакции); см. Раздел 9.9.5

localtimestamp2019-12-23 14:39:53.662522

localtimestamp ( integer ) → timestamp

Текущая дата и время (начало текущей транзакции), с ограниченной точностью; см. Раздел 9.9.5

localtimestamp(2)2019-12-23 14:39:53.66

make_date ( year int, month int, day int ) → date

Создание даты из полей года, месяца и дня (отрицательные годы обозначают до нашей эры)

make_date(2013, 7, 15)2013-07-15

make_interval ( [ years int [, months int[, weeks int[, days int[, hours int[, mins int [, secs double precision ]]]]]]] ) → interval

Создайте интервал из полей лет, месяцев, недель, дней, часов, минут и секунд, каждое из которых может быть установлено по умолчанию в ноль

make_interval(days => 10)10 days

make_time ( hour int, min int, sec double precision ) → time

Создание времени из полей часов, минут и секунд

make_time(8, 15, 23.5)08:15:23.5

make_timestamp ( year int, month int, day int, hour int, min int, sec double precision ) → timestamp

Создание метки времени из полей года, месяца, дня, часа, минуты и секунд (отрицательные годы обозначают до нашей эры)

make_timestamp(2013, 7, 15, 8, 15, 23.5)2013-07-15 08:15:23.5

make_timestamptz ( year int, month int, day int, hour int, min int, sec double precision [, часовой_пояс text ] ) → timestamp with time zone

Создайте метку времени с часовым поясом из полей года, месяца, дня, часа, минуты и секунды (отрицательные годы обозначают до нашей эры). Если параметр timezone не указан, используется текущий часовой пояс; примеры предполагают, что часовой пояс сессии - Europe/London

make_timestamptz(2013, 7, 15, 8, 15, 23.5)2013-07-15 08:15:23.5+01

make_timestamptz(2013, 7, 15, 8, 15, 23.5, 'America/New_York')2013-07-15 13:15:23.5+01

now ( ) → timestamp with time zone

Текущая дата и время (начало текущей транзакции); см. Раздел 9.9.5

now()2019-12-23 14:39:53.662522-05

statement_timestamp ( ) → timestamp with time zone

Текущая дата и время (начало текущего оператора); см. Раздел 9.9.5

statement_timestamp()2019-12-23 14:39:53.662522-05

timeofday ( ) → text

Текущая дата и время (как clock_timestamp, но в виде строки text); см. Раздел 9.9.5

timeofday()Mon Dec 23 14:39:53.662522 2019 EST

transaction_timestamp ( ) → timestamp with time zone

Текущая дата и время (начало текущей транзакции); см. Раздел 9.9.5

transaction_timestamp()2019-12-23 14:39:53.662522-05

to_timestamp ( double precision ) → timestamp with time zone

Преобразование Unix-эпохи (секунды с 1970-01-01 00:00:00+00) в метку времени с часовым поясом

to_timestamp(1284352323)2010-09-13 04:32:03+00


В дополнение к этим функциям, поддерживается оператор SQL OVERLAPS:

(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)

Это выражение возвращает true, когда два временных периода (определенных своими конечными точками) перекрываются, и false, когда они не перекрываются. Конечные точки можно указать в виде пар дат, времен, или временных меток; или в виде даты, времени или временной метки, за которыми следует интервал. Когда предоставляется пара значений, начало или конец могут быть записаны первыми; OVERLAPS автоматически берет более раннее значение из пары в качестве начала. Каждый временной период считается полуоткрытым интервалом start <= time < end, если только start и end не равны, в этом случае он представляет один момент времени. Это означает, например, что два временных периода, имеющих только общую конечную точку, не перекрываются.

SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
       (DATE '2001-10-30', DATE '2002-10-30');
Результат:true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS
       (DATE '2001-10-30', DATE '2002-10-30');
Результат:false
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS
       (DATE '2001-10-30', DATE '2001-10-31');
Результат:false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS
       (DATE '2001-10-30', DATE '2001-10-31');
Результат:true

При добавлении значения interval к (или вычитании значения interval из) значения timestamp или timestamp with time zone, поля месяцев, дней и микросекунд значения interval обрабатываются поочередно. Сначала ненулевое поле месяцев увеличивает или уменьшает дату временной метки на указанное количество месяцев, сохраняя день месяца тем же, если только он не выходит за пределы нового месяца, в этом случае используется последний день этого месяца. (Например, 31 марта плюс 1 месяц становится 30 апреля, но 31 марта плюс 2 месяца становится 31 мая.) Затем поле дней увеличивает или уменьшает дату временной метки на указанное количество дней. На обоих этих этапах местное время суток остается тем же. Наконец, если есть ненулевое поле микросекунд, оно добавляется или вычитается буквально. При выполнении арифметических операций с значением timestamp with time zone в часовом поясе, который признает летнее время (DST), это означает, что добавление или вычитание (например) interval '1 day' не обязательно имеет тот же результат, что и добавление или вычитание interval '24 hours'. Например, с установленным часовым поясом сессии America/Denver:

SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '1 day';
Результат:2005-04-03 12:00:00-06
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours';
Результат:2005-04-03 13:00:00-06

Это происходит потому, что час был прне указан из-за изменения летнего времени в 2005-04-03 02:00:00 в часовом поясе America/Denver.

Примечание: может возникнуть неоднозначность в поле months, возвращаемом функцией age, поскольку разные месяцы имеют разное количество дней. Подход Tantor SE-1C использует месяц из более ранней из двух дат при вычислении частичных месяцев. Например, age('2004-06-01', '2004-04-30') использует апрель, чтобы получить 1 мес 1 день, в то время как использование мая дало бы 1 мес 2 дня, потому что в мае 31 день, а в апреле только 30.

Вычитание дат и временных меток также может быть сложным. Одним из концептуально простых способов выполнить вычитание является преобразование каждого значения в количество секунд с помощью EXTRACT(EPOCH FROM ...), затем вычитание результатов; это дает количество секунд между двумя значениями. Это позволяет учесть количество дней в каждом месяце, изменения часового пояса и переход на летнее время. Вычитание значений даты или временной метки с использованием оператора - возвращает количество дней (24 часа) и часы/минуты/секунды между значениями, сделав те же корректировки. Функция age возвращает годы, месяцы, дни и часы/минуты/секунды, выполняя вычитание поля за полем, а затем корректируя отрицательные значения полей. В следующих запросах показаны различия в этих подходах. Примеры результатов были получены с использованием timezone = 'US/Eastern'; между двумя использованными датами происходит переход на летнее время.

SELECT EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
       EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00');
Результат:10537200.000000
SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
        EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'))
        / 60 / 60 / 24;
Результат:121.9583333333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00';
Результат:121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00');
Результат:4 mons

9.9.1. EXTRACT, date_part #

EXTRACT(field FROM source)

Функция extract извлекает подполя, такие как год или час, из значений даты/времени. source должен быть выражением значения типа timestamp, date, time или interval. (Метки времени и время могут быть с часовым поясом или без него.) field является идентификатором или строкой, которая выбирает, какое поле извлечь из исходного значения. Не все поля допустимы для каждого типа входных данных; например, поля меньше дня не могут быть извлечены из date, в то время как поля дня или более не могут быть извлечены из time. Функция extract возвращает значения типа numeric.

Следующие имена полей являются допустимыми:

century

Век; для значений interval поле года, деленное на 100

SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13');
Результат:20
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:21
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD');
Результат:1
SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC');
Результат:-1
SELECT EXTRACT(CENTURY FROM INTERVAL '2001 years');
Результат:20
day

День месяца (1–31); для interval значений, количество дней

SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:16
SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute');
Результат:40
decade

Поле года, разделенное на 10.

SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:200
dow

День недели от воскресенья (0) до субботы (6)

SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:5

Обратите внимание, что нумерация дней недели функции extract отличается от нумерации функции to_char(..., 'D').

doy

День года (1–365/366)

SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:47
epoch

Для значений типа timestamp with time zone количество секунд с 1970-01-01 00:00:00 UTC (отрицательное для времен до этого момента); для значений типа date и timestamp номинальное количество секунд с 1970-01-01 00:00:00, без учета часового пояса или правил перехода на летнее время; для значений типа interval общее количество секунд в интервале.

SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08');
Результат:982384720.120000
SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12');
Результат:982355920.120000
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
Результат:442800.000000

Вы можете преобразовать значение эпохи обратно в тип timestamp with time zone с помощью функции to_timestamp:

SELECT to_timestamp(982384720.12);
Результат:2001-02-17 04:38:40.12+00

Будьте осторожны при применении функции to_timestamp к эпохе, извлеченной из значения типа date или timestamp, так как это может привести к неправильному результату: результат будет предполагать, что исходное значение было задано в формате UTC, что может не соответствовать действительности.

hour

Поле часа (0–23 в метках времени, неограничено в интервалах)

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:20
isodow

День недели от понедельника (1) до воскресенья (7)

SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
Результат:7

Это идентично dow, за исключением воскресенья. Это соответствует нумерации дня недели в соответствии с ISO 8601.

isoyear

Год нумерации недель по ISO 8601, в который попадает дата

SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01');
Результат:2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02');
Результат:2006

Каждый год недельной нумерации ISO 8601 начинается с понедельника недели, содержащей 4 января, поэтому в начале января или в конце декабря ISO год может отличаться от григорианского года. См. поле week для получения дополнительной информации.

julian

Юлианская дата, соответствующая дате или временной метке. Временные метки, которые не соответствуют местному полуночи, приводят к дробному значению. См. Раздел B.7 для получения дополнительной информации.

SELECT EXTRACT(JULIAN FROM DATE '2006-01-01');
Результат:2453737
SELECT EXTRACT(JULIAN FROM TIMESTAMP '2006-01-01 12:00');
Результат:2453737.50000000000000000000
microseconds

Поле секунд, включая дробные части, умноженное на 1 000 000; обратите внимание, что это включает полные секунды.

SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
Результат:28500000
millennium

Тысячелетие; для значений interval, поле года делится на 1000

SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:3
SELECT EXTRACT(MILLENNIUM FROM INTERVAL '2001 years');
Результат:2

Годы в 1900-х годах находятся во втором тысячелетии. Третье тысячелетие началось 1 января 2001 года.

milliseconds

Поле секунд, включая дробные части, умноженное на 1000. Обратите внимание, что это включает полные секунды.

SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
Результат:28500.000
minute

Поле минут (0–59)

SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:38
month

Номер месяца в году (1–12); для значений interval, количество месяцев по модулю 12 (0–11)

SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:2
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months');
Результат:3
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
Результат:1
quarter

Четверть года (1–4), в которой находится дата

SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:1
second

Поле секунд, включая любые доли секунд

SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:40.000000
SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
Результат:28.500000
timezone

Смещение часового пояса относительно UTC, измеряемое в секундах. Положительные значения соответствуют часовым поясам на восток от UTC, отрицательные значения - на запад от UTC. (Технически, Tantor SE-1C не использует UTC, потому что не обрабатывает високосные секунды).

timezone_hour

Компонент часового пояса смещения

timezone_minute

Компонент минут смещения часового пояса

week

Количество недели года в нумерации недель ISO 8601. По определению, недели ISO начинаются в понедельник, и первая неделя года содержит 4 января этого года. Другими словами, первый четверг года находится в неделе 1 этого года.

В системе нумерации недель ISO возможно, что даты начала января могут быть частью 52-й или 53-й недели предыдущего года, а даты конца декабря могут быть частью первой недели следующего года. Например, 2005-01-01 является частью 53-й недели 2004 года, а 2006-01-01 является частью 52-й недели 2005 года, в то время как 2012-12-31 является частью первой недели 2013 года. Рекомендуется использовать поле isoyear вместе с полем week для получения последовательных результатов.

SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:7
year

Поле года. Имейте в виду, что нет 0 года н.э. 0 AD, поэтому вычитание лет до н.э. из AD н.э. следует делать внимательно.

SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
Результат:2001

При обработке значения interval, функция extract производит значения полей, которые соответствуют интерпретации, используемой функцией вывода интервала. Это может привести к неожиданным результатам, если начать с ненормализованного представления интервала, например:

SELECT INTERVAL '80 minutes';
Результат:01:20:00
SELECT EXTRACT(MINUTES FROM INTERVAL '80 minutes');
Результат:20

Примечание

Когда входное значение равно +/-Infinity, функция extract возвращает +/-Infinity для монотонно возрастающих полей (epoch, julian, year, isoyear, decade, century и millennium). Для других полей возвращается NULL. В предыдущих версиях PostgreSQL до 9.6 для всех случаев бесконечного ввода возвращался ноль.

Функция extract предназначена в основном для вычислительной обработки. Для форматирования значений даты/времени для отображения см. Раздел 9.8.

Функция date_part моделируется по аналогии с традиционной функцией Ingres, эквивалентной стандартной функции extract в SQL:

date_part('field', source)

Обратите внимание, что здесь параметр field должен быть строковым значением, а не именем. Допустимые имена полей для функции date_part такие же, как и для функции extract. По историческим причинам функция date_part возвращает значения типа double precision. Это может привести к потере точности в некоторых случаях. Рекомендуется использовать функцию extract вместо нее.

SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40');
Результат:16
SELECT date_part('hour', INTERVAL '4 hours 3 minutes');
Результат:4

9.9.2. date_trunc #

Функция date_trunc концептуально похожа на функцию trunc для чисел.

date_trunc(field, source [, time_zone ])

source - это выражение значения типа timestamp, timestamp with time zone или interval. (Значения типа date и time автоматически приводятся к типу timestamp или interval, соответственно). field выбирает точность, до которой усекается входное значение. Возвращаемое значение также имеет тип timestamp, timestamp with time zone или interval, и все поля, которые менее значимы, чем выбранное, устанавливаются в ноль (или в единицу для дня и месяца).

Допустимые значения для field следующие:

microseconds
milliseconds
second
minute
hour
day
week
month
quarter
year
decade
century
millennium

Когда входное значение имеет тип timestamp with time zone, обрезка выполняется с учетом определенного часового пояса; например, обрезка до day дает значение, которое является полночью в этом часовом поясе. По умолчанию обрезка выполняется с учетом текущей настройки TimeZone, но можно указать дополнительный аргумент time_zone, чтобы указать другой часовой пояс. Имя часового пояса можно указать любым из способов, описанных в Раздел 8.5.3.

Нельзя указывать часовой пояс при обработке ввода типа timestamp without time zone или interval. Они всегда принимаются как есть.

Примеры (предполагая, что локальный часовой пояс - America/New_York):

SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
Результат:2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
Результат:2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00');
Результат:2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney');
Результат:2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33');
Результат:3 days 02:00:00

9.9.3. date_bin #

Функция date_bin разбивает входную метку времени на указанный интервал (шаг stride), выровненный по указанному началу.

date_bin(stride, source, origin)

source - это выражение значения типа timestamp или timestamp with time zone. (Значения типа date автоматически приводятся к типу timestamp). stride - это выражение значения типа interval. Возвращаемое значение также имеет тип timestamp или timestamp with time zone, и оно обозначает начало интервала, в который помещается source.

Примеры:

SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01');
Результат:2020-02-11 15:30:00
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01 00:02:30');
Результат:2020-02-11 15:32:30

В случае полных единиц (1 минута, 1 час и т. д.) она дает тот же результат, что и аналогичный вызов функции date_trunc, но разница в том, что date_bin может усекать до произвольного интервала.

Интервал stride должен быть больше нуля и не может содержать единицы измерения месяца или больше.

9.9.4. AT TIME ZONE #

Оператор AT TIME ZONE преобразует временную метку без часового пояса в/из временной метки с часовым поясом и значения time with time zone в различные часовые пояса. Варианты использования приведены в таблице Таблица 9.34.

Таблица 9.34. AT TIME ZONE Варианты

Оператор

Описание

Пример(ы)

метка времени без часового пояса AT TIME ZONE zonetimestamp with time zone

Преобразует заданную временную метку без учета часового пояса в временную метку с учетом часового пояса, предполагая, что заданное значение находится в указанном часовом поясе.

timestamp '2001-02-16 20:38:40' at time zone 'America/Denver'2001-02-17 03:38:40+00

timestamp with time zone AT TIME ZONE zonetimestamp without time zone

Преобразует заданную временную метку с часовым поясом в временную метку без часового пояса, так, как она отобразилась бы в этом часовом поясе.

timestamp with time zone '2001-02-16 20:38:40-05' at time zone 'America/Denver'2001-02-16 18:38:40

время с часовым поясом AT TIME ZONE zonetime with time zone

Преобразует заданное время с учетом часового пояса в новый часовой пояс. Поскольку дата не указана, используется текущее активное перемещение относительно UTC для указанного целевого часового пояса.

time with time zone '05:34:17-05' at time zone 'UTC'10:34:17+00


В этих выражениях желаемый часовой пояс zone может быть указан либо в виде текстового значения (например, 'America/Los_Angeles'), либо в виде интервала (например, INTERVAL '-08:00'). В случае с текстом, имя часового пояса может быть указано любым из способов, описанных в Раздел 8.5.3. В случае с интервалом это полезно только для поясов, имеющих фиксированные смещения от UTC, поэтому на практике это не очень распространено.

Примеры (при условии, что текущая настройка TimeZone - America/Los_Angeles):

SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver';
Результат:2001-02-16 19:38:40-08
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver';
Результат:2001-02-16 18:38:40
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago';
Результат:2001-02-16 05:38:40

Первый пример добавляет временную зону к значению, которое ее не имеет, и отображает значение с использованием текущей настройки TimeZone. Второй пример сдвигает значение временной метки с временной зоной в указанную временную зону и возвращает значение без временной зоны. Это позволяет хранить и отображать значения, отличные от текущей настройки TimeZone. Третий пример преобразует время в Токио в время в Чикаго.

Функция timezone(zone, timestamp) эквивалентна конструкции, соответствующей стандарту SQL, timestamp AT TIME ZONE zone.

9.9.5. Текущая Дата/Время #

Tantor SE-1C предоставляет ряд функций, которые возвращают значения, связанные с текущей датой и временем. Эти функции, соответствующие стандарту SQL, возвращают значения, основанные на времени начала текущей транзакции:

CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIME(precision)
CURRENT_TIMESTAMP(precision)
LOCALTIME
LOCALTIMESTAMP
LOCALTIME(precision)
LOCALTIMESTAMP(precision)

CURRENT_TIME и CURRENT_TIMESTAMP возвращают значения с учетом часового пояса; LOCALTIME и LOCALTIMESTAMP возвращают значения без учета часового пояса.

CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME, и LOCALTIMESTAMP могут дополнительно принимать параметр точности, который приводит к округлению результата до указанного количества десятичных знаков в поле секунд. Без параметра точности результат предоставляется с полной доступной точностью.

Некоторые примеры:

SELECT CURRENT_TIME;
Результат:14:39:53.662522-05
SELECT CURRENT_DATE;
Результат:2019-12-23
SELECT CURRENT_TIMESTAMP;
Результат:2019-12-23 14:39:53.662522-05
SELECT CURRENT_TIMESTAMP(2);
Результат:2019-12-23 14:39:53.66-05
SELECT LOCALTIMESTAMP;
Результат:2019-12-23 14:39:53.662522

Так как эти функции возвращают время начала текущей транзакции, их значения не изменяются в течение транзакции. Это считается особенностью: цель состоит в том, чтобы позволить одной транзакции иметь последовательное представление текущего" времени, так чтобы несколько изменений в рамках одной транзакции имели одинаковую временную метку.

Примечание

Другие системы баз данных могут обновлять эти значения чаще.

Tantor SE-1C также предоставляет функции, которые возвращают время начала текущего оператора, а также фактическое текущее время в момент вызова функции. Полный список функций времени, не являющихся стандартными для SQL, включает:

transaction_timestamp()
statement_timestamp()
clock_timestamp()
timeofday()
now()

transaction_timestamp() эквивалентна CURRENT_TIMESTAMP, но названа так, чтобы ясно отражать то, что она возвращает. statement_timestamp() возвращает время начала текущего оператора (точнее, время получения последнего командного сообщения от клиента). statement_timestamp() и transaction_timestamp() возвращают одно и то же значение во время первой команды транзакции, но могут отличаться во время последующих команд. clock_timestamp() возвращает фактическое текущее время, и поэтому его значение изменяется даже в рамках одной SQL-команды. timeofday() - это историческая функция Tantor SE-1C. Как и clock_timestamp(), она возвращает фактическое текущее время, но в виде отформатированной строки text, а не значения timestamp with time zone. now() - это традиционный эквивалент Tantor SE-1C для transaction_timestamp().

Все типы данных даты/времени также принимают специальное литеральное значение now, чтобы указать текущую дату и время (снова, интерпретируемые как время начала транзакции). Таким образом, следующие три выражения возвращают одинаковый результат:

SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now';  -- but see tip below

Подсказка

Не используйте третью форму при указании значения, которое будет вычислено позже, например, в предложении DEFAULT для столбца таблицы. Система преобразует now в timestamp сразу после разбора константы, так что при необходимости значения по умолчанию будет использоваться время создания таблицы! Первые две формы не будут вычислены до использования значения по умолчанию, потому что они являются вызовами функций. Таким образом, они дадут желаемое поведение по умолчанию - использование времени вставки строки. (См. также Раздел 8.5.1.4).

9.9.6. Задержка выполнения #

Следующие функции доступны для отложенного выполнения процесса сервера:

pg_sleep ( double precision )
pg_sleep_for ( interval )
pg_sleep_until ( timestamp with time zone )

pg_sleep делает процесс текущей сессии спать до тех пор, пока не пройдет указанное количество секунд. Можно указывать задержки с долей секунды. pg_sleep_for - это удобная функция, которая позволяет указывать время сна в виде interval. pg_sleep_until - это удобная функция, когда требуется указать конкретное время пробуждения. Например:

SELECT pg_sleep(1.5);
SELECT pg_sleep_for('5 minutes');
SELECT pg_sleep_until('tomorrow 03:00');

Примечание

Эффективное разрешение интервала сна зависит от платформы; обычное значение составляет 0,01 секунды. Задержка сна будет не меньше указанного значения. Она может быть больше в зависимости от таких факторов, как загрузка сервера. В частности, функция pg_sleep_until не гарантирует точное пробуждение в указанное время, но она не пробудится раньше.

Предупреждение

Убедитесь, что ваша сессия не удерживает больше блокировок, чем необходимо, при вызове функции pg_sleep или ее вариантов. В противном случае, другие сессии могут быть вынуждены ждать вашего спящего процесса, что замедлит работу всей системы.