A leap year inequality
March 15, 2026 at 6:22 PM by Dr. Drang
I’ve been working my way through the fourth edition of Reingold and Dershowitz’s Calendrical Calculations, and I want to talk about something I learned.

It’s a simple inequality that initially appears in the first chapter of the book and gets used several times thereafter. Here it is:
It’s first presented as a way to figure out how leap years are distributed. In some calendars—not the Gregorian—there’s a repeating cycle of years in which years are leap years. If the leap years are distributed as evenly as possible, then the years in which satisfies the inequality are the leap years. The is a sort of offset that determines the position within the cycle associated with Year 0, and the operator represents modulo division. In Python, that’s the % operator.
It’s helpful to look at examples. Let’s say we have a 7-year cycle with 2 leap years and 5 normal years in each cycle. The leap years have to be either 3 or 4 years apart. Here’s an example showing three cycles:
1 1 1 1 1 1 1 1 1 1 2 2
Year 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Type N N N L N N L N N N L N N L N N N L N N L
For this, , , and . You can plug the values into the inequality to show that it’s satisfied for years 4, 7, 11, 14, 18, 21, and so on.
Here’s a similar example. The only difference is the offset. In this case, , and the leap years are years 2, 5, 9, 12, 16, 19, and so on.
1 1 1 1 1 1 1 1 1 1 2 2
Year 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Type N L N N L N N N L N N L N N N L N N L N N
A practical example of this formula is with the Hebrew calendar. It has a 19-year cycle () with 7 leap years (), and the offset is 11 years (). The current year is 5786, for which
so this is not a leap year. But for next year,
so it is a leap year and will have 13 months instead of 12. You can confirm this on any number of websites; the key is to note that 5787 has both an Adar I and an Adar II.
The Gregorian calendar has a 400-year cycle with 97 leap years, but those leap years are not distributed as evenly as possible, so the formula can’t be used. If it had been used, we’d have leap years typically every fourth year but occasionally every fifth year. Pope Gregory and his people must’ve thought that would be too tricky to deal with.
Surprisingly (to me, anyway), Reingold and Dershowitz do use this formula with the Gregorian calendar, but they use it with months instead of years. Think of the months in the Gregorian calendar as being either short or long. In a year, there are 5 short months and 7 long months, and they’re distributed like this:
1 1 1
1 2 3 4 5 6 7 8 9 0 1 2
Month J F M A M J J A S O N D
Length L S L S L S L L S L S L
The positions of the long months correspond to our inequality with , , and . Plug in those values, and you’ll see that the long months are 1, 3, 5, 7, 8, 10, and 12.
To calculate the day number within a year, it’s usually easiest to calculate the number of days in the preceding months and then add the day number within the current month. Today is March 15, so it’s Day of the year.
Instead of looping through the lengths of the preceding months, R&D use a formula based on our inequality to count the number of long months before the current month. That formula is
where the brackets without tops represent the floor function, i.e., the integer equal to or just below what’s inside the brackets.
Plugging in our values for , , and and doing some algebra, we get
This is the number of long months in the year before the current month .
If February had 30 days, the number of days in the months before the current month would be
So to get the (Gregorian) day of the year, R&D calculate the day number as if February had 30 days and then subtract (if necessary) to account for February’s deficiency. In Python, the code looks like this:
python:
def day_of_year(year, month, day):
year_day = (367 * month - 362) // 12 + day
if month <= 2:
return year_day
elif leap_year(year):
return year_day - 1
else:
return year_day - 2
where I’m assuming we already have a Boolean function leap_year to determine whether it’s a leap year or not. That’s not necessarily the most obvious code in the world, but it makes sense if you’ve gone through the derivation.
One last thing. Reingold is the co-author of a paper in which our inequality is connected to Euclid’s algorithm for calculating the greatest common divisor and Bresenham’s algorithm for plotting lines on bitmaps. Which is pretty cool.