Существует ли стандартный способ определения часового пояса пользователя на веб-странице веб-сервером?
Возможно, из заголовка HTTP или части строки user-agent?
Тогда пользователю, наверное, все равно?
Вы имеете в виду stackoverflow.com/q/1091372/218196?
Нет. Не помогает моему текущему делу, хотя выглядит полезным для других вещей. Что мне нужно сделать, так это взять минуты getTimezoneOffset() и передать их чему-то, что даст мне, например, America/Los_Angeles. Или передайте что-нибудь функции, которая даст мне это, или эквивалент. Я не хочу отображать время, основанное на часовом поясе, установленном пользователями, больше, чем на том месте, где что-то произошло.
Я не думаю, что есть встроенный API, который дает имя часового пояса. Для этого вам придется прибегнуть к помощи какой-либо внешней службы или библиотеки.
К сожалению, ответы на этот вопрос также позволяют профилировать пользователей и выполнять геозону.
Зачем нужно знать часовой пояс пользователя?
Что ж, к счастью для вас, этот ответ можно найти на нашем собственном веб-сайте stackoverflow: stackoverflow.com/questions/1033/ip-to-country, спойлер: hostip.info/use.html
Я не думаю, что это возможно, если пользователь не отправит информацию на сервер. Это должно выполняться на стороне клиента.






Пока нет HTTP-заголовков, которые сообщали бы о часовом поясе клиента, хотя было предложено включить его в спецификацию HTTP.
Если бы это был я, я бы, вероятно, попытался получить часовой пояс с помощью клиентского JavaScript, а затем отправить его на сервер с помощью Ajax или чего-то еще.
Как ни странно, это единственный ответ правильный на вопрос, который спрашивает, как это сделать на стороне сервера. Я подозреваю, что есть другие ответы с большим количеством голосов, потому что, как только вы понимаете, что вам нужно сделать это на стороне клиента, вы в конечном итоге используете другие ответы. Но ИМХО, любой, кто голосует за другой ответ, должен голосовать и за этот.
Я считаю, что лучший метод - использовать местоположение по географическому IP-адресу для сортировки возможных часовых поясов и по умолчанию выбрать первый, который (близко) соответствует смещению времени пользовательского агента (требуется JavaScript). Даже после этого вы должны предоставить способ исправить часовой пояс, даже если этот метод выберет неправильный.
@MikkoRantalainen осторожно использует прокси-серверы, так как они не всегда рекламируют себя в заголовках.
@Matthieu, в настоящее время существует лучший ответ: stackoverflow.com/a/11836123/334451
Это буквально единственный ответ, который действительно отвечал на поставленный вопрос.
JavaScript - самый простой способ узнать местное время клиента. Я бы предложил использовать XMLHttpRequest для отправки местного времени, и если это не удастся, вернуться к часовому поясу, обнаруженному на основе их IP-адреса.
Что касается геолокации, я использовал MaxMind GeoIP в нескольких проектах, и он работает хорошо, хотя я не уверен, предоставляют ли они данные о часовом поясе. Это услуга, за которую вы платите, и они ежемесячно обновляют вашу базу данных. Они предоставляют оболочки на нескольких веб-языках.
Я проголосовал за этот ответ, потому что широта и долгота, полученные из таких баз данных, как GeoIP (у которых есть бесплатная версия, доступная на данный момент), могут быть объединены с базами данных, которые преобразуют такие координаты в часовой пояс. Я думаю, что у GeoNames есть последняя такая база данных.
Текущие версии (как бесплатные, так и платные) баз данных / API MaxMind GeoIP действительно предоставляют информацию о часовом поясе (он возвращает «Европа / Лондон» для моего часового пояса.) Я не могу вспомнить, была ли старая версия их системы GeoIP сделал то же самое, но теперь он работает очень хорошо! Поля MaxMind называются «time_zone», «time_zone_name».
Самый популярный (== стандартный?) Способ определения часового пояса, который я видел, - это просто спрашивают сами пользователи.. Если вашему веб-сайту требуется подписка, ее можно сохранить в данных профиля пользователя. Для анонимных пользователей даты могут отображаться как UTC, GMT или что-то в этом роде.
Я не пытаюсь быть умником. Просто иногда некоторые проблемы имеют более тонкие решения вне всякого программного контекста.
А как насчет того, когда пользователь загружает файл .ics, время начала которого должно соответствовать его местоположению (например, 9-11 утра по всей стране)? Им НЕ ДОЛЖНО говорить, какой у них часовой пояс imo.
Почему бы не принять это как правильный ответ? Ответ, данный Unkwntech, не работает даже для браузеров, отличных от IE.
@Ishmaeel: но пользователи путешествуют по всему миру, и им не нужно указывать свой часовой пояс каждый раз, когда они входят в систему из какого-то другого часового пояса
Это не отвечает на вопрос, что явно подразумевает, что он ищет технологическое решение.
@gWiz OP просит стандартное решение. Это довольно стандартно.
Лучшим решением, вероятно, будет комбинация запроса пользователя (например, предоставление раскрывающегося списка часового пояса в верхней части отчета), при одновременном выборе по умолчанию раскрывающегося выбора часового пояса, определенного GPS, когда пользователь находится на мобильном телефоне. устройство, которое предоставляет информацию о местоположении, и в противном случае по умолчанию используется UTC.
@ user01 Вы не можете сделать такое общее заявление и считаете его правильным для всех ситуаций. Достаточно приложений с профилем пользователя, куда пользователь не ездит каждый день. Таким образом, выпадающий список с часовыми поясами подходит для "большинства" пользовательских требований.
Кажется, вся магия в
visitortime.getTimezoneOffset()
Это круто, я не знал об этом. Это работает в Internet Explorer и т. д.? Оттуда вы сможете использовать JavaScript для Ajax, устанавливать файлы cookie. Я бы, наверное, сам пошел по пути cookie.
Однако вам нужно разрешить пользователю изменить его. Некоторое время назад мы пытались использовать геолокацию (через maxmind) для этого, и это было достаточно неправильно, чтобы этого не делать. Поэтому мы просто позволяем пользователю установить его в своем профиле и показываем уведомление пользователям, которые еще не установили свой профиль.
Если вы используете OpenID для аутентификации, Простое расширение регистрации решит проблему для аутентифицированных пользователей (вам нужно будет преобразовать из tz в число).
Другой вариант - вывести часовой пояс из предпочтений страны пользовательского агента. Это несколько грубый метод (не работает для en-US), но дает хорошее приближение.
-new Date().getTimezoneOffset()/60;
Метод getTimezoneOffset() вычтет ваше время из GMT и вернет количество минут. Так что, если вы живете в GMT-8, он вернет 480.
Чтобы выразить это в часах, разделите на 60. Также обратите внимание, что знак противоположен тому, что вам нужно - он вычисляет смещение GMT от вашего часового пояса, а не смещение вашего часового пояса от GMT. Чтобы исправить это, просто умножьте на -1.
Также обратите внимание, что w3school говорит:
The returned value is not a constant, because of the practice of using Daylight Saving Time.
это то, что имеет для меня наибольший смысл. есть ли причина, по которой это не следует использовать, или все выше просто делают проблему более сложной, чем им нужно.
@jordanstephens Я не эксперт, поэтому не знаю, есть ли обстоятельства, при которых это не сработает, но у меня это сработало.
А как насчет пользователей сотовых телефонов с браузерами без поддержки javascript? Мне нравится вопрос, когда пользователь спрашивает о HTTP-заголовках, пользовательском агенте ... есть ли способ сделать эту работу на стороне сервера как можно более точной?
Это странно. Для меня это возвращает -4, но я нахожусь в GET, который должен быть +4 - что мне не хватает? Я проверил, что в моей ОС установлен правильный часовой пояс.
getTimezoneOffset () возвращает количество минут при вычитании текущего времени из времени GMT. Итак, если вы живете в Калифорнии, это PST, то есть GMT-8, так что вы отстаете на 8 часов. Вычтите это из GMT с помощью getTimezoneOffset (), и он вернет 480 минут. Если вы хотите найти свое смещение, умножьте его на -1 и разделите на 60.
Это не учитывает переход на летнее и летнее время, но ссылка, опубликованная Джозефом Ластом, учитывает: stackoverflow.com/a/5492192/462162
Это не всегда работает для летнего времени. Get timezone offset делает именно то, что написано. Это смещение. ЧАСОВАЯ ЗОНА - это фактически географическая область. Это не сработает для летнего времени, поскольку вы не знаете, в каком полушарии живет пользователь или есть ли в их стране летнее время. Почему бы вместо этого не использовать это: >>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Я прошу не согласиться с Кейо. Определение getTimezoneOffset () (согласно стандарту ECMA ecma-international.org/ecma-262/5.1/#sec-15.9.5.26): «Возвращает разницу между местным временем и временем UTC в минутах». - другими словами, следует учитывать переход на летнее время. В документации Mozilla говорится: «Переход на летнее время не позволяет этому значению быть постоянным даже для данной локали».
@xgretsch: получает смещение Текущий пользователя от GMT. Это нормально, если вы представляете другое время, которое происходит в тот же день (если текущая дата не является датой перехода, где это может быть неверно). Однако есть много часовых поясов, которые имеют одинаковое смещение от GMT, и они могут иметь разные даты перехода или не использовать летнее время.
@Keyo: вывод toTimeString зависит от реализации: ecma-international.org/ecma-262/5.1/#sec-15.9.5.4. Нет гарантии, что он будет включать название часового пояса. Также нет гарантии, что, если он делает включает имя часового пояса, он сопоставляется со всем, о чем сервер знает. Иногда он может работать в некоторых браузерах, но я бы не хотел на него полагаться.
@Mike Dimmick: Хотя это правда, сам вопрос спрашивает, есть ли способ получить смещение часового пояса, а не сам фактический часовой пояс, так что это должно быть правильно.
@Mike Dimmick: Ах, я понимаю вашу точку зрения. Я полагаю, что нет простого ответа на вопрос «каково смещение часового пояса пользователя» - вам нужно спросить «каково смещение часового пояса пользователя в определенный момент времени». Я начинаю думать, что единственный надежный способ сделать это - одно из тех ужасных решений, когда вы устанавливаете часовой пояс, распечатываете время по местному времени и сравниваете то, что у вас есть!
Здесь следует отметить одну вещь; в некоторых местах (например, в Ньюфаундленде в Канаде) часовые пояса отличаются на полчаса, так что после деления на 60 ваш ответ может быть не целым числом.
Чтобы решить вышеуказанную проблему, почему бы не получить текущее время браузера (т.е. фактическое время, а не смещение), а затем на стороне сервера определить смещение по Гринвичу, сравнив текущее время браузера с текущим временем сервера (при условии, что вы знаете собственное смещение по Гринвичу сервера). Мне это кажется наименее проблемным решением. Отсюда вы можете определить часовой пояс. В .NET, например, вы можете использовать TimeZoneInfo для циклического просмотра текущего времени в каждой зоне до тех пор, пока не будет найдено совпадение с сообщенным браузером временем (или запросить онлайн-службу времени).
Часы компьютера пользователя могут быть неправильными, и в этом случае это выйдет из строя. Например, если я отправляю учителям отчет, в котором перечислены ответы учащихся на вопросы с указанием их времени, а моя база данных хранит время в формате UTC, тогда мне нужно знать смещение часового пояса, а текущее компьютерное время пользователя будет не имеющий отношения. Единственный способ надежно получить такое смещение - это либо спросить пользователя (т.е. убедиться, что часовой пояс включен в запрос отчета, либо добавить раскрывающийся список для часового пояса над отчетом и выполнить преобразование на стороне клиента), либо определить физическое местоположение пользователя через GPS.
Вопрос спрашивает, как это определить на стороне сервера. Это код для клиента.
The returned value is not a constant, because of the practice of using Daylight Saving Time. as a Note.
Это даже не НАЧАЛО ответа на вопрос.
Вот статья (с исходным кодом), в которой объясняется, как определять и использовать локализованное время в приложении ASP.NET (VB.NET, C#):
Короче говоря, описанный подход основан на функции JavaScript getTimezoneOffset, которая возвращает значение, сохраненное в файле cookie сеанса и используемое программным кодом для корректировки значений времени между GMT и местным временем. Приятно то, что пользователю не нужно указывать часовой пояс (код делает это автоматически). Это более сложный процесс (поэтому я ссылаюсь на статью), но предоставленный код делает его действительно простым в использовании. Я подозреваю, что вы можете преобразовать логику в PHP и другие языки (если вы понимаете ASP.NET).
Ссылка мертвая. Думаю, это альтернативная ссылка: devproconnections.com/article/aspnet2/it-s-about-time-122778
Статья также доступна в формате PDF здесь: app.box.com/shared/bfvvmidtyg
Метод преобразования времени сервера UTC в время локального клиента, описанный в этой статье, неверен. Использование текущего смещения клиента для настройки времени UTC на сервере приведет к неправильному «местному» времени в течение полугода для локалей клиента, которые соблюдают летнее время. Рассмотрим следующий сценарий: клиент в Великобритании 14 января 2013 г. (GMT + 0000 Стандартное время) устанавливает дату и время 21 августа 2015 г., 14:00 (GMT + 0100, летнее время). Это нормализуется на сервере до 21 августа 2015 г., 13:00 UTC. В день, когда это происходит, смещение клиента равно 0, поэтому время, отправленное обратно клиенту, будет 21 августа 2015 года, 13:00.
Верно, но я не утверждал, что это пуленепробиваемое решение. Если вам нужно внедрить действительно чувствительное ко времени решение, например приложение для бронирования билетов на поезд, то вам нужно найти более полное (и комплексное) решение. Однако для многих приложений это не будет проблемой. Потому что во многих случаях мы хотим локализовать значения GMT для текущего сеанса. Теперь, если у вас есть приложение, которому необходимо сохранять временную метку для некоторых даже в будущем, и оно не может поддерживать DTS, тогда правильным способом будет предоставить возможность экономии времени непосредственно в GMT. Если знаете вариант получше, поделитесь, пожалуйста.
С помощью функции PHP date вы получите дату и время сервера, на котором расположен сайт. Единственный способ получить время пользователя - использовать JavaScript.
Но я предлагаю вам сделать это, если для вашего сайта требуется регистрация, тогда лучший способ - попросить пользователя сделать регистрацию в качестве обязательного поля. Вы можете указать различные часовые пояса на странице регистрации и сохранить их в базе данных. После этого, если пользователь входит на сайт, вы можете установить часовой пояс по умолчанию для этого сеанса в соответствии с выбранным пользователем часовым поясом.
Вы можете установить любой конкретный часовой пояс с помощью функции PHP date_default_timezone_set. Это устанавливает указанный часовой пояс для пользователей.
В основном часовой пояс пользователя переходит на сторону клиента, поэтому для этого мы должны использовать JavaScript.
Ниже приведен скрипт для получения часового пояса пользователей с помощью PHP и JavaScript.
<?php
#http://www.php.net/manual/en/timezones.php List of Time Zones
function showclienttime()
{
if (!isset($_COOKIE['GMT_bias']))
{
?>
<script type = "text/javascript">
var Cookies = {};
Cookies.create = function (name, value, days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires = " + date.toGMTString();
}
else {
var expires = "";
}
document.cookie = name + " = " + value + expires + "; path=/";
this[name] = value;
}
var now = new Date();
Cookies.create("GMT_bias",now.getTimezoneOffset(),1);
window.location = "<?php echo $_SERVER['PHP_SELF'];?>";
</script>
<?php
}
else {
$fct_clientbias = $_COOKIE['GMT_bias'];
}
$fct_servertimedata = gettimeofday();
$fct_servertime = $fct_servertimedata['sec'];
$fct_serverbias = $fct_servertimedata['minuteswest'];
$fct_totalbias = $fct_serverbias – $fct_clientbias;
$fct_totalbias = $fct_totalbias * 60;
$fct_clienttimestamp = $fct_servertime + $fct_totalbias;
$fct_time = time();
$fct_year = strftime("%Y", $fct_clienttimestamp);
$fct_month = strftime("%B", $fct_clienttimestamp);
$fct_day = strftime("%d", $fct_clienttimestamp);
$fct_hour = strftime("%I", $fct_clienttimestamp);
$fct_minute = strftime("%M", $fct_clienttimestamp);
$fct_second = strftime("%S", $fct_clienttimestamp);
$fct_am_pm = strftime("%p", $fct_clienttimestamp);
echo $fct_day.", ".$fct_month." ".$fct_year." ( ".$fct_hour.":".$fct_minute.":".$fct_second." ".$fct_am_pm." )";
}
showclienttime();
?>
Но, на мой взгляд, лучше спросить пользователей, обязательна ли регистрация в вашем проекте.
Вот более полный способ.
Ниже приводится отрывок:
function TimezoneDetect(){
var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
var intMonth;
var intHoursUtc;
var intHours;
var intDaysMultiplyBy;
// Go through each month to find the lowest offset to account for DST
for (intMonth=0;intMonth < 12;intMonth++){
//go to the next month
dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);
// To ignore daylight saving time look for the lowest offset.
// Since, during DST, the clock moves forward, it'll be a bigger number.
if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
intOffset = (dtDate.getTimezoneOffset() * (-1));
}
}
return intOffset;
}
Получение TZ и DST из JS (через Way Back Machine)
Это сработало для меня! Прочтите комментарии под сообщением в блоге, чтобы узнать о нескольких обновлениях кода.
Это по-прежнему будет возвращать только стандартное смещение для часового пояса, например +02: 00. Он не даст вам достаточно информации, чтобы определить часовой пояс пользователя, такого как Africa/Johannesburg или Europe/Istanbul. См. вики по тегу часового пояса.
Используя подход Unkwntech, я написал функцию с использованием jQuery и PHP. Это проверено и работает!
На странице PHP, где вы хотите использовать часовой пояс в качестве переменной, разместите этот фрагмент кода где-нибудь в верхней части страницы:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
Будет прочитана переменная сеанса «время», которую мы сейчас создаем.
На той же странице в
, you need to first of all include jQuery:<script type = "text/javascript" src = "http://code.jquery.com/jquery-latest.min.js"></script>
Также в
, below the jQuery, paste this:<script type = "text/javascript">
$(document).ready(function() {
if ("<?php echo $timezone; ?>".length==0){
var visitortime = new Date();
var visitortimezone = "GMT " + -visitortime.getTimezoneOffset()/60;
$.ajax({
type: "GET",
url: "http://example.org/timezone.php",
data: 'time='+ visitortimezone,
success: function(){
location.reload();
}
});
}
});
</script>
Возможно, вы заметили или не заметили, но вам нужно изменить URL-адрес на ваш реальный домен.
Последняя вещь. Вам, наверное, интересно, что такое timezone.php. Ну, это просто: (создайте новый файл с именем timezone.php и укажите на него указанным выше URL)
<?php
session_start();
$_SESSION['time'] = $_GET['time'];
?>
Если это работает правильно, он сначала загрузит страницу, выполнит JavaScript и перезагрузит страницу. После этого вы сможете прочитать переменную $ timezone и использовать ее в свое удовольствие! Он возвращает текущее смещение часового пояса UTC / GMT (GMT -7) или любой другой часовой пояс, в котором вы находитесь.
мне это нравится, но у меня может быть что-то, что проверяет текущий $ _SESSION ['time'] и заставляет javascript перезагружаться только в том случае, если он отличается
Вероятно, проще использовать cookie, чем сеанс, чтобы передать это, поскольку блокировка и десериализация сеанса PHP может вызвать замедление работы вашего приложения. Для максимальной эффективности вы можете скопировать значение в сеанс и удалить файл cookie, чтобы он не отправлялся в последующих запросах.
JavaScript:
function maketimus(timestampz)
{
var linktime = new Date(timestampz * 1000);
var linkday = linktime.getDate();
var freakingmonths = new Array();
freakingmonths[0] = "jan";
freakingmonths[1] = "feb";
freakingmonths[2] = "mar";
freakingmonths[3] = "apr";
freakingmonths[4] = "may";
freakingmonths[5] = "jun";
freakingmonths[6] = "jul";
freakingmonths[7] = "aug";
freakingmonths[8] = "sep";
freakingmonths[9] = "oct";
freakingmonths[10] = "nov";
freakingmonths[11] = "dec";
var linkmonthnum = linktime.getMonth();
var linkmonth = freakingmonths[linkmonthnum];
var linkyear = linktime.getFullYear();
var linkhour = linktime.getHours();
var linkminute = linktime.getMinutes();
if (linkminute < 10)
{
linkminute = "0" + linkminute;
}
var fomratedtime = linkday + linkmonth + linkyear + " " +
linkhour + ":" + linkminute + "h";
return fomratedtime;
}
Просто предоставьте этой функции свое время в формате временной метки Unix; JavaScript уже знает часовой пояс пользователя.
Так:
PHP:
echo '<script type = "text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';
Это всегда будет показывать время правильно в зависимости от часового пояса, установленного человеком на часах своего компьютера. Нет нужды ни у кого просить и сохранять по местам, слава богу!
$ unix_timestamp_ofshiz? Здесь чего-то не хватает и что-то не работает, хотя кажется, что это может быть хорошим ответом.
Простой способ сделать это - использовать:
new Date().getTimezoneOffset();
Почему вы репостили идентичный ответ (от Джона Исаакса) 2 года назад: stackoverflow.com/a/1809974/836407?
Кроме того, он возвращает только смещение часового пояса Текущий, но не часовой пояс. См. вики по тегу часового пояса.
Вот как я это делаю. Это установит часовой пояс PHP по умолчанию на местный часовой пояс пользователя. Просто вставьте следующее вверху всех своих страниц:
<?php
session_start();
if (!isset($_SESSION['timezone']))
{
if (!isset($_REQUEST['offset']))
{
?>
<script>
var d = new Date()
var offset= -d.getTimezoneOffset()/60;
location.href = "<?php echo $_SERVER['PHP_SELF']; ?>?offset = "+offset;
</script>
<?php
}
else
{
$zonelist = array('Kwajalein' => -12.00, 'Pacific/Midway' => -11.00, 'Pacific/Honolulu' => -10.00, 'America/Anchorage' => -9.00, 'America/Los_Angeles' => -8.00, 'America/Denver' => -7.00, 'America/Tegucigalpa' => -6.00, 'America/New_York' => -5.00, 'America/Caracas' => -4.30, 'America/Halifax' => -4.00, 'America/St_Johns' => -3.30, 'America/Argentina/Buenos_Aires' => -3.00, 'America/Sao_Paulo' => -3.00, 'Atlantic/South_Georgia' => -2.00, 'Atlantic/Azores' => -1.00, 'Europe/Dublin' => 0, 'Europe/Belgrade' => 1.00, 'Europe/Minsk' => 2.00, 'Asia/Kuwait' => 3.00, 'Asia/Tehran' => 3.30, 'Asia/Muscat' => 4.00, 'Asia/Yekaterinburg' => 5.00, 'Asia/Kolkata' => 5.30, 'Asia/Katmandu' => 5.45, 'Asia/Dhaka' => 6.00, 'Asia/Rangoon' => 6.30, 'Asia/Krasnoyarsk' => 7.00, 'Asia/Brunei' => 8.00, 'Asia/Seoul' => 9.00, 'Australia/Darwin' => 9.30, 'Australia/Canberra' => 10.00, 'Asia/Magadan' => 11.00, 'Pacific/Fiji' => 12.00, 'Pacific/Tongatapu' => 13.00);
$index = array_keys($zonelist, $_REQUEST['offset']);
$_SESSION['timezone'] = $index[0];
}
}
date_default_timezone_set($_SESSION['timezone']);
//rest of your code goes here
?>
Это не учитывает корректировки "летнего времени" - пользователь в Дублине будет соответствовать вашему "Европа / Дублин" зимой, но "Европа / Белград" летом. Если вы собираетесь использовать текущее смещение, все, что вы можете разумно предположить, - это смещение, а не географический идентификатор.
Легко, просто используйте функцию JavaScript getTimezoneOffset вот так:
-new Date().getTimezoneOffset()/60;
Кроме того, он возвращает только смещение часового пояса Текущий, но не часовой пояс. См. вики по тегу часового пояса.
Это всего лишь копия принятого ответа, почему вы даже голосуете за него.
Попробуйте этот код PHP:
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$json = file_get_contents("http://api.easyjquery.com/ips/?ip = " . $ip . "&full=true");
$json = json_decode($json,true);
$timezone = $json['LocalTimeZone'];
?>
Вот надежное решение JavaScript для определения часового пояса, в котором находится браузер.
>>> var timezone = jstz.determine();
>>> timezone.name();
"Europe/London"
https://github.com/pellepim/jstimezonedetect
Ответы только по ссылкам не приветствуются, потому что, если ссылка исчезает, ответ перестает быть полезным; и потому, что, не переходя по ссылке, читатели не знают, дает ли она хороший ответ. В этом случае вы могли бы пояснить, что это сторонняя библиотека, которая использует подход к идентификации на основе базы данных, и, возможно, объяснить некоторые принципы ее работы.
Этот! Это путь. Простая библиотека, правильно обрабатывает DST. Другие ответы полны WTF, и многие не используют DST.
Эта библиотека очень умная. Он работает, запрашивая текущее смещение к UTC, затем корректируя время объекта JavaScript Date, добавляя или вычитая секунды до тех пор, пока смещение к UTC не изменится. Используя этот метод, эта библиотека определяет достаточно много изменений DST, чтобы однозначно определить часовой пояс. Я думаю, что библиотека могла бы иметь еще лучшую производительность, если бы выполняла двоичный поиск вместо линейного. Возвращаемое значение - это информационный ключ зоны IANA (также известный как база данных часовых поясов Олсона).
Эта библиотека больше не нужна. Современные браузеры поддерживают Intl API, который возвращает строку часового пояса IANA. См. этот ответ.
Я до сих пор не видел здесь подробного ответа, который получает часовой пояс. Вам не нужно геокодировать по IP-адресу, использовать PHP (смеется) или неправильно угадывать смещение.
Во-первых, часовой пояс - это не просто смещение от GMT. Это участок земли, на котором правила времени устанавливаются местными стандартами. В некоторых странах действует летнее время, и они переходят на летнее время в разное время. Обычно важно получить фактическую зону, а не только текущее смещение.
Если вы собираетесь сохранить этот часовой пояс, например, в пользовательских настройках вам нужна зона, а не только смещение. Для конверсий в реальном времени это не имеет большого значения.
Теперь, чтобы получить часовой пояс с помощью javascript, вы можете использовать это:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
Однако мне было проще просто использовать этот надежный плагин, который возвращает часовой пояс в формате Olsen:
Для отправки смещения часового пояса в виде HTTP-заголовка на запросы AJAX с jQuery
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
}
});
Вы также можете сделать что-то подобное, чтобы получить фактическое имя часового пояса, используя moment.tz.guess(); из http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/
Это возвращает только смещение часового пояса Текущий, но не часовой пояс. См. вики по тегу часового пояса.
Отредактировано, чтобы включить информацию о том, как сделать то же самое для имени часового пояса.
Не используйте IP-адрес для окончательного определения местоположения (и, следовательно, часового пояса) - это потому, что с NAT, прокси-серверами (которые становятся все более популярными) и VPN, IP-адреса не обязательно реалистично отражают фактическое местоположение пользователя, но местоположение, в котором серверы, реализующие эти протоколы, постоянно находятся.
Подобно тому, как коды городов США больше не используются для поиска пользователя телефона, учитывая популярность переносимости номеров.
IP-адрес и другие методы, показанные выше, полезны для предлагая дефолт, которые пользователь может настроить / исправить.
Во-первых, поймите, что определение часового пояса в JavaScript несовершенно. Вы можете получить локальный смещение часового пояса для определенной даты и времени, используя getTimezoneOffset на экземпляре объекта Date, но это не совсем то же самое, что полный Часовой пояс IANA, такой как America/Los_Angeles.
Однако есть несколько вариантов, которые могут работать:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.info(tzid);Результатом является строка, содержащая настройку часового пояса IANA для компьютера, на котором выполняется код.
Поддерживаемые среды перечислены в таблице совместимости Intl. Разверните раздел DateTimeFormat и посмотрите на функцию resolvedOptions().timeZone defaults to the host environment.
Некоторые библиотеки, такие как Люксон, используют этот API для определения часового пояса с помощью таких функций, как luxon.Settings.defaultZoneName.
Если вам нужно поддерживать более широкий набор сред, например старые веб-браузеры, вы можете использовать библиотеку для создания обоснованное предположение в часовом поясе. Они работают, сначала пробуя API Intl, если он доступен, а когда он недоступен, они опрашивают функцию getTimezoneOffset объекта Date для нескольких разных моментов времени, используя результаты для выбора подходящего часового пояса из внутреннего набора данных.
И jsTimezoneDetect, и момент-часовой пояс имеют эту функцию.
// using jsTimeZoneDetect
var tzid = jstz.determine().name();
// using moment-timezone
var tzid = moment.tz.guess();
В обоих случаях результат можно рассматривать только как предположение. Предположение может быть верным во многих случаях, но не во всех.
Кроме того, эти библиотеки необходимо периодически обновлять, чтобы противодействовать тому факту, что многие старые реализации JavaScript знают только о правиле перехода на летнее время Текущий для своего местного часового пояса. Подробнее об этом здесь.
В конечном итоге, лучший подход - спросить пользователя об их часовом поясе. Обеспечьте настройку, которую они могут изменить. Вы можете использовать один из вышеперечисленных вариантов, чтобы выбрать параметр дефолт, но не делайте невозможным отклонение от него в своем приложении.
Также существует совершенно другой подход нет, основанный на настройке часового пояса на компьютере пользователя. Вместо этого, если вы можете собрать координаты широты и долготы, вы можете преобразовать их в часовой пояс с помощью один из этих методов. Это хорошо работает на мобильных устройствах.
Использование географического положения пользователя (т. Е. Его локали) для определения часового пояса также является ошибочным. Пользователи могут захотеть использовать на своем устройстве определенный часовой пояс, который не является местным часовым поясом, даже если он может отображать то же время (или нет). Например. путешественники часто оставляют свои устройства с часовым поясом, установленным на их обычное местоположение, и не ожидают, что даты и время будут использовать другое смещение без уведомления. Я могу говорить здесь из личного опыта… ;-)
Не могу сказать, троллит ли ты меня, Роб. ;) Но ни один из этих подходов не использует их локаль, а скорее настройку на устройстве, так что согласуется с вашей точкой зрения. (Только альтернативный подход, упомянутый в последнем абзаце, будет использовать текущее местоположение.)
Подключаемся к терминологическому примечанию: "locale" подчеркнуто нет - географическое положение пользователя. «Локаль» - это группа настроек, таких как язык, числовой формат, календарь и т. д. Например, локаль de_DE определяет немецкий как язык по умолчанию, евро как валюту по умолчанию, запятые как десятичный разделитель, точки как разделитель тысяч и григорианский как календарь. См. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Один из возможных вариантов - использовать поле заголовка Date, которое определено в RFC 7231 и должно включать часовой пояс. Конечно, не гарантируется, что значение действительно соответствует часовому поясу клиента, но это может быть удобной отправной точкой.
К сожалению, этот заголовок, по-видимому, в основном предназначен для ответов, а не для запросов: «Пользовательский агент МОЖЕТ отправить поле заголовка Date в запросе, хотя обычно не будет этого делать, если не предполагается, что он передает полезную информацию серверу». Я только что проверил, а Firefox не отправляет.
С JavaScript и PHP это просто:
Несмотря на то, что пользователь может испортить свои внутренние часы и / или часовой пояс, лучший способ, который я нашел до сих пор, чтобы получить смещение, - это new Date().getTimezoneOffset();. Это неинвазивно, не вызывает головной боли и избавляет от необходимости полагаться на третьих лиц.
Скажем, у меня есть таблица users, которая содержит поле date_created int(13) для хранения временных меток Unix;
Предполагая, что клиент creates a new account, данные получает post, и мне нужно, чтобы insert/updatedate_created column с меткой времени Unix клиента, а не сервера.
Поскольку timezoneOffset требуется во время вставки / обновления, он передается как дополнительный элемент $ _POST, когда клиент отправляет форму, что устраняет необходимость хранить его в сеансах и / или файлах cookie, а также не требует дополнительных обращений к серверу.
var off = (-new Date().getTimezoneOffset()/60).toString();//note the '-' in front which makes it return positive for negative offsets and negative for positive offsets
var tzo = off == '0' ? 'GMT' : off.indexOf('-') > -1 ? 'GMT'+off : 'GMT+'+off;
Скажем, сервер получает tzo как $_POST['tzo'];
$ts = new DateTime('now', new DateTimeZone($_POST['tzo']);
$user_time = $ts->format("F j, Y, g:i a");//will return the users current time in readable format, regardless of whether date_default_timezone() is set or not.
$user_timestamp = strtotime($user_time);
Вставьте / обновите date_created=$user_timestamp.
При получении date_created вы можете преобразовать метку времени следующим образом:
$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever
Теперь этот пример может соответствовать вашим потребностям, когда дело доходит до вставки метки времени first ... Когда дело доходит до дополнительной метки времени или таблицы, вы можете подумать о вставке значения tzo в таблицу пользователей для дальнейшего использования или настройки это как сеанс или как файл cookie.
P.S. НО что, если пользователь путешествует и меняет часовые пояса. Вход в систему в GMT + 4, быстрый переход в GMT-1 и повторный вход. Последний вход будет в будущем.
Я думаю ... мы слишком много думаем.
Вы можете сделать это на клиенте с помощью момент-часовой пояс и отправить значение на сервер; пример использования:
> moment.tz.guess()
"America/Asuncion"
В настоящее время я больше не рекомендую moment.js. В настоящее время существуют гораздо меньшие альтернативы (dayjs, дата-фнс). Момент огромный.
Получение действительного имени часового пояса базы данных TZ в PHP - это двухэтапный процесс:
С помощью JavaScript можно получить смещение часового пояса в минутах через getTimezoneOffset. Это смещение будет положительным, если местный часовой пояс отстает от UTC, и отрицательным, если он опережает. Таким образом, вы должны добавить к смещению противоположный знак.
var timezone_offset_minutes = new Date().getTimezoneOffset();
timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;
Передайте это смещение в PHP.
В PHP преобразуйте это смещение в действительное имя часового пояса с помощью функции timezone_name_from_abbr.
// Just an example.
$timezone_offset_minutes = -360; // $_GET['timezone_offset_minutes']
// Convert minutes to seconds
$timezone_name = timezone_name_from_abbr("", $timezone_offset_minutes*60, false);
// America/Chicago
echo $timezone_name;</code></pre>
Я написал об этом сообщение в блоге: Как определить часовой пояс пользователя в PHP. Он также содержит демо.
Я думаю, что более простой процесс - вызвать Intl.DateTimeFormat().resolvedOptions().timeZone и отправить его на веб-сервер. Ссылка: stackoverflow.com/questions/9772955/…
Нет такого способа определить часовой пояс в реальном HTML-коде или любой строке user-agent, но вы можете сделать базовую функцию, получая ее с помощью JavaScript.
Я пока не знаю, как писать код на JavaScript, поэтому выполнение моей функции может занять время.
Однако вы можете попытаться получить фактический часовой пояс также с помощью JavaScript с функцией getTzimezoneOffset() в разделе Date или просто new Date().getTimezoneOffset();.
Спросите пользователя. Если вы получаете часовой пояс с компьютера пользователя, и он установлен неверно, что тогда?