杂记 › 生活随笔 › 天干地支纪年怎么算?生肖与干支日的对应

天干地支纪年怎么算?生肖与干支日的对应

今年年初替公司给客户寄新年贺卡,落款我写了"丙午马年大吉",寄出的日子还在 2 月上旬。一位客户回得很客气:"我们这边蛇年还没过完呢。"我一度以为是他记错。真正让我改习惯的是另一件事:亲戚家孩子生在 2 月 10 日,家里老人一口咬定属蛇,产房发的纪念手环上,年份已经翻到马。

后来我把干支的算法自己推了一遍,才发现这两件事不是谁记错,而是"哪一天算换年"本来就有两套人在用:2026 年的正月初一是 2 月 17 日,丙午年从那天起算。下面这些数我是逐个取模算过的。

为什么是六十,而不是一百二十

十天干:甲乙丙丁戊己庚辛壬癸,十二地支:子丑寅卯辰巳午未申酉戌亥。把它们直接两两相乘是 120 种,但实际只有 60 种能出现,因为干的序号和支的序号必须同为阳或同为阴(甲只能配子寅辰午申戌,乙只能配丑卯巳未酉亥)。我拿两层循环数过:同阴阳的正好 60 个。

另一条路是求公倍数:干每 10 年转一圈、支每 12 年转一圈,要两个同时回到起点得走 lcm(10,12)=60 步。所以"六十甲子"不是凑出来的吉利数,是 10 和 12 的循环周期决定的:干支纪年六十年一循环,生肖只跟着地支走,十二年一轮回。1984 年是甲子,下一个甲子就是 2044 年。

年份取模:两种写法,同一个结果

最常见的是从 0 开始数:干序号 =(年份-4)mod 10,支序号 =(年份-4)mod 12,0 对应甲和子。也有资料写成(年份-3),那是从 1 开始数,余数 0 要归到第 10 个干(癸)和第 12 个支(亥)。两条式子答案完全相同,差别只在数法;我一开始把两套下标混着用,算出来的年份全错一位。

公历年 (年-4)mod 10 (年-4)mod 12 干支 生肖 六十甲子序号
190060庚子鼠37
194951己丑牛26
198400甲子鼠1
202404甲辰龙41
202515乙巳蛇42
202626丙午马43
202737丁未羊44

这里有两处专出错的边角。第一处是余数为 0:1900 年(年-4)mod 12 得 0,下标 0 是"子",(年-4)mod 10 得 6,下标 6 是"庚",合起来是庚子年;1984 年两个余数都是 0,正好是六十甲子第一位甲子。第二处是负数取模:JS 的 % 运算符在被除数为负时返回负余数,所以算公元 4 年以前的年份,(年份-4)先得到负数,要写成(余数+10)再 mod 10 才能落回 0 到 9。这一步只是算法层面的防御,1900 年以后(年份-4)恒为正,取模不可能出负数。

要查具体日子我不再手推,用 天干地支计算器:输入公历日期,年柱、月柱、日柱、时柱四柱一起给,附带生肖,还把取模过程写出来,方便我对草稿看哪一步偏了。

生肖和干支年对不上,是因为有两个"新年"

关键在于分界日。民俗和历书按正月初一(也就是春节)换年,国标 GB/T 33661-2017《农历的编算和颁行》也是从正月初一算新年;命理和八字按立春换年,立春在公历 2 月 3 日到 5 日之间浮动。春节的落点却能在 1 月下旬到 2 月中旬之间来回挪——我那份 2024 到 2030 年的表里,最早 1 月 26 日,最晚 2 月 17 日,相差 22 天。于是两个"新年"之间总有一段窗口期,同一日期在两种口径下分属两年。

亲戚家孩子那个 2 月 10 日就落在窗口里:2026 年立春在 2 月上旬、春节要到 2 月 17 日,所以按立春口径已是丙午年、属马,按春节口径还在乙巳年、属蛇,两边都没算错。反方向的窗口也有:2023 年春节 1 月 22 日、立春要到 2 月 4 日,1 月 28 日出生的人按春节口径是癸卯属兔,按立春口径仍是壬寅属虎——早出生十几天就差一个属相。

所以我的选择是看用途:写拜年话、跟长辈说属相走春节口径,排四柱、看年柱走立春口径。有个近似要拎出来:立春并不总在 2 月 4 日,2025 年是 2 月 3 日 22:10。按"2 月 4 日之前都算上一年"整切,多数年份没事;但碰上 2025 年这种交节在 2 月 3 日深夜的,22:10 到 24 点之间出生的人就被归到上一个年柱,差的是不到两小时。要精确到某一天,得按当年立春的实际时刻定,别信写死的 2 月 4 日。

还有一件前置工作比公式更容易出错:先确认那一天到底落在哪个公历日期上。跨时区出生的、只记得农历生辰的,我先把日期定下来再谈干支,比如用 世界时间 核对出生地当天的日期,或用 时间戳转换 把日期换成日序数,免得自己数的天数差一天。

干支纪日是另一条独立的轴

这点特别容易被忽略:纪年六十年一循环、生肖十二年一圈、纪月跟着节气走、纪日是连续六十天不停的一圈,不跟月初、年节、节日对齐。所以同一个人的年柱和日柱之间没有推导关系,四柱是四条各自独立推进的序列——月干由年干起(五虎遁),时干由日干起(五鼠遁),日柱只能靠锚点日期推。

正因为靠锚点,纪日对"起点差一天"极其敏感:锚点定错,整条序列就整体平移一位,结果看上去仍然像一个合法的干支。我能验证的是循环本身:60 的整数倍必然同柱,2026 年 10 月 15 日到 2026 年 12 月 14 日正好 60 天,这两天日柱相同;1900 年 1 月 31 日到 2024 年 2 月 10 日相隔 45300 天,45300 除以 60 得 755 整轮,也必然同柱。

锚点这块我自己串过行,正确值写在这儿:1900 年 1 月 1 日是甲戌日、六十甲子第 11 位;1900 年 1 月 31 日不是甲戌,是甲辰日、第 41 位,上面那组 45300 天两端同为甲辰,正好印证。另两个我逐个核过的是 1949 年 10 月 1 日甲子日(第 1 位)、2026 年 10 月 15 日壬戌日(第 59 位)。通式拿儒略日数写最省事:(JDN+49) mod 60,余数 0 是甲子;这三个点的余数应是 10、0、58,差 1 就整条平移 1 位。

Q:本命年到底按春节还是按立春算?

看你用在哪。民俗的"过本命年"从正月初一起算,命理、八字的年柱从立春起算。差别只在 1 月下旬到 2 月中旬那段窗口,其他日期两种数法结果一样。

Q:为什么网上的干支日和黄历上写的不一样?

因为锚点和日界不同。循环本身是确定的,各家用的起点日期、把子时算在哪一天未必一致,差一两天就体现成干支差一二位。核对时先看它给的锚点或示例日期,别只比结果。

Q:生肖是十二个,干支年有六十个,怎么对应?

生肖只跟着地支,12 年一圈;干支年要把干和支同时对齐,60 年才一圈。所以一个属相对应五个干支年,1984、1996、2008、2020、2032 都属鼠,分别是甲子、丙子、戊子、庚子、壬子。

Q:能不能用(年份-4)mod 10 去算日和月?

不能。年柱可以用年份的线性偏移,月要按节气切,日只能靠日序数取模。这三条轴的起点各不相同,套同一个公式一定会错。

那张贺卡的落款我最后改成了两种:给国内客户的写属相配公历年份,给讲究择日的合作方按立春口径写干支——问的人按哪个日子换年,我就按哪个日子算。

📎 相关文章

照片转了 90°,换台设备方向又回来了:EXIF 与真实旋转的分工 2026-10-22 每月同一天和每 28 天一次,一年差出 29 天 2026-10-22 用 sort(() => Math.random() - 0.5) 打乱名单,抽签就已经不公平了 2026-10-21 加仑有两种、马力有两种、字节有两套进位:换算前先问是哪一种 2026-10-21 2 月 29 日出生的人,平年哪天满 18 周岁?两种周年口径差一天 2026-10-21