我在FreeBSD 10.1和nginx上运行了PHP 7.0.8(FPM)。我需要按用户所在的国家/地区的首选格式显示时间。
setlocale(LC_ALL, "ru_RU.UTF-8");
date_default_timezone_set("Europe/Moscow");
echo strftime('%X', time());
// Returns 21:23:12 (correct) because 24-hr format is preferred in Russia.
setlocale(LC_ALL, "en_US.UTF-8");
date_default_timezone_set("America/New_York");
echo strftime('%X', time());
// Returns 21:23:12 (incorrect) must return 9:23:12 pm as preferred format in U.S.
这看起来像我的服务器或PHP版本的问题,因为 其他用户获得了正确的结果。
locale -a
返回包含ru_RU.UTF-8
和en_US.UTF-8
。
echo setlocale(LC_ALL, "en_US.UTF-8")
会返回正确的区域设置。
未应用任何特殊配置。
请帮我解决这个问题。感谢。
%X基于区域设置的首选时间表示,没有日期
P.S。首选日期%x
正常显示俄罗斯的dd.mm.yyyy和美国的mm / dd / yyyy。
答案 0 :(得分:2)
在FreeBSD 10.3上也是如此:
php -r 'date_default_timezone_set("Europe/Paris"); var_dump(setlocale(LC_ALL, "en_US.UTF-8"), strftime("%X", time()));'
string(11) "en_US.UTF-8"
string(8) "15:03:07"
首先,ls -l /usr/share/locale/en_US.UTF-8/LC_TIME
返回:
/usr/share/locale/en_US.UTF-8/LC_TIME@ -> ../en_US.ISO8859-1/LC_TIME
所以en_US.UTF-8实际上是en_US.ISO8859-1的符号链接。
然后,如果我们查看/usr/src/share/timedef/en_US.ISO8859-1.src(您需要安装源代码),我们会发现:
#
# X_fmt
#
%H:%M:%S
这可以解释您期望%I:%M:%S %p
(或%r
)时的实际结果。
可能的解决方案:
处理这个具体案例:
echo strftime(0 === strpos(setlocale(LC_ALL, '0'), 'en_US') ? '%r' : '%X');
更喜欢使用不依赖于系统区域设置的IntlDateFormatter(由ICU库假设)。例如:
$timefmt = new IntlDateFormatter('en_US', IntlDateFormatter::NONE, IntlDateFormatter::MEDIUM);
$timefmt->format(date_create());
X_fmt
的价值为%I:%M:%S %p
更新
X_fmt
为reverted,因为(即在FreeBSD> = 11,X_fmt
仍被定义为%H:%M:%S
)答案 1 :(得分:0)
摘自ubuntu 12.04上的/usr/share/i18n/locales/en_US
:
% Appropriate time representation (%X)
% "%r"
t_fmt "<U0025><U0072>"
%
% Appropriate AM/PM time representation (%r)
% "%I:%M:%S %p"
t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
<U0025><U0070>"
请注意%r的上午/下午的%I
。
unicode中的%X
为25 70,即%P
。
来自man date
(为简单而剥离):
%H hour (00..23)
%I hour (01..12)
%p locale's equivalent of either AM or PM; blank if not known
%P like %p, but lower case
%r locale's 12-hour clock time (e.g., 11:11:04 PM)
%R 24-hour hour and minute; same as %H:%M
%x locale's date representation (e.g., 12/31/99)
%X locale's time representation (e.g., 23:13:48)
读取所有这个文件,它应该按预期工作,所以我怀疑你的设置使用不同的语言环境文件或回退到C
语言环境(如果语言环境文件不在那里)
现在对于setlocale
,只有在你给出一个错误的变量(即LCAL
而不是LCALL
)时它才会返回false,但是会返回系统为其他情况返回的内容:< / p>
注意:setlocale()的返回值取决于PHP的系统 在跑。它准确返回系统setlocale函数 回报。
在“linuxes”setlocale
上返回NULL
并不总是被视为错误(请参阅here),这可能是您问题的根源,我不能发誓,因为我'没有运行FreeBSD来证实这一点。