Даты в расчётах: 29 февраля и ловушки Excel
Почему даты ломают расчёты: високосный год и 29 февраля, документированная ошибка Excel с 1900 годом, формат даты и часовой пояс, сложение месяцев, подсчёт возраста и срока. Что я проверяю в расчётах по дате рождения и как сверка 756 из 756 нашла лишний день в чужой таблице.
Коротко (TL;DR)
- Даты ломают расчёты в пяти местах: високосный год, формат записи, часовой пояс, сложение месяцев и разный счёт возраста. У каждого места есть простое правило, которое надо выбрать и записать.
- Excel считает 1900 год високосным ради совместимости с Lotus 1-2-3. Это подтверждает документация Microsoft: влияет на дни недели до 1 марта 1900 года, остальные високосные годы Excel считает верно.
- Дату рождения храните как год, месяц и день в формате ГГГГ-ММ-ДД, без времени и пояса. Возраст считайте сравнением трёх чисел.
- Расчёт по дате рождения проверяйте на эталоне: готовом примере автора. В моём проекте сверка дала 756 совпадений из 756.
Сделаю под ключ: разберу задачу, назову срок и цену. Чтобы начать, напишите в Telegram одной фразой.
Автоматизация бизнесаДаты в расчётах ломаются, потому что календарь неровный: в феврале то 28, то 29 дней, в месяцах разное число дней, а у одного и того же момента времени в разных странах разная дата. Программа или таблица, где это не учтено, молча выдаёт неверный возраст, срок или день недели. Ниже разбираю ловушки, начиная с 29 февраля, и то, как я их закрываю.
29 февраля и високосный год
Правило високосного года знают не все. По описанию Microsoft год високосный, если он делится на 4, но год, который делится на 100, високосный, только если делится ещё и на 400. Поэтому 2000 год високосный, а 1900 и 2100 нет. Частая ошибка в самописных формулах: проверить только деление на 4. Она не видна до 2100 года, и потому живёт в программах десятилетиями.
Второе место, где 29 февраля ломает расчёты: что считать днём рождения человека, родившегося 29 февраля, в невисокосный год. Универсального ответа нет, есть два варианта: 28 февраля или 1 марта. Мой совет простой: выбрать один, записать в ТЗ и держать в одном модуле, а не в трёх таблицах.
Третье, сложение месяцев. Если прибавить один месяц к 31 января, получить нужно конец февраля, но программа может выдать начало марта. В документации MDN по Date написано, что при выходе значения за пределы диапазона оно переносится на старший разряд. В Node.js у меня 31 января 2026 плюс один месяц превратилось в 3 марта 2026. Для сроков договоров и подписок это разница в три дня, и правило «последний день месяца, если такого числа нет» нужно задать самому.
Год 1900 в Excel: ошибка совместимости
В Excel есть известная странность, и она документирована. На странице Microsoft Learn прямо сказано, что Excel ошибочно считает 1900 год високосным. Причина: Lotus 1-2-3 принимал 1900 год за високосный, а Multiplan и Excel сохранили это, чтобы использовать ту же систему порядковых дат и упростить перенос таблиц. Microsoft пишет, что исправить технически можно, но недостатки перевешивают, так как почти все даты в существующих файлах сдвинулись бы на день.
Практический эффект по той же странице один: функция WEEKDAY возвращает неверные значения для дат до 1 марта 1900 года. Остальные високосные годы Excel обрабатывает правильно, включая 2100. Для обычного бизнеса это редкость, потому что люди с датами до 1900 года в таблицах не работают. Но знать о ней полезно: если вы переносите расчёт из Excel в программу, сроки и дни недели старых дат лучше сверить.
Отдельно скажу про случай, который к этой ошибке не относится. Мне попался Excel-файл, где у февраля стояло ровно 29 дней в любом году. Календарь на 2026 год в нём содержал 29 февраля, которого не существует. Это ошибка в самих формулах файла, а не особенность Excel. Об этом ниже в разделе про расчёты по дате рождения.
Формат даты и часовой пояс
Запись 03.04.2026 в одной стране читается как 3 апреля, в другой как 4 марта. Пока таблицу ведёт один человек, этого не видно. Когда данные идут из формы, из мессенджера и из разных файлов, получаются перепутанные день и месяц, и они не вызывают ошибок, поэтому их никто не замечает. Надёжный способ: хранить дату как текст ГГГГ-ММ-ДД, а показывать человеку в привычном виде на выходе.
Часовой пояс добавляет вторую проблему. По документации MDN, если пояс не указан, строка только с датой читается как UTC, а строка с датой и временем как местное время. Одна и та же дата рождения, прочитанная двумя способами, в какой-то части мира сдвинется на соседний день. Это типичная картина, когда сервер, пользователь и разработчик живут в разных часовых поясах. Я работаю из Дубая, а мои клиенты в России, поэтому за поясами приходится следить всегда.
Ещё нюанс: смещение пояса зависит не только от страны, но и от самой даты. Документация MDN по getTimezoneOffset отмечает, что смещение в регионе с переводом часов меняется по ходу года. А в старых датах прибавляются исторические изменения поясов. Поэтому для даты рождения без времени пояс вообще не нужен, и лучше его не подтягивать: день, месяц и год хранятся тремя числами.
Как считать возраст и срок
Возраст считают не делением числа дней на 365,25, а сравнением чисел. Из года сегодняшней даты вычитают год рождения, и если день рождения в этом году ещё не наступил, вычитают ещё один:
function age(b, t) { // b и t: { y, m, d }
let a = t.y - b.y;
if (t.m < b.m || (t.m === b.m && t.d < b.d)) a--;
return a;
}
// родился 29.02.2000: 28.02.2026 это 25, 01.03.2026 это 26
console.log(age({y:2000,m:2,d:29},{y:2026,m:2,d:28}),
age({y:2000,m:2,d:29},{y:2026,m:3,d:1}));
Здесь день рождения в невисокосный год приходится на 1 марта, и это выбор. Если по вашим правилам надо 28 февраля, меняется одно условие.
Разницу между датами в днях считают через полночь по UTC: обе даты приводят к UTC-полуночи и делят разницу на 86 400 000 миллисекунд. Так смещение пояса и перевод часов не прибавляют лишних часов. Срок в рабочих днях требует отдельного списка праздников и переносов, и этот список я держу данными, а не зашитым в код, потому что он может меняться от года к году.
Расчёты по дате рождения для эксперта
Отдельный класс задач: эксперт продаёт личный календарь или разбор по дате рождения, а расчёт живёт в таблице. Нумерологию, астрологию или другую методику я не оцениваю, для меня это расчёт с понятными формулами и аудиторией эксперта. Моя ответственность одна: чтобы цифры совпадали с авторской методикой и с реальным календарём.
В проекте личного календаря по дате рождения преподавательница нумерологии выдавала студентам копии Excel-файла. Я перенёс её формулы в код и сверил расчёт с её готовым PDF: совпали 756 чисел из 756. Попутно обнаружилось, что в её файле у февраля всегда 29 дней, поэтому календарь на 2026 год содержит несуществующее 29 февраля. В коде календарь настоящий: високосные годы и дни недели считаются сами. Честный статус: это предложение, расчётный модуль готов и сверен, бот и мини-приложение не написаны, решение за заказчицей.
Во втором проекте, персональных разборах по дате рождения, дат было больше, и ошибки вылезали на редких значениях. Кин Майя для дат до 1984 года считался неверно: високосные годы учитывались только с 1984 года. Я исправил это и расширил расчёт високосных лет до 1901 года. Начало года у разных систем плавает: по зурхаю он начинается с Сагаалгана, по Ба-цзы с Личуня, и родившийся в конце января часто попадает в прошлый год. Пришлось учесть историю часовых поясов, включая летнее время в СССР: ошибка на час меняет столп месяца. Если времени рождения нет, расчёт прогоняется по часам суток, и в разборе пишется, что меняется. Подробнее про такие конвейеры: автоматизация персональных разборов и сервис разборов для астролога.
Как я это делаю
- Прошу у заказчика эталон: готовый пример с рассчитанными значениями. Пока каждое число эталона не совпало с кодом, дальше не иду.
- Даты хранятся как год, месяц и день отдельными числами или как ГГГГ-ММ-ДД. Время и пояс добавляются, только если они нужны методике.
- Високосный год считается по полному правилу про 4, 100 и 400, а календарь строится из настоящих дат.
- Спорные правила записываются в ТЗ одной фразой: день рождения 29 февраля в обычный год, прибавление месяца к 31-му числу, начало года.
- Автотесты гоняют крайние даты: 28, 29 февраля и 1 марта, 31 декабря и 1 января, 1900, 2000 и 2100 годы, границы месяцев.
Если расчёт сейчас живёт в таблице и вы не уверены в нём, я могу его проверить: открыть формулы, прогнать крайние даты и показать, где расходится с реальностью.
Сколько это стоит
- Технический аудит расчётов и формул от 50 000 ₽, от 1 недели.
- Автоматизация процессов и документов (расчёт, сроки, PDF) от 60 000 ₽, от 2 недель.
- Бот для бизнеса, где пользователь вводит дату и получает результат, от 80 000 ₽, от 2 недель.
- Небольшая правка расчёта: разработка по часам от 3 000 ₽/час.
Цена зависит от числа формул, наличия эталона и от формата выдачи. Об этом на странице автоматизации бизнеса.
Частые вопросы
Исправили ли в Excel ошибку с 1900 годом?
По странице Microsoft Learn, на которую я ссылаюсь выше, нет: компания сочла, что недостатки исправления перевешивают, и оставила поведение ради совместимости. Проверьте актуальную версию статьи, если вам важна дата.
Как хранить дату рождения в базе?
Как дату без времени или как текст ГГГГ-ММ-ДД. Время и часовой пояс для даты рождения добавлять не нужно, они только создают сдвиги на соседний день.
Что делать с человеком, родившимся 29 февраля?
Выберите правило для невисокосных лет, 28 февраля или 1 марта, запишите его и применяйте везде одинаково. Выбор зависит от ваших договорённостей, а программа должна лишь выполнять его без исключений.
Можно ли проверить расчёт по дате рождения без автора методики?
Корректность формул без автора проверить нельзя, а вот совпадение кода с его таблицей и календарём можно. Для этого и нужен эталон.
Коротко о главном
С датами работает один принцип: выбрать правила для спорных случаев, записать их и проверить на крайних датах. Високосный год считается по правилу про 4, 100 и 400, дата рождения хранится тремя числами, возраст считается сравнением, а Excel с 1900 годом помнит о совместимости с Lotus 1-2-3.
Если ваш расчёт по датам живёт в таблице и вы хотите проверить его или перенести в бота, напишите мне в Telegram с кодовым словом «ДАТА»: посмотрю формулы и скажу, что и за сколько стоит исправить.
Расчёты по датам: проверка таблицы и перенос в бота
Напишите одной фразой, что нужно. Отвечу, что подойдёт, сколько займёт и сколько стоит. Сообщение уже подготовлено.
- Проверка формул на крайних датах: 29 февраля, 1900, 2100
- Сверка расчёта с вашим эталоном
- PDF и слайды по дате рождения
- Бот: ввёл дату, получил результат
Разборы, кейсы и практика — без воды. Выходит регулярно, читать 3–5 минут.


