Чи існує стандартний спосіб веб-сервера мати можливість визначати часовий пояс користувача в межах веб-сторінки?
Можливо, із заголовка HTTP або частини user-agent
рядка?
Чи існує стандартний спосіб веб-сервера мати можливість визначати часовий пояс користувача в межах веб-сторінки?
Можливо, із заголовка HTTP або частини user-agent
рядка?
Відповіді:
-new Date().getTimezoneOffset()/60;
Метод getTimezoneOffset()
відніме ваш час від GMT і поверне кількість хвилин. Тож якщо ви живете в GMT-8, він поверне 480.
Щоб розмістити це на години, розділіть на 60. Також зауважте, що знак протилежний тому, що вам потрібно - це обчислення зміщення GMT від вашого часового поясу, а не зміщення часового поясу від GMT. Щоб виправити це, просто помножте на -1.
Також зауважте, що w3school говорить:
Повернене значення не є постійною через практику використання літнього часу.
>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Найпопулярніший (== стандарт?) Спосіб визначення часового поясу, який я бачив, - це просто запитати самих користувачів. Якщо ваш веб-сайт вимагає підписки, це може бути збережено в даних профілю користувачів. Для інших користувачів дати можуть відображатися як UTC чи GMT або деякі такі.
Я не намагаюся бути розумним гаком. Просто іноді деякі проблеми мають тонші рішення поза будь-яким контекстом програмування.
Наразі немає заголовків HTTP, які б повідомляли про часовий пояс клієнтів, хоча було запропоновано включити його до специфікації HTTP.
Якби це я, я, мабуть, спробував би домогтися часового поясу за допомогою JavaScript JavaScript JavaScript, а потім подати його на сервер за допомогою Ajax або чогось іншого.
JavaScript - це найпростіший спосіб отримати місцевий час клієнта. Я б запропонував використовувати XMLHttpRequest для повернення місцевого часу, і якщо це не вдасться, повернутися до виявленого часового поясу на основі їх IP-адреси.
Що стосується геолокації, я використовував MaxMind GeoIP у кількох проектах, і він працює добре, хоча я не впевнений, чи вони надають дані часового поясу. Це послуга, яку ви платите, і вони щомісяця оновлюють вашу базу даних. Вони надають обгортки декількома веб-мовами.
По-перше, зрозумійте, що виявлення часового поясу в JavaScript недосконале. Ви можете отримати зміщення локального часового поясу на певну дату та час, використовуючи getTimezoneOffset
примірник Date
об'єкта, але це не зовсім так, як повний часовий пояс IANA, якAmerica/Los_Angeles
.
Є деякі варіанти, які можуть працювати:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tzid);
Результат - рядок, що містить налаштування часового поясу IANA комп'ютера, на якому працює код.
Підтримувані середовища перераховані в таблиці сумісності Intl . Розгорніть DateTimeFormat
розділ і подивіться на функцію з назвою resolvedOptions().timeZone defaults to the host environment
.
Деякі бібліотеки, наприклад, Luxon, використовують цей API для визначення часового поясу за допомогою таких функцій luxon.Settings.defaultZoneName
.
Intl
API, якщо він доступний, а коли він недоступний, вони допитують getTimezoneOffset
функцію Date
об'єкта протягом декількох різних моментів часу, використовуючи результати, щоб вибрати відповідний часовий пояс із внутрішнього набору даних.І jsTimezoneDetect, і часовий пояс мають цю функціональність.
// using jsTimeZoneDetect
var tzid = jstz.determine().name();
// using moment-timezone
var tzid = moment.tz.guess();
В обох випадках результат можна вважати лише здогадкою. Здогадка може бути правильною у багатьох випадках, але не у всіх.
Крім того, ці бібліотеки повинні періодично оновлюватися, щоб протидіяти тому, що багато старих реалізацій JavaScript знають лише поточне правило літнього часу для свого локального часового поясу. Детальніше про це тут.
Зрештою, кращим підходом є фактично запитати у користувача про їх часовий пояс. Надайте налаштування, яке вони можуть змінити. Ви можете скористатися одним із перерахованих вище варіантів, щоб вибрати налаштування за замовчуванням , але не унеможливлюйте відхилення від цього у вашому додатку.
Існує також зовсім інший підхід взагалі не покладатися на налаштування часового поясу комп'ютера користувача. Натомість, якщо ви можете зібрати координати широти та довготи, ви можете вирішити їх у часовому поясі, використовуючи один із цих методів . Це добре працює на мобільних пристроях.
Ось надійне рішення JavaScript для визначення часового поясу браузера.
>>> var timezone = jstz.determine();
>>> timezone.name();
"Europe/London"
https://bitbucket.org/pellepim/jstimezonedetect
Додаток 1: Зараз цей проект розміщено на GitHub: https://github.com/pellepim/jstimezonedetect
Ось більш повний спосіб.
Уривок наведено нижче:
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)
Africa/Johannesburg
або Europe/Istanbul
. Дивіться вікі тегів часового поясу .
Використовуючи підхід Unkwntech, я написав функцію за допомогою jQuery та PHP. Це перевірено і працює!
На сторінці PHP, де ви хочете мати часовий пояс як змінну, розмістіть цей фрагмент коду десь у верхній частині сторінки:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
Це буде читати змінну сесії "час", яку ми зараз збираємося створити.
На цій же сторінці, в <head>, перш за все, потрібно включити jQuery:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
Також у <head> під jQuery вставте це:
<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 і перезавантажить сторінку. Після цього ви зможете прочитати змінну часового поясу $ та використовувати її для свого задоволення! Він повертає поточне зміщення часового поясу UTC / GMT (GMT -7) або будь-який часовий пояс.
Щоб подати зміщення часового поясу у вигляді заголовка 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-адресою або використовувати PHP (lol) або неправильно здогадуватися від компенсації.
По-перше, часовий пояс - це не просто зміщення від GMT. Це ділянка землі, в якій норми часу встановлені місцевими стандартами. Деякі країни мають економію денного світла, і вони включатимуть DST у різний час. Зазвичай важливо отримати фактичну зону, а не лише поточне зміщення.
Якщо ви маєте намір зберігати цей часовий пояс, наприклад, у налаштуваннях користувачів, ви хочете, щоб зона, а не лише зміщення. Для конверсій у режимі реального часу це не має великого значення.
Тепер, щоб отримати часовий пояс за допомогою JavaScript, ви можете скористатися цим:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
Однак мені було простіше просто використовувати цей надійний плагін, який повертає часовий пояс, відформатований Olsen:
За допомогою date
функції PHP ви отримаєте час дати сервера, на якому знаходиться сайт. Єдиний спосіб отримати час користувача - це використовувати 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();
?>
Але, на мою точку зору, краще запитати користувачів, чи обов’язкова реєстрація у вашому проекті.
Не використовуйте IP-адресу для остаточного визначення місця розташування (а отже, і часового поясу) - це тому, що з NAT, проксі-серверами (все більш популярними) та VPN-адресами, IP-адреси не обов'язково реально відображають фактичне місцезнаходження користувача, але місце, у якому проживають сервери, що реалізують ці протоколи.
Подібно до того, як американські місцеві коди більше не корисні для пошуку телефонного користувача, враховуючи популярність переносу номерів.
IP-адреса та інші методи, показані вище, корисні для того, щоб запропонувати користувачеві налаштування / виправлення за замовчуванням .
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>';
Це завжди показуватиме правильний час залежно від часового поясу, який людина встановила на годиннику комп'ютера. Не потрібно нікому нічого просити і зберігати на місцях, слава богу!
Просто, просто використовуйте функцію JavaScript getTimezoneOffset
так:
-new Date().getTimezoneOffset()/60;
Магія все, здається, в
visitortime.getTimezoneOffset()
Це здорово, я про це не знав. Чи працює це в Internet Explorer тощо? Звідти ви повинні мати можливість використовувати JavaScript в Ajax, встановлювати файли cookie, що завгодно. Я б, мабуть, пішов самим маршрутом печива.
Вам потрібно буде дозволити користувачеві його змінити. Ми намагалися використовувати геолокацію (через maxmind), щоб зробити це деякий час тому, і це було помилково досить часто - достатньо, щоб зробити це не варто, тому ми просто дозволили користувачеві встановити його у своєму профілі та показати сповіщення користувачам, які ще не встановили свої.
Ось стаття (із вихідним кодом), яка пояснює, як визначити та використовувати локалізований час у додатку ASP.NET (VB.NET, C #):
Коротше кажучи, описаний підхід покладається на функцію JavaScript getTimezoneOffset
, яка повертає значення, яке зберігається в файлі cookie сеансу і використовується кодовим відставанням для налаштування значень часу між GMT та місцевим часом. Приємно те, що користувачеві не потрібно вказувати часовий пояс (код робить це автоматично). Є більше залучених (саме тому я посилаюсь на статтю), але наданий код робить його дійсно простим у використанні. Я підозрюю, що ви можете перетворити логіку на PHP та інші мови (поки ви розумієте ASP.NET).
Якщо ви використовуєте OpenID для аутентифікації, Просте розширення реєстрації вирішить проблему для аутентифікованих користувачів (Вам потрібно буде перетворити з tz в числовий).
Іншим варіантом може бути висновок про часовий пояс із переваг країни-агента користувача. Це дещо сирий метод (не працюватиме для en-US), але робить хороше наближення.
З JavaScript і PHP це просто:
Незважаючи на те, що користувач може возитися зі своїм внутрішнім годинником та / або часовим поясом, найкращим способом, який я знайшов поки що, отримати компенсацію, залишається new Date().getTimezoneOffset();
. Це неінвазивно, не болить головами і позбавляє від необхідності покладатися на сторонніх осіб.
Скажіть, у мене є таблиця users
, яка містить полеdate_created int(13)
для зберігання часових позначок Unix;
Припускаючи , що клієнт creates a new account
, дані приймаються post
, і мені потрібноinsert/update
date_created column
з Відмітка часу Unix клієнта, а на серверах.
Оскільки timezoneOffset потрібен під час вставки / оновлення, він передається як додатковий елемент $ _POST, коли клієнт подає форму, тим самим усуваючи необхідність зберігати її в сесіях та / або кукі, а також додаткові сервери не звертаються.
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
.
Отримавши дата_create, ви можете конвертувати часову позначку так:
$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.
PS АЛЕ що робити, якщо користувач подорожує та перемикає часові пояси. Увійдіть у систему GMT + 4, швидко переходите до GMT-1 та знову входите в систему. Останнє вхід буде в майбутньому.
Я думаю ... ми занадто багато думаємо.
Ви можете зробити це на клієнті з моментним часовим поясом і надіслати значення серверу; використання вибірки:
> moment.tz.guess()
"America/Asuncion"
Отримання дійсного імені часового поясу бази даних 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/…
Простий спосіб зробити це за допомогою:
new Date().getTimezoneOffset();
Одним із можливих варіантів є використання Date
поля заголовка, яке визначено в RFC 7231 і, як передбачається, включає часовий пояс. Звичайно, не гарантується, що це дійсно часовий пояс клієнта, але це може бути зручною відправною точкою.
Ось як я це роблю. Це встановить часовий пояс 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
?>