1. Check which weekday the year starts
2. Check if this year is a leap year.
If the year starts on the same weekday as another year and the leap-yeariness is the same, the year is the same.
With this info it's really easy to use your favorite date library to check which years match, but you can also do that manually.
Each year starts on the next weekday that the previous year did. (2019-01-01 was a Tuesday, 2020-01-01 will be a Wednesday) except when that previous year was a leap year. In that case one day is skipped.
Edit:ninja'd by jcranmer
More specifically, there are 14 possible calendars. The leap year cycle is 4 days (excluding the 100 year skips), and the weekday cycle is 7 days, so the leap year×weekday cycle is 28 years. So the starting weekdays are on a 28-year cycle, but you have to slip your resulting calculation by the number of centuries from the beginning of the 400-year cycle (i.e., integer division of year by 100). You'll reuse a leap year calendar in 28 years (40 years, if it crosses a round-hundred year), and you'll reuse a non-leap year calendar in 6 or 11 years (12 or 6 years, if it cross a round-hundred year).
The easiest way to code it is to just precompute the year % 400 table and report the results.
If you are interested, Chrono [1] internally uses the exact table. Constants there refer to dominical letters [2].
[1] https://github.com/chronotope/chrono/blob/a4488007272569f752...
I think you mean “The leap year cycle is 4 days (excluding the 100 year skips, except every fourth 100 years when they don’t),” eg how 2000 was a leap year despite this individual rule.
(I know it’s accounted for elsewhere in the modulo logic, but you shouldn’t resist the impulse to point out just how crazy it all is!)