Notes › Life Essays › Calculating the Chinese sexagenary cycle: zodiac years and ganzhi days

Calculating the Chinese sexagenary cycle: zodiac years and ganzhi days

At the start of this year I sent New Year cards to clients on behalf of the company. I signed them "A fortunate Bingwu horse year" and posted them in early February. One client replied politely: "Our snake year is not over yet." I assumed he had misremembered. What actually changed my habit was something else: a relative's child was born on 10 February, the grandparents insisted the child was a snake, and the commemorative wristband from the delivery room already had the horse year on it.

Then I derived the ganzhi arithmetic myself and found that neither of them had misremembered. There are simply two groups of people using different days for the year change: the first day of the first lunar month in 2026 is 17 February, and the Bingwu year counts from that day. I worked through the numbers below one modulo at a time.

Why sixty and not one hundred and twenty

The ten heavenly stems are jia, yi, bing, ding, wu, ji, geng, xin, ren and gui; the twelve earthly branches are zi, chou, yin, mao, chen, si, wu, wei, shen, you, xu and hai. Multiplying the two sets pairwise gives 120 combinations, but only 60 can occur, because a stem and a branch must share the same polarity, both yang or both yin (jia pairs only with zi, yin, chen, wu, shen and xu; yi only with chou, mao, si, wei, you and hai). I counted with two nested loops: exactly 60 share the same polarity.

The other route is the least common multiple: the stems cycle every 10 years and the branches every 12, so bringing both back to the start takes lcm(10,12)=60 steps. The sexagenary cycle is therefore not a lucky number someone picked; it follows from the periods 10 and 12. Ganzhi years repeat every 60, and the zodiac animal follows only the branches, cycling every 12. 1984 was a jiazi year, and the next jiazi is 2044.

Modulo on the year: two formulations, one result

The usual version counts from zero: stem index = (year-4) mod 10, branch index = (year-4) mod 12, with 0 mapping to jia and zi. Some references write (year-3), which counts from one, so a remainder of 0 has to be assigned to the tenth stem (gui) and the twelfth branch (hai). The two formulas give identical answers; only the counting base differs. I mixed the two index bases at first and every year came out one place off.

Gregorian year (year-4) mod 10 (year-4) mod 12 Ganzhi Zodiac Sexagenary index
190060gengziRat37
194951jichouOx26
198400jiaziRat1
202404jiachenDragon41
202515yisiSnake42
202626bingwuHorse43
202737dingweiGoat44

Two edge cases cause most of the errors. The first is a remainder of 0: for 1900, (year-4) mod 12 gives 0, index 0 is zi, and (year-4) mod 10 gives 6, index 6 is geng, so the year is gengzi. For 1984 both remainders are 0, which is exactly jiazi, the first of the sixty. The second is modulo on a negative number: JavaScript's % operator returns a negative remainder when the dividend is negative, so for years before AD 4, (year-4) turns negative first and you must write (remainder+10) and take mod 10 again to land back in 0 to 9. That step is only defensive; after 1900, (year-4) is always positive and the modulo cannot go negative.

I no longer derive specific dates by hand. I use the Ganzhi Calendar: enter a Gregorian date and it returns the year, month, day and hour pillars together with the zodiac animal, and it prints the modulo steps so I can see which step my draft got wrong.

Zodiac and ganzhi year disagree because there are two new years

The dividing day is the key. Folk custom and almanacs change the year at the first day of the first lunar month, which is Spring Festival, and the national standard GB/T 33661-2017 also counts the new year from that day. Fortune-telling and bazi change the year at the start of spring (lichun), which floats between 3 and 5 February on the Gregorian calendar. Spring Festival itself can land anywhere from late January to mid-February: in my table for 2024 to 2030 the earliest is 26 January and the latest 17 February, a spread of 22 days. So there is always a window between the two new years in which one date belongs to two different years depending on the convention.

The relative's child, born on 10 February, falls inside that window: in 2026 the start of spring comes in early February while Spring Festival waits until 17 February, so by the lichun convention the child is already in the bingwu year and a horse; by the Spring Festival convention the year is still yisi and the child is a snake. Neither is wrong. The window opens the other way too: in 2023 Spring Festival was 22 January and the start of spring did not arrive until 4 February, so someone born on 28 January is a rabbit in the guimao year by the Spring Festival convention and still a tiger in the renyin year by the lichun convention. Ten days earlier at birth, a different animal.

So I choose by purpose: New Year greetings and telling elders your animal sign follow Spring Festival; setting out the four pillars and reading the year pillar follow lichun. One approximation needs calling out: the start of spring is not always on 4 February; in 2025 it was 3 February at 22:10. Cutting everything before 4 February into the previous year works in most years, but in a year like 2025, where the solar term turns late on 3 February, anyone born between 22:10 and midnight lands in the previous year pillar, a difference of under two hours. To be exact to the day, use that year's actual lichun time and do not trust a hard-coded 4 February.

There is also a preliminary step that goes wrong more often than the formula: confirm which Gregorian date that day actually falls on. For people born across time zones, or those who only remember a lunar birth date, I fix the date before discussing ganzhi. I might check the date at the birthplace with the World Clock, or convert the date to a day number with the Timestamp Converter, so my own counting is not a day off.

Ganzhi days are a separate axis

This is easy to overlook: the year cycle is 60, the zodiac cycle is 12, months follow the solar terms, and days form an unbroken 60-day cycle that does not align with the start of a month, the new year or any festival. So there is no derivation between a person's year pillar and day pillar; the four pillars are four independently advancing sequences. The month stem starts from the year stem (the five-tiger rule), the hour stem from the day stem (the five-rat rule), and the day pillar can only be derived from an anchor date.

Because it depends on an anchor, the day count is extremely sensitive to a one-day error at the start: set the anchor wrong and the whole sequence shifts by one, while the result still looks like a legal ganzhi. What I can verify is the cycle itself: any multiple of 60 must give the same pillar. 15 October 2026 to 14 December 2026 is exactly 60 days, so both days share a day pillar; 31 January 1900 to 10 February 2024 is 45,300 days apart, and 45,300 divided by 60 gives 755 full cycles, so those two must also match.

I once mixed up the anchors myself; the correct values are here: 1 January 1900 was a jiaxu day, number 11 of the sixty. 31 January 1900 was not jiaxu but a jiachen day, number 41, which the 45,300-day pair above confirms at both ends. Two more I checked one by one: 1 October 1949 was a jiazi day (number 1), and 15 October 2026 was a renxu day (number 59). The general formula is easiest with the Julian day number: (JDN+49) mod 60, where a remainder of 0 is jiazi. Those three points should leave remainders of 10, 0 and 58; being off by 1 shifts the whole sequence one place.

Q: Is the zodiac year counted from Spring Festival or from the start of spring?

It depends where you use it. The folk custom of passing through your zodiac year starts on the first day of the first lunar month; the year pillar in fortune-telling and bazi starts at lichun. The two differ only in the window from late January to mid-February; on other dates both give the same result.

Q: Why do online ganzhi days differ from what the almanac prints?

Because the anchor and the day boundary differ. The cycle itself is fixed, but the starting date each source uses, and which day it assigns the zi hour to, need not match; a difference of a day or two shows up as a ganzhi one or two places apart. When checking, look at the anchor or example date it gives, not just the result.

Q: There are twelve zodiac animals and sixty ganzhi years. How do they correspond?

The zodiac follows only the earthly branches, cycling every 12 years; a ganzhi year aligns stem and branch together, so it takes 60 years to cycle. One animal therefore corresponds to five ganzhi years: 1984, 1996, 2008, 2020 and 2032 are all rat years, respectively jiazi, bingzi, wuzi, gengzi and renzi.

Q: Can I use (year-4) mod 10 for days and months too?

No. The year pillar can use a linear offset on the year, months have to be cut at solar terms, and days can only use a modulo on a day number. The three axes start at different points, so one formula for all of them will always be wrong.

I ended up with two versions of the card signature: for domestic clients, the animal sign plus the Gregorian year; for partners who care about choosing dates, the ganzhi by the lichun convention. Whichever day the person uses to change the year is the day I calculate from.

📎 Related articles

A photo rotated 90° lies flat again on another device: how the EXIF flag and a real rotation split the work 2026-10-22 Same Day Every Month Versus Every 28 Days, 29 Days Apart Within a Year 2026-10-22 Shuffling with a random sort comparator is already unfair 2026-10-21 Two gallons, two horsepower ratings, two byte prefixes: ask which one first 2026-10-21 Born on 29 February: which day you turn 18 in a common year 2026-10-21