Писал как-то на перле валидатор дат и додумался до формулы, вычисляющей число дней в месяце — она заказчику не пригодилась, и была выкинута из кода ради сомнительной простоты, так что буду думать эту мысль ещё раз.
Итак, в языках с си-подобным синтаксисом (хотя подойдёт и для питона) определить, сколько же дней в месяце, можно по формуле
days = 30 + (month + 4) * 13 / 12 % 2
где month
— номер месяца начиная с 1.
Работает для всех месяцев кроме февраля. Например, перловый однострочник
perl -e 'printf "%2d → %d\n", $_, 30 + ($_ + 4) * 13 / 12 % 2 for 1 .. 12'
выведет
1 → 31
2 → 30
3 → 31
4 → 30
5 → 31
6 → 30
7 → 31
8 → 31
9 → 30
10 → 31
11 → 30
12 → 31
С февралём ситуация чуть более сложная, потому что число дней в нём зависит от номера года: в григорианском календаре високосным годом является такой, который делится на 4, но не на 100, хотя если при этом делится на 400 — всё равно високосный. Например, 1900 год — обычный, а 2000 — високосный, как и 2004.
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
можно вообще переписать как
!!(!(year % 4) && ((year % 100) || !(year % 400)))
однако такой вариант хуже — хоть и компактнее, но менее понятен.
Проверим (в перле «из коробки» нет булевых типов, поэтому выводятся нули и единицы)
1600 → 1
1700 → 0
1799 → 0
1800 → 0
1899 → 0
1900 → 0
1901 → 0
1944 → 1
1988 → 1
1999 → 0
2000 → 1
2001 → 0
2004 → 1
Осталось объединить всё в одну формулу