Я подумал, что нашел лучшее решение для обхода PHP strftime () в Windows, а затем пользователь сообщил о проблеме.
Windows имеет некоторые ограничения для strftime () и, кроме того, она не поддерживает UTF-8. Поэтому я написал обходной путь для обеих этих проблем, но наткнулся на проблемы с кодировкой.
Вот как выглядит мой код:
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 (): невозможно определить кодировку символов
Как видите, «auto» не может определить кодировку. Пользователь находится на чешской установке Windows, но я не могу жестко закодировать его в «ISO-8859-2», поскольку это поможет только чешским пользователям, а не другим конечным пользователям, которые не имеют ни малейшего представления, что такое языковой стандарт Windows. или какой кодировкой.
Так что же является наилучшим возможным решением для универсального крутого решения?
Примечание: формат не является проблемой здесь. Это может быть что угодно, например,% b% e% Y% H:% M. Идентификация кодировки — это проблема.
В соответствии с руководство, проблемы, которые strftime () имеет в Windows, включают:
Не все спецификаторы преобразования могут поддерживаться вашей C-библиотекой, в
в этом случае они не будут поддерживаться PHP strftime ().
Кроме того, не все платформы поддерживают отрицательные временные метки, поэтому ваш
диапазон дат может быть ограничен не ранее эпохи Unix. это
означает, что% e,% T,% R и,% D (и, возможно, другие) — а также даты
до 1 января 1970 года — не будет работать на Windows, некоторые Linux
дистрибутивы и несколько других операционных систем.
Ваш код использует нераскрытые параметры ($format
а также $timestamp
) так что вас беспокоит довольно непонятно.
Однако полученное сообщение об ошибке связано с кодировка текста, не дата обработки per se. Просто невозможно правильно обрабатывать текст для неизвестных кодировок, но вы можете выбирать кодировка производится strftime()
выбрав подходящий язык:
strftime
— Форматировать местное время / дату в соответствии с настройками локалиОтформатируйте время и / или дату в соответствии с настройками локали. Названия месяцев и дней недели и другие зависящие от языка строки соответствуют текущая локаль установлена с Setlocale ().
Однако следует помнить, что обработка локали ненадежна на некоторых платформах, таких как поточно-ориентированные сборки в Windows. Если это так, вам может понадобиться сбросить strftime()
целиком и выберите подходящий инструмент локализации.
Конечно, вы всегда можете оставить локаль по умолчанию и просто попытаться угадать кодировку, но вам, вероятно, потребуется поддерживать базу данных.
Лучшее решение, которое я мог придумать, — это определить кодировку локали 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);
}