Функции и операторы даты/времени
В Таблице 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_bindate_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_partdate_part('hour', timestamp '2001-02-16 20:38:40') → 20 |
||
date_part ( text, interval ) → double precision | ||
Выдает подполе интервала (равнозначно extract); см. подраздел EXTRACT, date_partdate_part('month', interval '2 years 3 months') → 3 |
||
date_trunc ( text, timestamp ) → timestamp | ||
Усекает временную метку до указанной точности; см. подраздел date_truncdate_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_truncdate_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_truncdate_trunc('hour', interval '2 days 3 hours 40 minutes') → 2 days 03:00:00 |
||
extract ( поле from timestamp ) → numeric | ||
Выдает подполе временной метки; см. подраздел EXTRACT, date_partextract(hour from timestamp '2001-02-16 20:38:40') → 20 |
||
extract ( поле from interval ) → numeric | ||
Выдает подполе интервала; см. подраздел EXTRACT, date_partextract(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, поэтому на
практике он не очень распространен
Примеры (предполагается, что текущее значение параметра 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-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 или ее вариантов убедитесь, что ваш сеанс не содержит больше блокировок, чем это необходимо. В противном случае другим сеансам, возможно, придется ждать завершения вашего спящего режима, замедляя работу всей системы.