闰年判断必须严格遵循格里高利历规则:能被4整除且不能被100整除,或能被400整除;推荐使用checkdate(2,29,$year)而非手动数学计算或date('l'),因其语义清晰、边界安全、不易出错。

闰年判断的数学逻辑必须严格按格里高利历规则
PHP里写错闰年判断,往往是因为只记住了“能被4整除就是闰年”这个不完整的口诀。实际规则是:年份能被4整除 且 不能被100整除,或者 能被400整除。漏掉任一条件都会在1900、2100这类年份出错。
常见错误现象:date_is_leap_year(1900) 返回 true(如果手写逻辑没排除100倍数),但1900年不是闰年。
- 能被400整除 → 一定是闰年(如2000)
- 能被100整除但不能被400整除 → 一定不是闰年(如1900、2100)
- 能被4整除但不能被100整除 → 是闰年(如2024、2028)
- 其余情况 → 不是闰年(如2023、2025)
用 date() + checkdate() 最稳妥
自己写 if 判断容易漏边界,PHP原生函数更可靠。核心思路是:尝试构造该年2月29日的日期,再用 checkdate() 验证是否合法。
function isLeapYear($year) {
return checkdate(2, 29, $year);
}
这个方法不依赖时区、不关心年份范围(只要 $year 在 checkdate() 支持范围内,通常是1–32767),也天然规避了格里高利历规则的手动实现错误。比纯数学计算更直观,也更难写错。
注意:checkdate() 返回布尔值,不要和 date('L', ...) 混用——后者需要时间戳,而传入2月29日的时间戳在非闰年会自动归到3月1日,导致误判。
date('L') 只能在已知有效日期上用
date('L') 确实能返回当前年份是否闰年(1为是,0为否),但它依赖传入的时间戳。如果直接用 mktime(0,0,0,1,1,$year) 构造时间戳再取 'L',看似可行,但有隐患:
- PHP 5.1+ 对超大年份(如公元10000年)支持不稳定,
mktime()可能返回false - 某些系统 time_t 限制在 2038 年前,
mktime()会溢出 - 时区设置会影响结果(比如
date_default_timezone_set('UTC')必须显式设好)
所以除非你确定年份在安全范围内(如1970–2037),且已统一时区,否则不推荐这条路。不如直接用 checkdate(2,29,$year) 干净利落。
性能差异几乎可以忽略,别为优化牺牲可读性
三种常见写法(数学判断 / checkdate() / date('L'))在百万次调用下差距不到10ms。真正该关注的是语义清晰和边界覆盖。
如果你在写通用工具函数,选 checkdate(2,29,$year);如果只是临时判断当前年,date('L') 加个注释也够用。但千万别为了“看起来快”写成 !($year % 100) && ($year % 400) 这种反直觉表达——它把逻辑弄反了,而且难维护。
最易被忽略的一点:年份变量类型。传入字符串 "2024" 会被 PHP 自动转为整型,但如果是 "2024-01-01" 这种就直接崩了。务必确保 $year 是整数或可安全转换的数字字符串。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











