Даты в SQL — текущая дата, прибавить день, разница
| Задача | SQLite | MySQL | PostgreSQL |
|---|---|---|---|
| Сегодня | 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.2026 | strftime('%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'.
Текущая дата и часовой пояс
SELECT date('now'), datetime('now'), datetime('now', 'localtime');date('now') и CURRENT_TIMESTAMP в SQLite дают время по UTC — для Беларуси это на 3 часа меньше местного. Местное время даёт добавка 'localtime'. Хранить время в UTC и переводить при показе — хорошая привычка: так нет путаницы с часовыми поясами.
Прибавить и отнять
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_later | month_ago | first_day | last_day |
|---|---|---|---|
| 2026-09-08 | 2026-08-01 | 2026-09-01 | 2026-09-30 |
Добавки идут по порядку: «начало месяца», «плюс месяц», «минус день» — получается последний день месяца. Есть и '+3 hours', '+30 minutes', '+1 year'.
Осторожно с месяцами в SQLite: date('2026-01-31', '+1 month') даст 2026-03-03 — несуществующее 31 февраля перенеслось на март. MySQL и PostgreSQL в таком случае берут последний день месяца — 28 февраля.
Разница между датами
SELECT julianday('2026-09-10') - julianday('2026-09-01') AS days;Ответ — 9.0. julianday превращает дату в число дней, и разность — это дни, с дробной частью, если есть время. Целое число дней — CAST(… AS INTEGER).
Части даты и вывод
strftime('%Y', d) — год, '%m' — месяц, '%d' — день, '%H:%M' — часы и минуты. Вид для людей:
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:
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 с датой без времени:
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 потерялся. Правильно — «от начала месяца и раньше начала следующего»:
SELECT id, created FROM orders
WHERE created >= '2026-09-01' AND created < '2026-10-01';| id | created |
|---|---|
| 2 | 2026-09-01 09:00:00 |
| 3 | 2026-09-30 18:45:00 |
Так же это работает в MySQL и PostgreSQL. Итоги по месяцам в SQLite — группировка по strftime('%Y-%m', created):
SELECT strftime('%Y-%m', created) AS month, COUNT(*) AS orders
FROM orders
GROUP BY month
ORDER BY month;| month | orders |
|---|---|
| 2026-08 | 1 |
| 2026-09 | 2 |
| 2026-10 | 1 |
В MySQL то же даёт DATE_FORMAT(created, '%Y-%m'), в PostgreSQL — date_trunc('month', created).