PHP实现按月拆分上下半月并显示英文月份的问题排查
薪资系统月份英文显示问题排查与解决
需求背景
为薪资系统实现按月拆分显示逻辑:将每个月分为前15天和15号之后的剩余天数,且月份需以英文单词形式展示(如1对应January)。
问题现象
初始代码可正常输出数字格式的月份日期范围,但修改为英文月份后,所有月份均显示为January,无法得到对应月份的英文名称:
- 期望输出:
January 1, 2024 <=> January 15, 2024 January 16, 2024 <=> January 31, 2024 February 1, 2024 <=> February 15, 2024 ...
- 实际输出:
January 1, 2024 <=> January 15, 2024 January 16, 2024 <=> January 31, 2024 January 1, 2024 <=> January 15, 2024 ...
错误代码
for($i=1;$i<=12;$i++) { $totaldays=cal_days_in_month(CAL_GREGORIAN,$i,$currentYear); $firstDay = date($i.'-01-'.$currentYear); $firstDay = date('F 1, Y', strtotime($firstDay)); $first15 = date($i.'-15-'.$currentYear); $first15 = date('F 15, Y', strtotime($first15)); $after15days = date($i.'-16-'.$currentYear); $after15days = date('F 16, Y', strtotime($after15days)); $lastDay = date($i.'-'.$totaldays.'-'.$currentYear); $lastDay = date('F '.$totaldays.', Y', strtotime($lastDay)); }
问题原因
核心问题出在日期格式的解析歧义:
代码中构造的日期字符串是$i.'-01-'.$currentYear(如2-01-2024),这种“月-日-年”格式并非PHP strtotime()函数默认的标准格式,函数会将其误判为“日-月-年”。例如2-01-2024会被解析成2024年1月2日,因此后续用date('F')获取月份时始终返回January。
解决方法
方法1:使用标准日期格式构造字符串
将日期格式改为年-月-日(ISO标准格式),避免strtotime()解析错误:
$currentYear = date('Y', strtotime($date_now)); for($i=1;$i<=12;$i++) { $totaldays = cal_days_in_month(CAL_GREGORIAN, $i, $currentYear); // 用年-月-日格式构造日期字符串 $firstDay = date('F 1, Y', strtotime("{$currentYear}-{$i}-01")); $first15 = date('F 15, Y', strtotime("{$currentYear}-{$i}-15")); $after15days = date('F 16, Y', strtotime("{$currentYear}-{$i}-16")); $lastDay = date('F '.$totaldays.', Y', strtotime("{$currentYear}-{$i}-{$totaldays}")); // 输出结果 echo "{$firstDay} <=> {$first15}\n"; echo "{$after15days} <=> {$lastDay}\n"; }
方法2:使用DateTime类(更可靠)
DateTime类对日期格式的处理更明确,避免解析歧义:
$currentYear = date('Y', strtotime($date_now)); for($i=1;$i<=12;$i++) { $totaldays = cal_days_in_month(CAL_GREGORIAN, $i, $currentYear); $dateObj = DateTime::createFromFormat('Y-n-d', "{$currentYear}-{$i}-01"); $firstDay = $dateObj->format('F 1, Y'); $dateObj->setDate($currentYear, $i, 15); $first15 = $dateObj->format('F 15, Y'); $dateObj->setDate($currentYear, $i, 16); $after15days = $dateObj->format('F 16, Y'); $dateObj->setDate($currentYear, $i, $totaldays); $lastDay = $dateObj->format('F '.$totaldays.', Y'); // 输出结果 echo "{$firstDay} <=> {$first15}\n"; echo "{$after15days} <=> {$lastDay}\n"; }
最终效果
修正后代码可正确输出各月份的英文名称,符合需求:
January 1, 2024 <=> January 15, 2024 January 16, 2024 <=> January 31, 2024 February 1, 2024 <=> February 15, 2024 February 16, 2024 <=> February 29, 2024 ...
内容的提问来源于stack exchange,提问作者WP Expert
相关产品推荐
相关产品推荐

