使用IntlDateFormatter()->format():Apache与CLI执行结果差异问题
解决IntlDateFormatter在Apache与CLI环境下月份缩写不一致的问题
问题重现
你的代码在Apache和CLI环境执行时,9月的短名称分别输出sept.和sep.,代码如下:
<?php $obj_formato = new IntlDateFormatter(setlocale(LC_TIME, 0), null, null); $obj_formato->setPattern("MMM"); for($i=1; $i<13; $i++) { print $obj_formato->format(strtotime("2022-$i-01")) . PHP_EOL; }
问题原因
核心问题在于setlocale(LC_TIME, 0)返回的是当前进程的系统区域设置,而Apache与CLI运行在不同的环境上下文:
- Apache通常以系统服务身份运行,其环境变量(如
LC_TIME、LANG)可能与CLI用户的环境变量不一致 - IntlDateFormatter依赖ICU库处理本地化,
setlocale返回的系统区域名称与ICU的区域标识符可能存在映射差异,不同环境下的映射结果不同,最终导致月份短名称的输出不一致
解决方案
1. 明确指定ICU区域标识符(推荐)
直接在IntlDateFormatter构造函数中传入明确的ICU区域标识符,而非依赖系统的setlocale结果,确保两个环境使用统一的本地化规则:
<?php // 示例:指定英文(美国)区域,可根据需求替换为其他区域如'es_ES'(西班牙语西班牙) $locale = 'en_US'; $obj_formato = new IntlDateFormatter($locale, null, null); $obj_formato->setPattern("MMM"); for($i=1; $i<13; $i++) { print $obj_formato->format(strtotime("2022-$i-01")) . PHP_EOL; }
这样无论在Apache还是CLI环境,只要PHP的ICU库包含该区域的数据,输出结果就会完全一致。
2. 统一Apache与CLI的系统区域环境变量
如果需要对齐系统的区域设置,可通过以下方式统一环境变量:
- Apache端:在Apache配置文件(如
httpd.conf或虚拟主机配置)中添加环境变量设置:SetEnv LC_TIME en_US.UTF-8 - CLI端:确保执行PHP的用户环境中
LC_TIME与Apache设置的一致,可在用户的~/.bashrc或~/.profile中添加:export LC_TIME=en_US.UTF-8
这种方式依赖系统配置,不如直接指定ICU区域标识符稳定,仅适用于必须对齐系统区域的场景。
3. 直接使用日期格式常量替代自定义Pattern
如果仅需获取标准短格式月份名,可直接使用IntlDateFormatter的格式常量,无需手动设置Pattern:
<?php $obj_formato = new IntlDateFormatter('en_US', IntlDateFormatter::SHORT, IntlDateFormatter::NONE); for($i=1; $i<13; $i++) { $date = new DateTime("2022-$i-01"); print $obj_formato->format($date) . PHP_EOL; }
这种方式会输出标准短格式月份名(如"Jan"),效果与MMMPattern一致。
内容的提问来源于stack exchange,提问作者framirezfa
相关产品推荐
相关产品推荐

