strftime () возвращает неправильный предпочтительный формат времени

Я получил PHP 7.0.8 (FPM), работающий на FreeBSD 10.1 и nginx. Мне нужно отображать время в предпочитаемом формате в зависимости от страны, где проживает пользователь.

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 Предпочитаемое представление времени на основе локали без даты

Постскриптум Предпочитаемая дата %x работает корректно, отображая дд.мм.гггг для России и мм / дд / гггг для США.

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).

Возможные решения:

  • заполнить отчет об ошибке если вы считаете это актуальным и / или1 патч файла выше, затем перестроить мир (я думаю)
  • обработать этот конкретный случай:

    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());
    

1 Кажется, что X_fmt ценится до %I:%M:%S %p в хобот а также 11-СТАБИЛЬНЫЙ

Обновить:

  • изменение коммита X_fmt было вернулся так как (т.е. во FreeBSD> = 11, X_fmt по-прежнему определяется как %H:%M:%S)
  • в FreeBSD 11 файл, определяющий форматы времени, имеет вид /usr/src/share/timedef/en_US.UTF-8.src (символическая ссылка на локаль en_US.ISO8859-1 пропала)
2

Другие решения

Выдержка из /usr/share/i18n/locales/en_US на Ubuntu 12.04:

% 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>"

Пожалуйста, обратите внимание %I в дату AM / PM для% r.

%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 locale (например, если там нет файла locale)

Теперь для setlocale, он вернет false только в случае, если вы передадите неверную переменную (т.е. LCAL вместо LCALL) но вернет то, что система возвращает для других случаев:

Примечание: возвращаемое значение setlocale () зависит от системы, в которой работает PHP
бежит. Он возвращает именно то, что системная функция setlocale
возвращается.

На «linux» setlocale возвращается NULL который не всегда считается ложным (см. Вот) которая может быть источником вашей проблемы, я не могу поклясться, так как у меня не работает FreeBSD, чтобы подтвердить эту точку зрения.

0

По вопросам рекламы [email protected]