Текущая дата на сервере
PostgreSQL поддерживает все типы данных, предусмотренные стандартом SQL для даты и времени. Даты обрабатываются в соответствии с григорианским календарем.
В таблице ниже перечислены поддерживаемые типы даты/времени
Имя | Описание | Наименьшее значение | Наибольшее значение | Точность |
---|---|---|---|---|
timestamp [ (p) ] [ without time zone ] | дата и время без часового пояса | 4713 до н. э. | 294276 н. э. | 1 микросекунда |
timestamp [ (p) ] with time zone | дата и время с часовым поясом | 4713 до н. э. | 294276 н. э. | 1 микросекунда |
date | дата (без времени суток) | 4713 до н. э. | 5874897 н. э. | 1 день |
time [ (p) ] [ without time zone ] | время суток (без даты) | 00:00:00 | 24:00:00 | 1 микросекунда |
time [ (p) ] with time zone | время суток (без даты), с часовым поясом | 00:00:00+1559 | 24:00:00-1559 | 1 микросекунда |
interval [ поля ] [ (p) ] | временной интервал | -178000000 лет | 178000000 лет | 1 микросекунда |
В таблице используются следующие обозначения
- [. ] — в квадратных скобках указываются необязательные поля.
- (p) — точность хранения данных, количество разрядов в дробной части секунды.
Время с указанием часового пояса time with time zone стоит использовать с осторожностью. В этом типе не хранится дата, а смещение часового пояса может изменяться при переходе на летнее/зимнее время.
При работе с датами есть много нюансов, особенно с часовыми поясами. Но обо всем по порядку.
Получение текущей даты
Текущую дату на сервере можно получить с помощью функции CURRENT_DATE .
SELECT CURRENT_DATE
# | current_date |
---|---|
1 | 2022-12-06 |
Функция CURRENT_DATE возвращает текущую дату с типом данных date .
Получение даты со временем
Для получения текущей даты со временем есть две функции:
- CURRENT_TIMESTAMP — возвращает текущую дату со временем с указанием часового пояса (тип данных timestamp with time zone).
- LOCALTIMESTAMP — возвращает текущую дату со временем без указания часового пояса (тип данных timestamp without time zone).
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP
# | current_timestamp | localtimestamp |
---|---|---|
1 | 2022-12-06 12:13:39.414652+07 | 2022-12-06 12:13:39.414652 |
Получение времени
Для получения времени есть также две функции:
- CURRENT_TIME — возвращает текущее время с указанием часового пояса (тип данных time with time zone)
- LOCALTIME — возвращает текущее время без указания часового пояса (тип данных time with time zone)
SELECT CURRENT_TIME, LOCALTIME
# | current_time | localtime |
---|---|---|
1 | 12:18:52.072083+07 | 12:18:52.072083 |
Обрати внимание, что текущая дата и время берутся с сервера, на котором запущена СУБД.
8.13 TO_CHAR — форматирование числа
9.2 Точность хранения времени
Как узнать текущую дату в sql
Из всех типов данных в SQL временны́е данные являются наиболее сложными . Сложность возникает по нескольким причинам, и вот некоторые из них:
- множество способов задания даты и времени
- наличие временных зон
- неочевидность вычислений некоторых значений на основании временных данных. Например, сложность вычисления возраста.
Временные данные можно получить одним из следующих способов:
- скопировать данные из существующего столбца с времéнным типом данных
- задать дату и время через строковое представление
- получить временны́е данные путём вызова встроенных функций, возвращающих временной тип данных
Для задания даты и времени используются следующие форматы:
Тип | Формат по умолчанию |
---|---|
DATE | YYYY-MM-DD |
DATETIME | YYYY-MM-DD hh:mm:ss |
TIMESTAMP | YYYY-MM-DD hh:mm:ss |
TIME | hhh:mm:sss |
YEAR | YYYY — полный формат YY или Y — сокращённый формат, который возвращает год в пределах 2000-2069 для значений 0-69 и год в пределах 1970-1999 для значений 70-99 |
Причём, при указании даты допускается использовать любой знак пунктуации в качестве разделительного между частями разделов даты или времени. Также возможно задавать дату вообще без разделительного знака, слитно.
Примеры валидного задания временных значений через строковое представление:
MySQLSELECT CAST("2022-06-16 16:37:23" AS DATETIME) AS datetime_1, CAST("2014/02/22 16*37*22" AS DATETIME) AS datetime_2, CAST("20220616163723" AS DATETIME) AS datetime_3, CAST("2021-02-12" AS DATE) AS date_1, CAST("160:23:13" AS TIME) AS time_1, CAST("89" AS YEAR) AS year
datetime_1 datetime_2 datetime_3 date_1 time_1 year 2022-06-16T16:37:23.000Z 2014-02-22T16:37:22.000Z 2022-06-16T16:37:23.000Z 2021-02-12T00:00:00.000Z 160:23:13 1989 В запросе выше для принудительного преобразования строки в дату и время была использована функция CAST . Она необходима, если сервер не ожидает временного значения и, соответственно, автоматически не преобразует строку к нужному типу. С преобразованием типов мы более подробно познакомимся в статье «Функции преобразования типов, CAST».
Если необходимо получить временные данные из строки, которая не соответствует ни одному формату, который принимает функция CAST , то можно использовать встроенную функцию STR_TO_DATE , которая принимает произвольную строку, содержащую дату, и формат, описывающий её.
MySQLSELECT STR_TO_DATE('November 13, 1998', '%M %d, %Y') AS date;
date 1998-11-13T00:00:00.000Z Более подробное описание функции STR_TO_DATE и её аргументов можно посмотреть в справочнике.
Для генерации же текущей даты или времени нет необходимости создавать строку для последующего её преобразования в дату, потому что есть встроенные функции для получения данных значений: CURDATE , CURTIME и NOW .
MySQLSELECT CURDATE(), CURTIME(), NOW();
Иногда необходимо получить не всю дату, а только её конкретную часть, например, месяц или год.
Для этого в SQL есть следующие функции:
Функция Описание YEAR Возвращает год для указанной даты MONTH Возвращает числовое значение месяца года (от 1 до 12) даты DAY Возвращает порядковый номер дня в месяце (от 1 до 31) HOUR Возвращает значение часа (от 0 до 23) для времени MINUTE Возвращает значение минут (от 0 до 59) для времени В MySQL есть очень похожие друг на друга типы данных: DATETIME и TIMESTAMP . Они оба направлены на хранение даты и времени, но имеют ряд отличий, определяющих их целевое использование.
Критерий DATETIME TIMESTAMP Диапазон от 1000-01-01 00:00:00
до 9999-12-31 23:59:59от 1970-01-01 00:00:00
до 2038-01-19 03:14:07Часовой пояс Не учитывается
Отображается в таком виде, в котором дата была установленаУчитывается
При выборках отображается с учётом текущего часового пояса сервера БДТак как люди во всем мире хотят, чтобы полдень примерно соответствовал максимальному подъёму Солнца, то никогда не было задачи использовать универсальное время и мир был разделён на 24 часовых пояса.
В качестве точки отсчёта времени используется UTC (Coordinated Universal Time). Все остальные часовые пояса можно описать количеством часов сдвига от UTC. Для примера, часовой пояс Москвы может быть описан как UTC+3.
Часовой пояс является одной из настроек сервера баз данных и может задаваться:
- глобально
- для текущего пользователя
- для текущей пользовательской сессии
MySQLSET GLOBAL time_zone = '+03:00'; // глобально SET time_zone = '+03:00'; // для текущего пользователя SET @@session.time_zone = '+03:00'; // для текущей пользовательской сессии
Соответственно, при изменении временной зоны все значения с типом TIMESTAMP будут выводиться с учётом текущей активной временной зоны.
Хочется отдельно остановиться на наиболее популярных задачах, связанных с временным типом данных, на которых часто совершаются ошибки.
При постановке задачи найти возраст человека по дате его рождения часто возникает соблазн вычислить разницу текущего года и года рождения человека:
MySQLSELECT YEAR(NOW()) - YEAR('2003-07-03 14:10:26');
Проблема такого подхода в том, что он не учитывает был ли день рождения у данного человека в этом году или ещё нет. То есть, если на момент запроса уже наступило 3-е июля (07-03), то человек отпраздновал свой день рождения и ему уже 20 лет, иначе ему по-прежнему 19 года. Разница функций YEAR тут будет бесполезна — в обоих случаях она даст 20 лет.
Если определить возраст через разницу годов — неработающий вариант, то может возникнуть желание найти возраст через разницу дней между двумя датами, затем поделить эту разницу на количество дней в году и округлить вниз:
MySQLSELECT FLOOR(DATEDIFF(NOW(), '2003-07-03 14:10:26') / 365);
И это решение будет гораздо точнее предыдущего. Но оно не будет абсолютно точным из-за наличия високосных годов, когда в году 366 дней. Хотя погрешность в вычислении возраста для 1 человека из-за наличия високосного года достаточно низкая, в вычислениях на определение, скажем, среднего возраста среди определённого списка людей, погрешность может накапливаться и исказить реальные значения.
И как же тогда корректно определять возраст? Для этого есть готовая встроенная функция — TIMESTAMPDIFF , которая первым аргументом принимает единицу измерения, в которой нужно вернуть разницу между двумя временными значениями.
MySQLTIMESTAMPDIFF(YEAR, '2003-07-03 14:10:26', NOW());
SQL функции даты и времени
Приветствую Вас, уважаемые читатели блога webcodius.ru. В базе данных часто требуется хранить различные данные связанные с датой и временем. Это может быть дата добавления информации, дата регистрации пользователя, время последней автоизации и другие данные. В языке SQL есть множество функций связанных с датой и временем, сегодня их и рассмотрим.
Все ниже рассмотренные функции работают с календарными типами данных.
Получение текущей даты и времени.
Чтобы получить текущую дату и время используется функция NOW ().
SELECT NOW ()
Результат: 2015-09-25 14:42:53Для получения только текущей даты есть функция CURDATE ().
SELECT CURDATE ()
Результат: 2015-09-25И функция CURTIME (), которая возвращает только текущее время:
SELECT CURTIME ()
Результат: 14:42:53Функции CURDATE () и NOW () удобно использовать для добавления в базу данных записей, для которых требуется хранить дату добавления. Например, при добавлении статьи на сайт хорошо бы хранить ее дату публикации. Тогда запрос на добавление статьи в базу будет примерно таким:
INSERT INTO posts (id_post, text_post, date_publication) VALUES (1, 'текст статьи', NOW ());
Прибавление и вычитание дат и времени
Функция ADDDATE (date, INTERVAL value) прибавляет к дате date значение value и возвращает полученное значение. В качестве value могут выступать следующие значения:
- SECOND — секунды
- MINUTE — минуты
- HOUR — часы
- DAY — дни
- WEEK — недели
- MONTH — месяцы
- QUARTER — кварталы
- YEAR — годы
а также их комбинации:
- MINUTE_SECOND — минуты и секунды
- HOUR_SECONDчасы — минуты и секунды
- HOUR_MINUTE — часы и минуты
- DAY_SECOND — дни, часы, минуты и секунды
- DAY_MINUTE — дни, часы и минуты
- DAY_HOUR — дни и часы
- YEAR_MONTH — года и месяцы.
SELECT ADDDATE ('2015-09-28 10:30:20', INTERVAL 1 DAY)
Результат: 2015-09-29 10:30:20SELECT ADDDATE ('2015-09-28 10:30:20', INTERVAL '3 1:20' DAY_MINUTE)
Результат: 2015-10-01 11:50:20Функция SUBDATE (date, INTERVAL value) производит вычитание значения value из даты date . Пример:
SELECT SUBDATE ('2015-09-28 10:30:20', INTERVAL 20 HOUR)
Результат: 2015-09-27 14:30:20Функция PERIOD_ADD (period, n) прибавляет к значению period n месяцев. Значение период должно быть представлено в формате YYYYMM (например сентябрь 2015 года будет 201509). Пример:
SELECT PERIOD_ADD (201509, 4)
Результат: 201601Функция TIMESTAMPADD (interval, n, date) прибавляет к дате date временной интервал n , значения которого задаются параметром interval . Возможные значения параметра interval:
- FRAC_SECOND — микросекунды
- SECOND — секунды
- MINUTE — минуты
- HOUR — часы
- DAY — дни
- WEEK — недели
- MONTH — месяцы
- QUARTER — кварталы
- YEAR — годы
SELECT TIMESTAMPADD (QUARTER, 1, '2015-09-28')
Результат: 2015-12-28Функция SUBTIME (date, time) вычитает из даты date время time. Пример:
SELECT SUBTIME ('2015-09-28 10:30:20', '50:20:19')
Результат: 2015-09-26 08:10:01Вычисление интервала между датами
Функция TIMEDIFF (date1, date2) вычисляет разницу в часах, минутах и секундах между двумя датами date1 и date2 . Пример:
SELECT TIMEDIFF ('2015-09-28 10:30:20', '2015-09-29 10:30:20')
Результат: -24:10:00Функция DATEDIFF (date1, date2) вычисляет разницу в днях между двумя датами, при этом часы, минуты и секунды при указании дат игнорируются. Пример:
SELECT DATEDIFF ('2015-09-28 00:00:20', '2015-09-27 23:40:20')
Результат: 1С помощью этой функции легко определить сколько дней прошло с даты публикации статьи:
SELECT DATEDIFF (CURDATE (), date_publication) FROM posts WHERE id_post = 1
Функция PERIOD_DIFF (period1, period2) вычисляет разницу в месяцах между двумя датами. Даты должны быть представлены в формате YYYYMM . Например, узнаем сколько месяцев прошло с января 2015 по сентябрь 2015:
SELECT PERIOD_DIFF (201509, 201501)
Результат: 9Функция TIMESTAMPDIFF (interval, date1, date2) вычисляет разницу между датами date2 и date1 в единицах указанных в параметре interval . При этом interval может принимать следующие значения:
- FRAC_SECOND — микросекунды
- SECOND — секунды
- MINUTE — минуты
- HOUR — часы
- DAY — дни
- WEEK — недели
- MONTH — месяцы
- QUARTER — кварталы
- YEAR — годы
SELECT TIMESTAMPDIFF (HOUR, '2015-09-28 10:30:20', '2015-09-28 19:50:20')
Результат: 9Получение различных форматов даты и времени и другой информации
Функция DATE (datetime) возвращает дату, отсекая время. Пример:
SELECT DATE ('2015-09-28 10:30:20')
Результат: 2015-09-28Функция TIME (datetime) возвращает время, отсекая дату. Пример:
SELECT TIME ('2015-09-28 10:30:20')
Результат: 10:30:20Функция TIMESTAMP (date) возвращает полный формат со временем даты date . Пример:
TIMESTAMP ('2015-09-28')
Результат: 2015-09-28 00:00:00DAY (date) и DAYOFMONTH (date). Функции-синонимы, которые возвращают порядковый номер дня месяца. Пример:
SELECT DAY ('2015-09-28'), DAYOFMONTH ('2015-09-28')
Результат: 28 | 28Функции DAYNAME (date), DAYOFWEEK (date) и WEEKDAY (date). Первая функция возвращает название дня недели, вторая — номер дня недели (отсчет от 1 — воскресенье до 7 — суббота), третья также номер дня недели только другой отсчет(отсчет от 0 — понедельник, до 6 — воскресенье). Пример:
SELECT DAYNAME ('2015-09-28'), DAYOFWEEK ('2015-09-28'), WEEKDAY ('2015-09-28')
Результат: Monday 2 | 0Функции WEEK (date) и WEEKOFYEAR (datetime). Обе функции возвращают номер недели в году, только у первой неделя начинается с воскресенья, а у второй с понедельника. Пример:
SELECT WEEK ('2015-09-28 10:30:20'), WEEKOFYEAR ('2015-09-28 10:30:20')
Результат: 39 | 40Функция MONTH (date) возвращает числовое значение месяца (от 1 до 12), а MONTHNAME (date) название месяца. Пример:
SELECT MONTH ('2015-09-28 10:30:20'), MONTHNAME ('2015-09-28 10:30:20')
Результат: 9 | SeptemberФункция QUARTER (date) возвращает номер квартала года (от 1 до 4). Пример:
SELECT QUARTER ('2015-09-28 10:30:20')
Результат: 3Функция YEAR (date) возвращает значение года (от 1000 до 9999). Пример:
SELECT YEAR ('2015-09-28 10:30:20')
Результат: 2015Функция DAYOFYEAR (date) возвращает порядковый номер дня в году (от 1 до 366). Прмиер:
SELECT DAYOFYEAR ('2015-09-28 10:30:20')
Результат: 271Функция HOUR (datetime) возвращает значение часа (от 0 до 23). Пример:
SELECT HOUR ('2015-09-28 10:30:20')
Результат: 10Функция MINUTE (datetime) возвращает значение минут (от 0 до 59). Пример:
SELECT MINUTE ('2015-09-28 10:30:20')
Результат: 30Функция SECOND (datetime) возвращает значение секунд (от 0 до 59). Пример:
SELECT SECOND ('2015-09-28 10:30:20')
Результат: 20Функция EXTRACT (type FROM date) возвращает часть даты date определяемую параметром type . Пример:
SELECT EXTRACT (YEAR FROM '2015-09-28 10:30:20'), EXTRACT (MONTH FROM '2015-09-28 10:30:20'), EXTRACT (DAY FROM '2015-09-28 10:30:20'), EXTRACT (HOUR FROM '2015-09-28 10:30:20'), EXTRACT (MINUTE FROM '2015-09-28 10:30:20'), EXTRACT (SECOND FROM '2015-09-28 10:30:20')
Результат: 2015 | 9 | 28 | 10 | 30 | 20Взаимообратные функции TO_DAYS (date) и FROM_DAYS (n). Первая преобразует дату в количество дней, прошедших с нулевого года. Вторая, наоборот, принимает число дней, прошедших с нулевого года и преобразует их в дату. Пример:
SELECT TO_DAYS ('2015-09-28 10:30:20'), FROM_DAYS (736234)
Результат: 736234 | 2015-09-28Взаимообратные функции UNIX_TIMESTAMP (date) и FROM_UNIXTIME (n). Первая преобразует дату в количество секунд, прошедших с 1 января 1970 года. Вторая, наоборот, принимает число секунд, с 1 января 1970 года и преобразует их в дату. Пример:
SELECT UNIX_TIMESTAMP ('2015-09-28 10:30:20'), FROM_UNIXTIME (1443425420)
Результат: 1443425420 | 2015-09-28 10:30:20Взаимообратные функции TIME_TO_SEC (time) и SEC_TO_TIME (n). Первая преобразует время в количество секунд, прошедших от начала суток. Вторая, наоборот, принимает число секунд с начала суток и преобразует их во время. Пример:
SELECT TIME_TO_SEC ('10:30:20'), SEC_TO_TIME (37820)
Результат: 37820 | 10:30:20Функция MAKEDATE (year, n) принимает год year и номер дня в году n и преобразует их в дату. Пример:
SELECT MAKEDATE (2015, 271)
Результат: 2015-09-28На этом все, до новых встреч!
Date, SQL date, timestamp
— Я вспомнил, что хотел рассказать тебе немного про работу с датами.
— Так вы мне уже рассказывали, что в Java существует класс Date, с помощью которого можно работать с датой.
— Гм. Ну, с некоторого времени класс Date устарел.
Сейчас вместо него советуют использовать класс Calendar, у которого есть метод getTime(), который и возвращает текущую дату.
Вот как обычно создается объект типа Календарь:
Создание объекта календарь
Calendar cal = Calendar.getInstance();
— Когда ты вызываешь этот метод, в зависимости от настроек твоего компьютера, будет создан нужный календарь.
— Нужный? Их что – несколько?
— Ага. Более того, правильно было бы сказать – актуальный. Дело в том, что на Земле не один, а много календарей. И почти каждый из них связан с какой-нибудь религией или страной.
В зависимости от того, в какой стране ты находишься, год может быть другим.
Вот примеры самых распространённых календарей.
Класс календаря Название календаря GregorianCalendar Христианский Грегорианский календарь BuddhistCalendar Буддистский календарь JapaneseImperialCalendar Японский Императорский календарь Есть еще Китайский календарь, Исламский календарь и много других.
— Чтобы узнать текущую дату, надо написать такой код:
Как узнать текущее время
Calendar cal = Calendar.getInstance(); Date date = cal.getTime();
У класса календарь есть много методов, которые позволяют быстро получить любую информацию о дате и времени.
Calendar calendar = Calendar.getInstance(); int era = calendar.get(Calendar.ERA); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); int hour = calendar.get(Calendar.HOUR); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND);
эра год месяц день месяца день недели (пн, вт, ср,…) час минута секундаИногда действительно нужно получить только часть информации. Например, какой сегодня год, или какой день недели.
Но иногда бывает нужно просто вывести дату в нужном формате.
Например, в лог-файл или еще куда-нибудь.
Или сделать формат, который бы настраивал пользователь. Как тогда быть?
Для этого тоже есть специальные классы. И класс SimpleDateFormat отлично справляется с описанной тобой задачей:
Как привести дату к нужному формату
Calendar calendar = Calendar.getInstance(); DateFormat formatter = new SimpleDateFormat("MM-DD-YY"); String message = formatter.format(calendar.getTime());
— Ага. Я помню. Вы мне уже что-то такое объясняли про SimpleDateFormat , но я честно говоря, не очень запомнил.
Тут все очень просто. Создаешь объект типа SimpleDateFormat и передаешь в него шаблон даты, которую хочешь получить. Затем вызываешь метод format, и он приводит тебе переданную дату к нужному виду.
— Звучит интересно. Мне бы побольше подробностей.
— Будут тебе подробности. Вот какие ключевые слова в шаблоне бывают:
Ключевое слово Описание G будет заменено на эру даты (н.э. или до н.э.) y вместо этого символа будет подставлен год M заменяется на месяц w номер недели в году W порядковый номер недели в месяце D номер дня в году d день месяца F номер дня недели в месяце E день недели a AM/PM (до обеда или после) H час в 24-часовом формате (0-23) k час в 24-часовом формате (1-24) K час в 12-часовом формате (0-11) h час в 12-часовом формате (1-12) m минуты s секунды S миллисекунды z часовая зона в формате Pacific Standard Time, PST Z часовая зона в формате -0800 — Круто! Почти все, что нужно.
— Тут еще есть дополнительные нюансы с удвоением этих символов.
Если ты напишешь YY, то получишь две последние цифры года, если YYYY – то полный год из четырех цифр.
С месяцем тоже не все просто. MM – это число месяца. MMM – это трехбуквенное сокращение месяца (Jan, Feb, Mar, Apr, May,…). Если MMMM – полное название месяца.
Дни недели можно тоже вывести полностью – EEEE или только первые две буквы EE.
— Спасибо, Риша, действительно полезная штука этот SimpleDateFormat, буду знать.
— Пользуйся на здоровье. И, удачи!