什么是闰年
闰年(Leap Year)指的是公历中比普通年份多一天的年份,即2月份有29天,全年共有366天。闰年的设置是为了补偿地球绕太阳公转周期与日历年的微小差异。
公历闰年的判定规则如下:
-
普通闰年:能被4整除但不能被100整除
-
世纪闰年:能被400整除
比如2000年能被400整除,是闰年;1900年能被4整除也能被100整除但不能被400整除,不是闰年;2024年能被4整除且不能被100整除,是闰年。
个人经验:很多新手以为“每4年一次闰年”就够了,但实际上世纪年的处理是一个容易忽略的细节。比如1900年不是闰年,而2000年是。不搞清楚这个规则,写出来的闰年判定在某些年份上会出错。
核心实现逻辑
判定闰年有两种常见方法:
方法一(使用PHP日期函数):利用date()函数配合mktime()获取指定年份2月29日是否存在。如果存在,说明这一年是闰年。这种方法利用了PHP内置的日期处理能力,不需要手动写判定逻辑。
方法二(使用条件判断):根据闰年的数学规则,用%取模运算符检查年份是否满足条件:(能被4整除 且 不能被100整除)或 能被400整除。
示例一:使用date()函数判定指定范围内的闰年
代码号学习编程中,这个方法利用了PHP内置的日期函数,代码简洁且准确。
<?php
function isLeapYear($year) {
// mktime(时, 分, 秒, 月, 日, 年) 生成时间戳
// date('L', 时间戳) 返回1表示闰年,0表示平年
return date('L', mktime(0, 0, 0, 1, 1, $year)) == 1;
}
// 检查1991年到2016年之间的所有年份
for ($year = 1991; $year <= 2016; $year++) {
if (isLeapYear($year)) {
echo "{$year}:闰年<br>";
} else {
echo "{$year}:平年<br>";
}
}
?>
关于mktime()函数的说明:这个函数生成一个Unix时间戳。参数顺序是时、分、秒、月、日、年。这里设置为1月1日的0点0分0秒,只是为了生成一个有效的时间戳,具体时分秒不重要,因为date('L')只关心年份。
示例二:通过表单输入年份并判定闰年
下面这个例子展示了如何接收用户输入的年份,并根据闰年规则进行判定。
<html>
<body>
<form method="post">
请输入年份:<input type="text" name="year">
<input type="submit" name="submit" value="判断闰年">
</form>
</body>
</html>
<?php
if ($_POST) {
$year = trim($_POST['year']);
// 检查是否为有效数字
if (!is_numeric($year)) {
echo "请输入有效的数字年份";
return;
}
// 转为整数
$year = (int)$year;
// 闰年判定条件:能被4整除且不能被100整除,或能被400整除
if (($year % 4 == 0 && $year % 100 != 0) || ($year % 400 == 0)) {
echo "{$year} 是闰年";
} else {
echo "{$year} 不是闰年";
}
}
?>
判定条件的拆解说明:
-
$year % 4 == 0:年份能被4整除 -
$year % 100 != 0:年份不能被100整除 -
$year % 400 == 0:年份能被400整除
第一条和第二条用&&(与)连接,表示“能被4整除但不能被100整除”。然后这个结果与第三条用||(或)连接,表示满足任意一个条件就是闰年。
本节课程知识要点
| 知识点 | 说明 |
|---|---|
| date('L') | PHP日期格式字符,L表示闰年(Leap year),返回1或0 |
| mktime() | 生成时间戳,参数顺序:时、分、秒、月、日、年 |
| 取模运算符(%) | 求余数,用于判断整除关系 |
| 世纪年规则 | 能被400整除才是闰年,否则是平年 |
| 逻辑运算符 | &&(与)、||(或)、!(非)组合使用 |
两种方法的对比
| 维度 | date('L') + mktime() | 条件判断(%运算) |
|---|---|---|
| 代码可读性 | 高,语义清晰 | 中等,需要理解规则 |
| 执行效率 | 较低(涉及时间戳计算) | 较高(纯整数运算) |
| 依赖项 | 依赖PHP日期函数 | 无依赖 |
| 适用范围 | 年份范围受时间戳限制(通常1901-2038) | 任意整数年份 |
| 学习价值 | 了解日期函数 | 理解逻辑运算组合 |
个人经验:在Web开发中,如果需要判定的是近期年份(比如1901-2038之间),两种方法都可以。但如果年份超出了时间戳范围(比如公元前或3000年),mktime()可能无确处理,这时候必须用条件判断方法。条件判断方法的效率也更高,所以我个人在项目中更常用第二种方式。
闰年判定中的常见错误
错误1:只判断能被4整除
if ($year % 4 == 0) { // 不够准确
这种写把1900年误判为闰年,但实际上1900年不是闰年。
错误2:条件中的逻辑运算符使用错误
if ($year % 4 == 0 && $year % 100 != 0 && $year % 400 == 0)
这种写法为false,因为一个数不可能同时满足%100 != 0和%400 == 0。应该用||而不是&&连接之后一部分。
错误3:忘记处理用户输入的字符串
-
后果:用户输入字母时,
$year % 4会导致PHP类型转换,结果不可预测 -
解决:在运算前用
is_numeric()检查
错误4:未考虑负数年份
-
说明:公历纪元的闰年规则通常只适用于公元1年及以后
-
解决:可以在判定前加
if ($year < 1) return false;
扩展:封装闰年判定函数
在项目中,建议将闰年判定逻辑封装成一个函数,方便多处调用。
/**
* 判断年份是否为闰年
* @param int $year 年份(公元后)
* @return bool 闰年返回true,平年返回false
*/
function checkLeapYear($year) {
if (!is_numeric($year) || $year < 1) {
return false; // 无效输入返回false
}
$year = (int)$year;
return ($year % 4 == 0 && $year % 100 != 0) || ($year % 400 == 0);
}
// 使用示例
echo checkLeapYear(2024) ? "2024是闰年" : "2024是平年"; // 闰年
echo checkLeapYear(1900) ? "1900是闰年" : "1900是平年"; // 平年
echo checkLeapYear(2000) ? "2000是闰年" : "2000是平年"; // 闰年
个人经验与建议
关于两种方法的选择:
-
学习阶段:两种都写一遍,理解各自的实现思路
-
项目开发:优先用条件判断法,效率好,适用范围广
-
日期处理密集的场景:如果已经用了Carbon等日期库,可以直接调用现成的方法
关于表单输入的细节:上面示例中用了return来终止脚本。在项目中,更好的做法是把错误信息存到变量中,在合适的位置输出,而不是直接return中断程序。
关于年份范围的考虑:如果业务中需要处理公元前的年份(比如历史数据统计),闰年的定义需要重新确认——历史学家对儒略历和公历的转换有不同的标准。一般Web应用很少涉及,知道有这个边界即可。