PHP 5.4 Не может определять временные зоны самостоятельно

Я просто ищу немного разъяснения по этому поводу. PHP 5.4 устраняет переменную окружения TZ и «угадывание», date_default_timezone_get раньше date_default_timezone_get . Итак, теперь мне кажется, что вообще невозможно установить часовой пояс сервера.

Поэтому мой вопрос заключается в следующем: возможно ли получить часовой пояс сервера в PHP 5.4? Я знаю, что могу вручную установить его в php.ini, но это кажется глупым, когда есть компьютер, который отлично знает, в какое время. Я ожидаю, что ответ будет «нет», поэтому, возможно, кто-то может пролить свет на то, почему язык программирования не сможет определить свой часовой пояс, если это так.

Нет надежного способа угадать часовой пояс для каждой системы. В разных системах используются разные соглашения, а иногда и разные определения часового пояса (например, Unix и Windows), иногда имеют противоречивые спецификаторы часовых поясов (одно и то же аббревиатура из трех букв может означать разные вещи в разных местах). Поэтому, если вы хотите иметь код, который переносится между системами, единственный способ надежно сделать это – спросить пользователя. См., Например, эту тему: http://marc.info/?t=132356551500002&r=1&w=2 по некоторым проблемам с ней (ищите электронные письма от Derick Rethans – он является разработчиком расширений PHP datetime).

Если у вас есть способ узнать часовой пояс, которому вы доверяете – например, переменная TZ – тогда вы всегда можете сделать date_default_timezone_set($_SERVER['TZ']); , Однако в целом это не надежный метод, поэтому вам должно быть ваше решение доверять ему, PHP не может сделать это за вас.

Если вы посмотрите здесь, вы можете увидеть код из PHP 5.3, который попытается угадать системный часовой пояс. Это не так уж и много, но, по-видимому, причины для удаления угадывания в основном связаны с DST, так как именно там возникают проблемы.

Разбивка всего процесса угадывания выглядит так:

  • Проверяет, определено ли это глобально (php.ini или предыдущее предположение) (строка 851-853)
  • Проверьте переменную окружения TZ (редко когда-либо определяемую по моему опыту) (строка 855-858)
  • Проверьте date.default_timezone от php.ini (специальный случай, как он уже должен быть определен) (строка 860-872)
  • Попытайтесь угадать часовой пояс из системы, сравнивая time() с localtime() . Спектр кажется, что установка часового пояса является необязательной, поскольку могут возникнуть проблемы с потоковыми версиями этого вызова (строка 873-890)
  • Win32: Вызвать функцию WinAPI GetTimeZoneInformation() и попытаться определить системный часовой пояс (строка 893-928)
  • Netware: проверьте значение _timezone если оно определено (строка 929-937)
  • Отказ от UTC, если ни одна из вышеперечисленных проверок не выполнена

Я могу только догадываться, но, возможно, они только удалили его, так как это было предположение для начала и не всегда надежны.

Также из-за популярности PHP он устанавливается практически на каждом плане хостинга на базе Linux, где клиенты часто находятся не в том же часовом поясе, что и сервер, поэтому возврат к серверному часовому поясу для этих людей не лучше, чем использование UTC по умолчанию. Тогда это только вызывает путаницу, поскольку эти клиенты должны прийти к SO, чтобы спросить, почему в PHP неверно время.

Я не достаточно знаком с C и стандартом, но кажется, что в часовом поясе угадывания на основе localtime проблемы с многопоточным кодом или в некоторых случаях недоступны. Поскольку на платформах, отличных от Windows, это лучший способ определить часовой пояс, это не имеет смысла делать, если сказать половину времени, когда он ничего не возвращает или не создает проблем для многопоточного PHP.

Тогда, конечно, проблема DST в некоторых местах, где часовой пояс и смещение различаются в зависимости от времени года.

Надеюсь, это поможет.

Нет, на данный момент невозможно восстановить часовой пояс на ПК.

Недавно я построил несколько серверов для проекта, с нуля. Из-за предыдущего опыта в других проектах, где серверы использовали локальные часовые пояса, я решил заставить каждый сервер использовать часовой пояс UTC. Хотя это привело к тому, что файлы журналов отключились на 7 часов (UTC – PST), он устранил несогласованность, вызывающую локальные часовые пояса (из предыдущего проекта).

Принудительная согласованность оказалась полезной в слоях ОС и приложений. Для уровня ОС все записи файла журнала можно просматривать из централизованного местоположения (через syslog через udp) независимо от их физического местоположения. И на уровне приложения было намного проще хранить каждую временную метку в формате UTC, а затем конвертировать в рендеринг для пользователей, указавших часовой пояс. Это одностороннее преобразование намного проще, чем двухстороннее преобразование, где вам нужно будет преобразовать временную метку в UTC из локального часового пояса сервера после сохранения, а затем преобразовать ее в выбранный часовой пояс пользователя при рендеринге.

Поэтому, если для ваших серверов не существует очень убедительной причины для уведомления о часовых поясах, я бы предпочел придерживаться UTC, который по умолчанию был прежним до 5.4: «Если ни одно из указанных выше не будет выполнено, date_default_timezone_get () вернет часовой пояс по умолчанию для UTC. "

Это просто дикая догадка. Можете ли вы получить часовой пояс:

date('H', 0); или что-то типа того? Я имею в виду, что, поскольку отметка unixtime одинакова во всех регионах, но Hour отличается, разве вы не сможете опираться на час, который знает, какой часовой пояс используется?

На сервере Windows можно получить локальный системный часовой пояс с небольшим количеством математики:

 <?php date_default_timezone_set('UTC'); $nowUTC = new DateTime(); $nowSys = new DateTime(exec('echo %time%')); $offset = $nowUTC->diff($nowSys); echo $nowUTC->format('H:i:s') . '<br />'; echo $nowSys->format('H:i:s') . '<br />'; echo $offset->format('%H'); ?> 

Из моей локали (UTC-05) во время написания этого кода:

 22:16:41 17:16:41 05 

Существует одно предостережение: временные метки иногда могут быть отключены на 1 секунду, в результате чего переменная $offset имеет значение 4:59:59. Правильный выбор временной зоны должен сделать немного округления, чтобы быть в безопасности.