Разработка 8 мин чтения

Даты в расчётах: 29 февраля и ловушки Excel

Почему даты ломают расчёты: високосный год и 29 февраля, документированная ошибка Excel с 1900 годом, формат даты и часовой пояс, сложение месяцев, подсчёт возраста и срока. Что я проверяю в расчётах по дате рождения и как сверка 756 из 756 нашла лишний день в чужой таблице.

даты в расчётахExcelвисокосный годдата рождениячасовой пояс2026

Коротко (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 года. Начало года у разных систем плавает: по зурхаю он начинается с Сагаалгана, по Ба-цзы с Личуня, и родившийся в конце января часто попадает в прошлый год. Пришлось учесть историю часовых поясов, включая летнее время в СССР: ошибка на час меняет столп месяца. Если времени рождения нет, расчёт прогоняется по часам суток, и в разборе пишется, что меняется. Подробнее про такие конвейеры: автоматизация персональных разборов и сервис разборов для астролога.

Как я это делаю

  1. Прошу у заказчика эталон: готовый пример с рассчитанными значениями. Пока каждое число эталона не совпало с кодом, дальше не иду.
  2. Даты хранятся как год, месяц и день отдельными числами или как ГГГГ-ММ-ДД. Время и пояс добавляются, только если они нужны методике.
  3. Високосный год считается по полному правилу про 4, 100 и 400, а календарь строится из настоящих дат.
  4. Спорные правила записываются в ТЗ одной фразой: день рождения 29 февраля в обычный год, прибавление месяца к 31-му числу, начало года.
  5. Автотесты гоняют крайние даты: 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 минут.

Готовые решения под ключTurnkey solutionsSoluciones llave en mano交钥匙解决方案Түлхүүр гардуулах шийдэл 451 готовых IT-решений для бизнеса451 ready-made IT solutions for business451 soluciones IT listas para empresas451 个面向企业的现成 IT 解决方案Бизнест зориулсан 451 бэлэн IT шийдэл Автоматизация, боты, AI, 152-ФЗ и платформы · бесплатная консультацияAutomation, bots, AI, data privacy and platforms · free consultationAutomatización, bots, IA, privacidad de datos y plataformas · consulta gratis自动化、机器人、AI、数据合规与平台 · 免费咨询Автоматжуулалт, бот, AI, өгөгдлийн хамгаалалт ба платформ · үнэгүй зөвлөгөө Смотреть каталогView catalogVer catálogo查看目录Каталог үзэх