生肖计算不能直接用year(生日)%12,因生肖按农历年切换,而公历年与农历年起始不同;正确做法是按立春(2月4日)划分生肖,将生日与当年立春比较确定所属农历年再取模。

生肖计算为什么不能直接用 YEAR(生日) % 12?
因为生肖按农历年切换,而 YEAR() 返回的是公历年份——比如 1997-02-07 出生的人,公历是 1997 年,但农历仍属牛(丁丑年),直到 1997-02-08 才进入虎年(戊寅年)。直接对公历年取模会把春节前出生的人算错一个生肖。
正确做法是:先将生日转换为对应农历年份(即该生日实际所属的农历年),再对 12 取模。关键不是“哪年出生”,而是“出生那天属于哪个农历年”。
MySQL 中用 STR_TO_DATE + DATE_SUB 粗略对齐农历年起始
严格农历计算需查表或调用外部服务,但日常业务中常采用「以每年 2 月 4 日(立春)为生肖分界」的简化规则——这是《中国黄历》通用做法,误差仅 1–2 天,且覆盖 99% 的身份证/用户数据场景。
- 把生日转成当年立春日期:
STR_TO_DATE(CONCAT(YEAR(生日), '-02-04'), '%Y-%m-%d') - 若生日
- 最终农历年 =
YEAR(生日) - IF(生日
示例:查询 users 表中所有属龙的人(龙对应余数为 8,见下条):
SELECT * FROM users WHERE (YEAR(birth_date) - IF(birth_date <h3>生肖与取模结果的映射关系必须从 1900 年起校准</h3><p>1900 年 1 月 31 日是庚子年(鼠年)开始,所以 1900 % 12 = 4,但生肖是鼠 → 鼠对应余数 4。由此推出标准映射:</p>
- 鼠=4,牛=5,虎=6,兔=7,龙=8,蛇=9,马=10,羊=11,猴=0,鸡=1,狗=2,猪=3
- 注意:
% 12结果是 0–11,不是 1–12;猴对应 0,不是 12 - 写 WHERE 条件时别写成
= 12,那是错的
验证:2000 年 1 月 1 日属兔(壬午年已过,进入辛巳年?不对——实际 2000 年 2 月 5 日才立春,所以 1 月 1 日仍属虎),按公式:2000 - 1 = 1999 → 1999 % 12 = 7 → 兔 ✅
PostgreSQL 或 SQLite 要换函数名,但逻辑完全一致
核心只是替换日期函数,取模和偏移逻辑不变:
- PostgreSQL:
EXTRACT(YEAR FROM birth_date)替代YEAR(),用(birth_date 判断是否跨年 - SQLite:
strftime('%Y', birth_date)取年份,用strftime('%Y-%m-%d', birth_date) 做字符串比较(因 SQLite 无原生日期比较) - 所有数据库都要注意:字段类型是
DATE或DATETIME,别用字符串存生日,否则STR_TO_DATE或strftime可能失败
最易被忽略的一点:没有统一处理 NULL 生日。加个 AND birth_date IS NOT NULL 是基本安全线,不然取模会返回 NULL,整行消失却不报错。










