Глиф Учебники

Даты в SQL — текущая дата, прибавить день, разница

Справочник · SQL · 2 минуты чтения

ЗадачаSQLiteMySQLPostgreSQL
Сегодняdate('now', 'localtime')CURDATE()CURRENT_DATE
Сейчасdatetime('now', 'localtime')NOW()now()
Плюс 7 днейdate(d, '+7 days')DATE_ADD(d, INTERVAL 7 DAY)d + INTERVAL '7 days'
Дней между датамиjulianday(b) - julianday(a)DATEDIFF(b, a)b - a (для date)
Годstrftime('%Y', d)YEAR(d)EXTRACT(YEAR FROM d)
Вид 15.09.2026strftime('%d.%m.%Y', d)DATE_FORMAT(d, '%d.%m.%Y')to_char(d, 'DD.MM.YYYY')

Как хранить даты в SQLite

Отдельного типа даты в SQLite нет. Даты хранят текстом в виде ГГГГ-ММ-ДД или ГГГГ-ММ-ДД ЧЧ:ММ:СС: '2026-09-15', '2026-09-15 14:30:00'. Все функции дат SQLite понимают именно такой вид, а ещё такие строки правильно сравниваются и сортируются как обычный текст.

Привычный вид 15.09.2026 для хранения не годится. Функции его не понимают (date('15.09.2026') вернёт NULL), а сравнение ломается: '05.09.2026' > '01.10.2026' — верно, хотя 5 сентября раньше 1 октября. Переводите дату в такой вид только при выводе.

В MySQL и PostgreSQL для дат есть свои типы — DATE, DATETIME, timestamp; значения в запросах пишут в том же виде '2026-09-15'.

Текущая дата и часовой пояс

SQL
SELECT date('now'), datetime('now'), datetime('now', 'localtime');

date('now') и CURRENT_TIMESTAMP в SQLite дают время по UTC — для Беларуси это на 3 часа меньше местного. Местное время даёт добавка 'localtime'. Хранить время в UTC и переводить при показе — хорошая привычка: так нет путаницы с часовыми поясами.

Прибавить и отнять

SQL
SELECT date('2026-09-01', '+7 days')                              AS week_later,
       date('2026-09-01', '-1 month')                             AS month_ago,
       date('2026-09-15', 'start of month')                       AS first_day,
       date('2026-09-15', 'start of month', '+1 month', '-1 day') AS last_day;
week_latermonth_agofirst_daylast_day
2026-09-082026-08-012026-09-012026-09-30

Добавки идут по порядку: «начало месяца», «плюс месяц», «минус день» — получается последний день месяца. Есть и '+3 hours', '+30 minutes', '+1 year'.

Осторожно с месяцами в SQLite: date('2026-01-31', '+1 month') даст 2026-03-03 — несуществующее 31 февраля перенеслось на март. MySQL и PostgreSQL в таком случае берут последний день месяца — 28 февраля.

Разница между датами

SQL
SELECT julianday('2026-09-10') - julianday('2026-09-01') AS days;

Ответ — 9.0. julianday превращает дату в число дней, и разность — это дни, с дробной частью, если есть время. Целое число дней — CAST(… AS INTEGER).

Части даты и вывод

strftime('%Y', d) — год, '%m' — месяц, '%d' — день, '%H:%M' — часы и минуты. Вид для людей:

SQL
SELECT strftime('%d.%m.%Y %H:%M', '2026-09-15 14:30:00') AS shown;
shown
15.09.2026 14:30

strftime возвращает текст: условие strftime('%Y', d) = 2026 не сработает, нужно = '2026'.

Строки за месяц

Таблица заказов с временем. В учебной базе курса таблица orders уже есть, поэтому этот пример запускайте в отдельной базе, например sqlite3 dates.db:

SQL
CREATE TABLE orders (id INTEGER PRIMARY KEY, created TEXT);
INSERT INTO orders (created) VALUES
    ('2026-08-31 23:10:00'), ('2026-09-01 09:00:00'),
    ('2026-09-30 18:45:00'), ('2026-10-01 00:05:00');

Частая ошибка — BETWEEN с датой без времени:

SQL
SELECT id FROM orders WHERE created BETWEEN '2026-09-01' AND '2026-09-30';

Ответ — только заказ 2: строка '2026-09-30 18:45:00' больше, чем '2026-09-30', и заказ 3 потерялся. Правильно — «от начала месяца и раньше начала следующего»:

SQL
SELECT id, created FROM orders
WHERE created >= '2026-09-01' AND created < '2026-10-01';
idcreated
22026-09-01 09:00:00
32026-09-30 18:45:00

Так же это работает в MySQL и PostgreSQL. Итоги по месяцам в SQLite — группировка по strftime('%Y-%m', created):

SQL
SELECT strftime('%Y-%m', created) AS month, COUNT(*) AS orders
FROM orders
GROUP BY month
ORDER BY month;
monthorders
2026-081
2026-092
2026-101

В MySQL то же даёт DATE_FORMAT(created, '%Y-%m'), в PostgreSQL — date_trunc('month', created).