PHP中比较m-d与y-m-d格式日期及计算区间天数的方法
PHP场景下m-d格式与完整Y-m-d日期比较、区间统计最优方案
核心实现思路
- 优先使用PHP原生
DateTime、DatePeriod类处理日期逻辑,规避手动计算时间戳、拼接日期带来的闰年、月份天数差、时区等误差 - 不需要给仅含月日的季节起止日期补全年份,遍历日期区间时将每个日期格式化为
m-d字符串,直接和季节起止字符串做字典序比较即可——固定两位月+两位日的m-d格式,字典序和实际日期先后顺序完全一致 - 逻辑兼容两种季节区间场景:季节起止在同一年(如示例的03-15到04-30)、季节区间跨年度(如12-15到次年01-20)
- 自动校正输入的两个完整日期的先后顺序,不需要提前判断
$date1、$date2哪个更早
可直接复用的实现代码
// 示例输入参数 $date1 = "2022-04-20"; $date2 = "2022-05-20"; $seasonStart = "03-15"; $seasonEnd = "04-30"; // 初始化完整日期区间端点 $startDate = new DateTime($date1); $endDate = new DateTime($date2); // 校正顺序,保证左端点早于右端点 if ($startDate > $endDate) { [$startDate, $endDate] = [$endDate, $startDate]; } // DatePeriod的结束日期为排他逻辑,加1天保证包含区间最后一天 $endDate = $endDate->modify('+1 day'); // 判断季节区间是否跨年 $isCrossYearSeason = $seasonStart > $seasonEnd; $matchCount = 0; // 按天遍历整个日期区间 $period = new DatePeriod($startDate, new DateInterval('P1D'), $endDate); foreach ($period as $currentDay) { $currentMd = $currentDay->format('m-d'); if ($isCrossYearSeason) { // 跨年季节区间:月日大于等于起始值 或 小于等于结束值 即为命中 if ($currentMd >= $seasonStart || $currentMd <= $seasonEnd) { $matchCount++; } } else { // 同年季节区间:月日介于起止值之间 即为命中 if ($currentMd >= $seasonStart && $currentMd <= $seasonEnd) { $matchCount++; } } } echo $matchCount; // 示例场景输出11,即4月20日-4月30日共11天符合要求
避坑说明
不要给
m-d格式的日期拼接当年年份再转时间戳比较:如果遇到平年,拼接2月29日会生成无效日期导致判断失效;如果遇到跨年的季节区间,拼接单一年份会完全算错后半段的日期范围。
不要手动拆分月、日做数字比较:需要额外写逻辑处理不同月份的天数差、闰年2月的特殊情况,代码冗余且容易出边界bug。
内容的提问来源于stack exchange,提问作者A. Atal
相关产品推荐
相关产品推荐

