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

В подразделе Функции даты/времени приведены имеющиеся функции для обработки значений даты/времени; подробные описания представлены в следующих подразделах. Подраздел Операторы даты/времени иллюстрирует поведение основных арифметических операторов (+, * и т. д.). Функции для форматирования описаны в разделе Функции для форматирования типов данных. С основной информацией о типах данных даты/времени можно ознакомиться в разделе Типы даты/времени.

Кроме того, для типов даты/времени имеются обычные операторы сравнения, перечисленные в подразделе Операторы сравнения. Даты и временные метки (с часовым поясом или без него) можно сравнивать как угодно, тогда как время (с часовым поясом или без него) и интервалы можно сравнивать только со значениями того же типа. При сравнении временной метки без часового пояса и временной метки с часовым поясом предполагается, что первое значение задано в часовом поясе, установленном параметром конфигурации 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); мы приводим только один вариант из каждой такой пары.



Операторы даты/времени

date + integer → date

Добавляет к дате указанное число дней.

date '2001-09-28' + 7 → 2001-10-05

date + interval → timestamp

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

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

date + time → timestamp

Добавляет к дате время.

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

interval + interval → interval

Складывает интервалы.

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

timestamp + interval → timestamp

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

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

time + interval → time

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

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

- interval → interval

Инвертирует интервал.

- interval '23 hours' → -23:00:00

date - date → integer

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

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

date - integer → date

Вычитает из даты указанное число дней.

date '2001-10-01' - 7 → 2001-09-24

date - interval → timestamp

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

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

time - time → interval

Вычитает из одного времени другое.

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

time - interval → time

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

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

timestamp - interval → timestamp

Вычитает из временной метки интервал.

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

interval - interval → interval

Вычитает из одного интервала другой.

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

timestamp - timestamp → interval

Вычитает из одной временной метки другую (преобразуя 24-часовые интервалы в дни подобно функции justify_hours()).

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

interval * double precision → interval

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

interval '1 second' * 900 → 00:15:00

interval '1 day' * 21 → 21 days

interval '1 hour' * 3.5 → 03:30:00

interval / double precision → interval

Делит интервал на скалярное значение.

interval '1 hour' / 1.5 → 00:40:00


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

age

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

clock_timestamp ( ) → timestamp with time zone

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

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

current_date

current_date → date

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

current_date → 2019-12-23

current_time

current_time → time with time zone

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

current_time → 14:39:53.662522-05

current_time ( integer ) → time with time zone

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

current_time(2) → 14:39:53.66-05

current_timestamp

current_timestamp → timestamp with time zone

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

current_timestamp → 2019-12-23 14:39:53.662522-05

current_timestamp ( integer ) → timestamp with time zone

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

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

date_add

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

date_bin ( interval, timestamp, timestamp ) → timestamp

Укладывает входное значение в заданный интервал, установленный с указанным начальным моментом; см. подраздел Функция date_bin.

date_bin('15 minutes', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00') → 2001-02-16 20:35:00

date_part

date_part ( text, timestamp ) → double precision

Выдает подполе временной метки (равнозначно extract); см. подраздел EXTRACT, date_part.

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

date_part ( text, interval ) → double precision

Выдает подполе интервала (равнозначно extract); см. подраздел EXTRACT, date_part.

date_part('month', interval '2 years 3 months') → 3

date_subtract

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

date_trunc ( text, timestamp ) → timestamp

Усекает временную метку до указанной точности; см. подраздел Функция date_trunc.

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

Усекает временную метку до указанной точности в заданном часовом поясе; см. подраздел Функция date_trunc.

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

Усекает интервал до указанной точности; см. подраздел Функция date_trunc.

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

extract

extract ( поле from timestamp ) → numeric

Выдает подполе временной метки; см. подраздел EXTRACT, date_part.

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

extract ( поле from interval ) → numeric

Выдает подполе интервала; см. подраздел EXTRACT, date_part.

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

isfinite

isfinite ( date ) → boolean

Проверяет дату на конечность (не +/- бесконечность).

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

isfinite ( timestamp ) → boolean

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

isfinite(timestamp 'infinity') → false

isfinite ( interval ) → boolean

Проверяет интервал на конечность (в настоящее время всегда true).

isfinite(interval '4 hours') → true

justify_days

justify_days ( interval ) → interval

Настраивает интервал, преобразуя 30-дневные периоды времени в месяцы.

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

justify_hours

justify_hours ( interval ) → interval

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

justify_hours(interval '50 hours 10 minutes') → 2 days 02:10:00

justify_interval

justify_interval ( interval ) → interval

Настраивает интервал, используя justify/_days и justify/_hours, с дополнительной коррекцией знака.

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

localtime

localtime → time

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

localtime → 14:39:53.662522

localtime ( integer ) → time

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

localtime(0) → 14:39:53

localtimestamp

localtimestamp → timestamp

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

localtimestamp → 2019-12-23 14:39:53.662522

localtimestamp ( integer ) → timestamp

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

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

make_date

make_date ( годint,месяцint,день int ) → date

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

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

make_interval

make_interval ( [ годыint [,месяцыint [,неделиint [,дниint [,часыint [,минутыint [,секунды double precision ]]]]]]] ) → interval

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

make_interval(days => 10) → 10 days

make_time

make_time ( часint,минутаint,секунда double precision ) → time

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

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

make_timestamp

make_timestamp ( годint,месяцint,деньint,часint,минутаint,секунда double precision ) → timestamp

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

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

make_timestamptz

make_timestamptz ( годint,месяцint,деньint,часint,минутаint,секундаdouble precision [,часовой_пояс text ] ) → timestamp with time zone

Создает временную метку с часовым поясом из полей года, месяца, недели, дня, часа, минуты и секунды (отрицательное значение года означает год до н. э.). Если часовой_пояс не указан, используется текущий часовой пояс; в примерах предполагается, что часовой пояс сеанса — 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

now ( ) → timestamp with time zone

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

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

statement_timestamp

statement_timestamp ( ) → timestamp with time zone

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

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

timeofday

timeofday ( ) → text

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

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

transaction_timestamp

transaction_timestamp ( ) → timestamp with time zone

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

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

to_timestamp

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:

(начало1, конец1) OVERLAPS (начало2, конец2)
(начало1, длительность1) OVERLAPS (начало2, длительность2)

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

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

При добавлении к значению timestamp или timestamp with time zone значения interval (или при вычитании из него значения interval) поля месяцев, дней и микросекунд значения interval обрабатываются по очереди. Сначала в ненулевом поле месяцев дата временной метки прибавляется или убавляется на указанное количество месяцев, сохраняя день месяца неизменным, если он не превышает количество дней в новом месяце, а в ином случае используется последний день этого месяца. (Например, 31 марта плюс 1 месяц становится 30 апреля, но 31 марта плюс 2 месяца становится 31 мая.) Затем в поле дней дата временной метки прибавляется или убавляется на указанное количество дней. На обоих этих этапах локальное время суток остается неизменным. Наконец, если имеется ненулевое поле микросекунд, оно прибавляется или вычитается буквально. При выполнении арифметических действий со значением timestamp with time zone в часовом поясе, учитывающем переход на летнее время, это означает, что прибавление или вычитание (например) 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, потому что в разных месяцах разное количество дней. При расчете неполных месяцев QHB использует месяц от более ранней из двух дат. Например, age('2004-06-01', '2004-04-30') использует апрель, и получается 1 mon 1 day, тогда как использование мая даст 1 mon 2 days, потому что в мае 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


EXTRACT, date_part

EXTRACT(поле FROM источник)

Функция extract извлекает из значений даты/времени подполя, такие как год или час. Аргумент источник должен быть выражением значения типа timestamp, date, time или interval. (Время и временная метка могут быть как с часовым поясом, так и без него). Аргумент поле — это идентификатор или строка, выбирающая, какое поле извлечь из исходного значения. Не все поля допустимы для каждого типа данных; к примеру, поля меньше суток не могут вычитаться из типа 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

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

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

Годы в 20 веке относятся ко второму тысячелетию. Третье тысячелетие началось 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. (Строго говоря, QHB не использует 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 года. Для получения согласованных результатов рекомендуется вместе с полем week использовать поле isoyear.

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

year

Поле года. Имейте в виду, что 0-го года н. э. (0 AD) не существует, поэтому вычитать годы до н. э. (BC) из годов после н. э. (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

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

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

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

date_part('поле', источник)

Обратите внимание, что здесь параметр поле должен быть строковым значением, а не именем. Допустимые имена полей для 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


Функция date_trunc

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

date_trunc(поле, источник [, часовой_пояс ])

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

Допустимые значения для аргумента поле:

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

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

Часовой пояс нельзя указывать при обработке входных данных типа 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


Функция date_bin

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

date_bin(шаг, источник, начальный_момент)

Здесь источник — это выражение значения типа timestamp или timestamp with time zone. (Значения типа date автоматически приводятся к типу timestamp.) Под шагом подразумевается выражение значения типа interval. Возвращаемое значение также имеет тип timestamp или timestamp with time zone и отмечает начало позиции, в которую помещается источник.

Примеры:

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 может усечь дату до произвольного интервала.

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



AT TIME ZONE

Оператор AT TIME ZONE преобразует временную метку без часового пояса в метку времени с часовым поясом и обратно, а значения типа time with time zone пересчитывает для разных часовых поясов. Ниже показаны его варианты.

timestamp without time zone AT TIME ZONE часовой_пояс → timestamp 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 часовой_пояс → timestamp 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

time with time zone AT TIME ZONE часовой_пояс → time with time zone

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

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

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

Примеры (предполагается, что текущее значение параметра TimeZoneAmerica/ 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-05' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago';
Результат: 2001-02-16 05:38:40

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

Функция timezone (часовой_пояс, временная_метка) равнозначна совместимой с SQL конструкции временная_метка AT TIME ZONE часовой_пояс.



Текущая дата/время

QHB предоставляет ряд функций, которые возвращают значения, зависящие от текущих даты и времени. Все эти функции, соответствующие стандарту SQL, возвращают значения, опирающиеся на время начала текущей транзакции:

CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIME(точность)
CURRENT_TIMESTAMP(точность)
LOCALTIME
LOCALTIMESTAMP
LOCALTIME(точность)
LOCALTIMESTAMP(точность)

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

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

Несколько примеров:

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

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

Примечание
В других СУБД эти значения могут меняться чаще.

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

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

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

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

SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP ’now’; -- но см. совет ниже

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



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

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

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 или ее вариантов убедитесь, что ваш сеанс не содержит больше блокировок, чем это необходимо. В противном случае другим сеансам, возможно, придется ждать завершения вашего спящего режима, замедляя работу всей системы.