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

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

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

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

Оператор

Описание

Пример(ы)

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

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

Функция

Описание

Пример(ы)

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

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

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

current_date → date

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

current_date → 2019-12-23

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 → 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_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 ( 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_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 ( поле 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 ( 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 ( interval ) → interval

Настраивает интервал так, чтобы 30-дневные периоды времени представлялись как месяцы

justify_days(interval '35 days') → 1 mon 5 days

justify_hours ( interval ) → interval

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

justify_hours(interval '27 hours') → 1 day 03:00:00

justify_interval ( interval ) → interval

Настраивает интервал, используя justify_days и justify_hours, с дополнительной коррекцией знака

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

localtime → time

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

localtime → 14:39:53.662522

localtime ( integer ) → time

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

localtime(0) → 14:39:53

localtimestamp → timestamp

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

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

localtimestamp ( integer ) → timestamp

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

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

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

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

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

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

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

make_interval(days => 10) → 10 days

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

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

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

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

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

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

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 ( ) → timestamp with time zone

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

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

statement_timestamp ( ) → timestamp with time zone

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

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

timeofday ( ) → text

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

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

transaction_timestamp ( ) → timestamp with time zone

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

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:

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

century

Век

SELECT EXTRACT(CENTURY FROM TIMESTAMP ’2000-12-16 12:21:13’);
Результат: 20
SELECT EXTRACT(CENTURY FROM TIMESTAMP ’2001-02-16 20:38:40’);
Результат: 21

Первый век начинается в 0001-01-01 00:00:00 н. э., хотя люди в то время этого не знали. Это определение относится ко всем странам с григорианским календарем. Нет века с номером 0, после -1-го века наступает 1-й век.

day

Для значений timestamp это поле дня (месяца) (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.12
SELECT EXTRACT(EPOCH FROM INTERVAL ’5 days 3 hours’);
Результат: 442800

Значение эпохи можно преобразовать обратно в 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

Тысячелетие

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

Годы в 20 века относятся ко второму тысячелетию. Третье тысячелетие началось 1 января 2001 года.

milliseconds

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

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

minute

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

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

month

Для значений timestamp это номер месяца в году (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
SELECT EXTRACT(SECOND FROM TIME ’17:12:28.5’);
Результат: 28.5

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

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

Примечание
Когда входное значение равно +/- бесконечность, функция 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 пересчитывает для разных часовых поясов. В Таблице 33 показаны его варианты.

Таблица 33. Варианты AT 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

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

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

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