我认为我在Windows上提出了针对PHP strftime()的解决方法的最佳解决方案,然后用户报告了问题。
Windows对strftime()有一些限制,而且它不支持UTF-8。所以我为这两个问题写了一个解决方法,但偶然发现了charset问题。
这就是我的代码:
function strftimefixed($format, $timestamp=null) {
if ($timestamp === null) $timestamp = time();
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
$format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); // Don't mind this line
}
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'auto'); // Charset is the problem
}
错误消息
警告:mb_convert_encoding():无法检测字符编码
你可以看到&#39; auto&#39;无法识别编码。用户正在安装捷克语,但我无法将其硬编码到ISO-8859-2&#39;因为这只会帮助捷克用户,而不是其他最终用户,他们对Windows区域设置或者哪种字符集没有任何了解。
那么制作一些通用的优秀解决方案的最佳解决方案是什么?
注意:这里的格式不是问题。它可以是任何东西,例如%b%e%Y%H:%M。字符集识别是问题所在。
答案 0 :(得分:0)
根据the manual,strftime()在Windows上遇到的问题包括:
您的C库可能不支持所有转换说明符 在哪种情况下,PHP的strftime()不支持它们。 此外,并非所有平台都支持负时间戳,因此您的 日期范围可能不会早于Unix纪元。这个 表示%e,%T,%R和%D(可能还有其他) - 以及日期 在1970年1月1日之前 - 在Windows上,某些Linux上不起作用 发行版和其他一些操作系统。
您的代码使用未公开的参数($format
和$timestamp
),所以您担心的是相当不清楚的。
但是,您收到的错误消息与文本编码有关,而与日期处理本身无关。对于未知编码,无法正确处理文本,但您可以通过选择合适的区域设置选择 strftime()
生成的编码:
strftime
- 根据区域设置格式化本地时间/日期根据区域设置格式化时间和/或日期。月份和工作日名称以及其他依赖于语言的字符串遵循使用setlocale()设置的当前区域设置。
请注意,在某些平台(例如Windows上的线程安全版本)中,区域设置处理是不可靠的。如果是这种情况,您可能需要完全转储strftime()
并选择正确的本地化工具。
当然,您可以始终保留默认语言环境,只是尝试从中猜测编码,但您可能需要维护数据库。
答案 1 :(得分:0)
我能想出的最佳解决方案是检测Windows区域设置字符集并从那里开始工作。
function strftimefixed($format, $timestamp=null) {
if ($timestamp === null) $timestamp = time();
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
$format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format);
$locale = setlocale(LC_TIME, 0);
switch(true) {
case (preg_match('#\.(874|1256)$#', $locale, $matches)):
return iconv('UTF-8', "$locale_charset", strftime($format, $timestamp));
case (preg_match('#\.1250$#', $locale)):
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'ISO-8859-2');
case (preg_match('#\.(1251|1252|1254)$#', $locale, $matches)):
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'Windows-'.$matches[1]);
case (preg_match('#\.(1255|1256)$#', $locale, $matches)):
return iconv('UTF-8', "Windows-{$matches[1]}", strftime($format, $timestamp));
case (preg_match('#\.1257$#', $locale)):
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'ISO-8859-13');
case (preg_match('#\.(932|936|950)$#', $locale)):
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'CP'.$matches[1]);
case (preg_match('#\.(949)$#', $locale)):
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'EUC-KR');
default:
trigger_error("Unknown charset for system locale ($locale)", E_USER_NOTICE);
return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'auto');
}
}
return strftime($format, $timestamp);
}