因为最近帮亲戚处理数据,涉及到通过身份证计算年龄问题,这两天我把 CNID 包更新了下,该包主要功能包括:验证身份证的有效性(未对区划代码有效性验证),提取地区、生日、性别信息,附带地计算年龄、生肖(用的阳历,不太严谨)、星座。欢迎各位使用,也欢迎诸位提出改进意见和建议。

remotes::install_gitlab("chuxinyuan/cnid")

更新:已于2025年3月1日解决了生肖用阳历计算不严谨的问题,采用正月初一为分界点。

tctcab 谢谢!我之前也搜了下,确实没有搜到,DeepSeek 给出的方案有二,一是基于预置数据表的简化实现;二是通过 reticulate 调用 Python 库。我本来想通过方案二生成一张万年历,然后利用方案一思路直接放在包里,后来继续问了下 DeepSeek 关于生肖的问题,给出的如下答复:

1. 生肖划分标准

  • 核心依据:以二十四节气中的立春为分界点(非阴历正月初一)
  • 历法基础:基于中国农历(阴阳合历),但具体执行采用节气系统

2. 分界点说明

  • 错误认知:约47%的民众误认为正月初一为分界
  • 正确规则:若某年立春在正月初一之前,则立春当日即属新年生肖(如2023年2月4日立春,早于春节1月22日,当日即属兔年)
  • 历史依据:该标准自汉代确立,明清《协纪辨方书》明确记载

3. 争议现状

  • 官方口径:为方便统计采用正月初一分界(占52%使用场景)
  • 专业领域:命理学、农业历法仍严格使用立春标准
  • 典型矛盾:2023年1月21日(除夕)出生者,按官方属虎,按传统历法仍属牛

4. 换算工具建议

  • 使用中国科学院紫金山天文台发布的《百年农历节气表》进行精确查询
  • 示例:1997年2月3日出生者,虽在春节前(当年春节为2月7日),但因立春在2月4日,故属牛而非鼠

(数据来源:中国民俗学会2023年历法使用调查报告)

综上,以立春为分界点才是正确的划分规则。这比我之前认为的正月初一为分界要麻烦得多,所以暂时放弃了。

    chuxinyuan

    看起来很厉害啊,不过细节逻辑还是会有问题,比方说

    如2023年2月4日立春,早于春节1月22日

    以及

    1997年2月3日出生者,……,但因立春在2月4日,故属牛而非鼠

    ------------ 分割线一下 ------

    回到生肖的划分问题本身,这本身是匹配地支来方便纪年的,所以核心在于农历新年第一天到底在什么位置。在古代这是官方来定(年号等)。在现代,紫金山天文台是发布过计算标准的,包括生肖的对应规则。当然,这个计算规则中就是所谓的“官方口径”的正月初一分界。Wiki的农历页面也有一些计算规则。

    我能找到的,以立春为分界来划分生肖,也就是一些八字算命。不过我没能力考证古代的新年第一天是不是以立春来定(官方的规则?)。

    但是考虑到生肖本来就是为了方便纪年,以及现在是有“官方”规则的,我感觉如果真的要去做的话,没必要再去纠结曾经的,或者找不到多少支撑论据的所谓“正确”规则。

    PS:昨天在搜这个话题的时候也找到一个公历农历转换的php项目,也包含生肖,看起来是考虑了立春的实现。

    PS:真的看紫金山天文台的日历资料的话,节气的分割是精确到“分”的,不过身份证上只能精确到“日”,所以真要做按节气的分割的话还得再考虑下将大家缺失的“时”和“分”都填补一下。

    细节拉满!似乎可以既要又要,就是两个标准整两个函数,各取所取。目前可以先按照“官方口径”的正月初一分界计算一个,这个相对容易实现。对于按照立春为分界,如果按照太阳地心视黄经315°来精确分割的话,现有数据确实做不到,只能精确到日了,或者说粗略的以零时零分为界。