Existe uma maneira padrão de um servidor Web determinar o fuso horário de um usuário em uma página da Web?
Talvez de um cabeçalho HTTP ou parte da user-agent
string?
Existe uma maneira padrão de um servidor Web determinar o fuso horário de um usuário em uma página da Web?
Talvez de um cabeçalho HTTP ou parte da user-agent
string?
Respostas:
-new Date().getTimezoneOffset()/60;
O método getTimezoneOffset()
subtrairá seu tempo do GMT e retornará o número de minutos. Então, se você mora em GMT-8, ele retornará 480.
Para colocar isso em horas, divida por 60. Além disso, observe que o sinal é o oposto do que você precisa - está calculando o deslocamento do GMT no seu fuso horário, e não o deslocamento do GMT no seu fuso horário. Para corrigir isso, basta multiplicar por -1.
Observe também que o w3school diz:
O valor retornado não é uma constante, devido à prática de usar o horário de verão.
>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
A maneira mais popular (== padrão?) De determinar o fuso horário que eu já vi é simplesmente perguntar aos próprios usuários. Se o seu site exigir assinatura, isso poderá ser salvo nos dados do perfil dos usuários. Para usuários antigos, as datas podem ser exibidas como UTC ou GMT ou algo parecido.
Não estou tentando ser um espertinho. Às vezes, alguns problemas têm soluções melhores fora de qualquer contexto de programação.
Não há cabeçalhos HTTP que reportarão o fuso horário dos clientes até o momento, embora tenha sido sugerido incluí-lo na especificação HTTP.
Se fosse eu, provavelmente tentaria buscar o fuso horário usando o JavaScript do cliente e enviá-lo ao servidor usando o Ajax ou algo assim.
JavaScript é a maneira mais fácil de obter a hora local do cliente. Sugiro usar um XMLHttpRequest para enviar de volta a hora local e, se isso falhar, retorne ao fuso horário detectado com base em seu endereço IP.
Quanto à geolocalização, usei o MaxMind GeoIP em vários projetos e funciona bem, embora não tenha certeza se eles fornecem dados de fuso horário. É um serviço pelo qual você paga e eles fornecem atualizações mensais ao seu banco de dados. Eles fornecem wrappers em vários idiomas da web.
Primeiro, entenda que a detecção de fuso horário no JavaScript é imperfeita. Você pode obter o local de deslocamento de fuso horário uma determinada data e hora usando para getTimezoneOffset
em uma instância do Date
objeto, mas isso não é bem o mesmo que um completo fuso horário IANA como America/Los_Angeles
.
Existem algumas opções que podem funcionar:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tzid);
O resultado é uma sequência que contém a configuração de fuso horário da IANA do computador em que o código está sendo executado.
Os ambientes suportados estão listados na tabela de compatibilidade Intl . Expanda a DateTimeFormat
seção e observe o recurso chamado resolvedOptions().timeZone defaults to the host environment
.
Algumas bibliotecas, como Luxon, usam essa API para determinar o fuso horário através de funções como luxon.Settings.defaultZoneName
.
Intl
API, se estiver disponível, e quando não está disponível, interrogam a getTimezoneOffset
função do Date
objeto, por vários momentos diferentes, usando os resultados para escolher um fuso horário apropriado em um conjunto de dados interno.O jsTimezoneDetect e o fuso horário do momento têm essa funcionalidade.
// using jsTimeZoneDetect
var tzid = jstz.determine().name();
// using moment-timezone
var tzid = moment.tz.guess();
Nos dois casos, o resultado pode ser considerado apenas um palpite. O palpite pode estar correto em muitos casos, mas não em todos.
Além disso, essas bibliotecas precisam ser atualizadas periodicamente para combater o fato de que muitas implementações mais antigas do JavaScript só conhecem a regra atual do horário de verão para o fuso horário local. Mais detalhes sobre isso aqui.
Por fim, uma abordagem melhor é solicitar ao usuário o fuso horário. Forneça uma configuração que eles possam alterar. Você pode usar uma das opções acima para escolher uma configuração padrão , mas não torne impossível desviar dela no seu aplicativo.
Também existe uma abordagem totalmente diferente de não depender da configuração de fuso horário do computador do usuário. Em vez disso, se você conseguir reunir coordenadas de latitude e longitude, poderá resolvê-las em um fuso horário usando um desses métodos . Isso funciona bem em dispositivos móveis.
Aqui está uma solução JavaScript robusta para determinar o fuso horário do navegador.
>>> var timezone = jstz.determine();
>>> timezone.name();
"Europe/London"
https://bitbucket.org/pellepim/jstimezonedetect
Apêndice 1: Agora, este projeto está localizado no GitHub: https://github.com/pellepim/jstimezonedetect
Aqui está uma maneira mais completa.
Um trecho está abaixo:
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;
}
Obtendo TZ e DST de JS (via Way Back Machine)
Africa/Johannesburg
ou Europe/Istanbul
. Veja o wiki da tag de fuso horário .
Usando a abordagem de Unkwntech, escrevi uma função usando jQuery e PHP. Isso é testado e funciona!
Na página PHP em que você deseja ter o fuso horário como uma variável, tenha esse trecho de código em algum lugar próximo ao topo da página:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
Isso lerá a variável de sessão "time", que estamos prestes a criar.
Na mesma página, no <head>, você precisa primeiro incluir o jQuery:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
Também no <head>, abaixo do jQuery, cole este:
<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>
Você pode ou não ter notado, mas precisa alterar o URL para o seu domínio real.
Uma última coisa. Você provavelmente está se perguntando o que diabos é o timezone.php. Bem, é simplesmente o seguinte: (crie um novo arquivo chamado timezone.php e aponte para ele com o URL acima)
<?php
session_start();
$_SESSION['time'] = $_GET['time'];
?>
Se isso funcionar corretamente, ele primeiro carregará a página, executará o JavaScript e recarregará a página. Você poderá ler a variável $ timezone e usá-la como desejar! Ele retorna o deslocamento atual do fuso horário UTC / GMT (GMT -7) ou o fuso horário em que você estiver.
Para enviar o deslocamento do fuso horário como um cabeçalho HTTP em solicitações AJAX com jQuery
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
}
});
Você também pode fazer algo semelhante para obter o nome real fuso horário utilizando moment.tz.guess();
a partir http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/
Ainda não vi uma resposta detalhada aqui que identifique o fuso horário. Você não precisa geocodificar por endereço IP ou usar PHP (lol) ou adivinhar incorretamente a partir de um deslocamento.
Em primeiro lugar, um fuso horário não é apenas um deslocamento do GMT. É uma área de terra em que as regras de tempo são definidas pelos padrões locais. Alguns países têm horário de verão e ativam o horário de verão em horários diferentes. Geralmente é importante obter a zona real, não apenas o deslocamento atual.
Se você pretende armazenar esse fuso horário, por exemplo, nas preferências do usuário, deseja a zona e não apenas o deslocamento. Para conversões em tempo real, não importa muito.
Agora, para obter o fuso horário com javascript, você pode usar isto:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
No entanto, achei mais fácil simplesmente usar esse plugin robusto que retorna o fuso horário no formato Olsen:
Com a date
função PHP , você obtém a data e hora do servidor em que o site está localizado. A única maneira de obter o tempo do usuário é usar JavaScript.
Mas eu sugiro que, se o seu site possui registro necessário, a melhor maneira é solicitar ao usuário que o registro seja obrigatório. Você pode listar vários fusos horários na página de registro e salvá-lo no banco de dados. Depois disso, se o usuário efetuar login no site, você poderá definir o fuso horário padrão para essa sessão de acordo com o fuso horário selecionado dos usuários.
Você pode definir qualquer fuso horário específico usando a função PHP date_default_timezone_set
. Isso define o fuso horário especificado para os usuários.
Basicamente, o fuso horário dos usuários vai para o lado do cliente, portanto, devemos usar JavaScript para isso.
Abaixo está o script para obter o fuso horário dos usuários usando PHP e 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();
?>
Mas, de acordo com meu ponto de vista, é melhor perguntar aos usuários se o registro é obrigatório em seu projeto.
Não use o endereço IP para determinar definitivamente o local (e, portanto, o fuso horário) - porque, com NAT, proxies (cada vez mais populares) e VPNs, os endereços IP não refletem necessariamente realisticamente o local real do usuário, mas o local no qual o servidores que implementam esses protocolos residem.
Semelhante à maneira como os códigos de área dos EUA não são mais úteis para localizar um usuário de telefone, dada a popularidade da portabilidade de números.
O endereço IP e outras técnicas mostradas acima são úteis para sugerir um padrão que o usuário pode ajustar / corrigir.
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;
}
Basta fornecer seus horários no formato de carimbo de data e hora do Unix para esta função; O JavaScript já conhece o fuso horário do usuário.
Como isso:
PHP:
echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';
Isso sempre mostrará os horários corretamente com base no fuso horário que a pessoa definiu no relógio do computador. Não há necessidade de pedir nada a ninguém e salvá-lo em lugares, graças a Deus!
Fácil, basta usar a getTimezoneOffset
função JavaScript da seguinte forma:
-new Date().getTimezoneOffset()/60;
A mágica parece estar toda
visitortime.getTimezoneOffset()
Isso é legal, eu não sabia disso. Funciona no Internet Explorer, etc? A partir daí, você poderá usar o JavaScript no Ajax, definir cookies, o que for. Eu provavelmente segui a rota dos biscoitos.
Você precisará permitir que o usuário altere isso. Tentamos usar a geolocalização (via maxmind) para fazer isso há um tempo atrás, e estava errado razoavelmente - o suficiente para fazer com que não valesse a pena, então deixamos o usuário configurá-lo em seu perfil e mostramos um aviso aos usuários que ainda não definiu o deles.
Aqui está um artigo (com código fonte) que explica como determinar e usar o tempo localizado em um aplicativo ASP.NET (VB.NET, C #):
Em resumo, a abordagem descrita depende da getTimezoneOffset
função JavaScript , que retorna o valor que é salvo no cookie da sessão e usado pelo code-behind para ajustar os valores de tempo entre GMT e hora local. O bom é que o usuário não precisa especificar o fuso horário (o código faz isso automaticamente). Há mais envolvimento (é por isso que vinculo ao artigo), mas o código fornecido facilita o uso. Suspeito que você possa converter a lógica em PHP e outras linguagens (desde que entenda o ASP.NET).
Se você estiver usando o OpenID para autenticação, o Simple Registration Extension resolveria o problema para usuários autenticados (será necessário converter de tz para numérico).
Outra opção seria deduzir o fuso horário da preferência de país do agente do usuário. Este é um método um tanto grosseiro (não funcionará para os EUA), mas faz uma boa aproximação.
É simples com JavaScript e PHP:
Mesmo que o usuário possa mexer no relógio interno e / ou no fuso horário, a melhor maneira que encontrei até agora, para obter o deslocamento, permanece new Date().getTimezoneOffset();
. É não invasivo, não dá dores de cabeça e elimina a necessidade de confiar em terceiros.
Digamos que eu tenha uma tabela, users
que contenha um campo date_created int(13)
, para armazenar registros de data e hora do Unix;
Assumindo um cliente creates a new account
, os dados são recebidos por post
, e eu preciso insert/update
o date_created column
com timestamp Unix do cliente, não o servidor do.
Como o timezoneOffset é necessário no momento da inserção / atualização, ele é passado como um elemento $ _POST extra quando o cliente envia o formulário, eliminando a necessidade de armazená-lo em sessões e / ou cookies, e nenhum servidor adicional é atingido.
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;
Digamos que o servidor receba tzo
como $_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);
Inserir / atualizar date_created=$user_timestamp
.
Ao recuperar o date_created, você pode converter o carimbo de data e hora da seguinte forma:
$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever
Agora, este exemplo pode atender às necessidades de alguém, quando se trata de inserir um first
carimbo de data / hora ... Quando se trata de um carimbo de data / hora ou tabela adicional, convém inserir o valor de tzo na tabela de usuários para referência futura ou defini-lo como sessão ou como cookie.
PS Mas e se o usuário viaja e alterna fusos horários. Efetua login no GMT + 4, viaja rápido para o GMT-1 e efetua login novamente. O último login seria no futuro.
Eu acho ... nós pensamos demais.
Você poderia fazer isso no cliente com fuso horário e enviar o valor ao servidor; uso da amostra:
> moment.tz.guess()
"America/Asuncion"
Obter um nome de fuso horário do TZ Database válido no PHP é um processo de duas etapas:
Com JavaScript, obtenha o deslocamento do fuso horário em minutos getTimezoneOffset
. Esse deslocamento será positivo se o fuso horário local estiver atrás do UTC e negativo se estiver adiantado. Portanto, você deve adicionar um sinal oposto ao deslocamento.
var timezone_offset_minutes = new Date().getTimezoneOffset();
timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;
Passe esse deslocamento para o PHP.
No PHP, converta esse deslocamento em um nome de fuso horário válido com a função 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>
Eu escrevi um post sobre ele: Como detectar o fuso horário do usuário em PHP . Ele também contém uma demonstração.
Intl.DateTimeFormat().resolvedOptions().timeZone
e enviá-lo para o servidor web. Ref: stackoverflow.com/questions/9772955/...
Uma maneira simples de fazer isso é usando:
new Date().getTimezoneOffset();
Uma opção possível é usar o Date
campo de cabeçalho, definido na RFC 7231 e que deve incluir o fuso horário. Obviamente, não é garantido que o valor seja realmente o fuso horário do cliente, mas pode ser um ponto de partida conveniente.
Aqui está como eu faço isso. Isso definirá o fuso horário padrão do PHP como o fuso horário local do usuário. Basta colar o seguinte no topo de todas as suas páginas:
<?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
?>