Determinar o fuso horário de um usuário

Existe alguma maneira padrão para um servidor da Web determinar o fuso horário de um usuário em uma página da Web?

Talvez de um header HTTP ou parte da cadeia de caracteres do agente do usuário?

 -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 no 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 do seu fuso horário, não o deslocamento do seu fuso horário do GMT. Para corrigir isso, basta multiplicar por -1.

Observe também que w3school diz:

O valor retornado não é uma constante, devido à prática de usar o horário de verão.

A maneira mais popular (== padrão?) De determinar o fuso horário que vi ao redor é simplesmente perguntar aos próprios usuários. Se o seu site exigir assinatura, isso pode ser salvo nos dados do perfil dos usuários. Para usuários anon, as datas podem ser exibidas como UTC ou GMT ou algo assim.

Eu não estou tentando ser inteligente. É só que algumas vezes alguns problemas têm soluções melhores fora de qualquer contexto de programação.

Não há headers HTTP que relatem 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 lado do cliente e, em seguida, enviá-lo para o 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, voltar ao fuso horário detectado com base em seu endereço IP.

Quanto à geolocalização, usei o MaxMind GeoIP em vários projetos e ele funciona bem, embora eu 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 para o seu database. Eles fornecem wrappers em vários idiomas da web.

Aqui está uma solução robusta de JavaScript para determinar o fuso horário em que o navegador está.

 >>> var timezone = jstz.determine(); >>> timezone.name(); "Europe/London" 

https://bitbucket.org/pellepim/jstimezonedetect

Aqui está um caminho mais completo.

  1. Obter o deslocamento do fuso horário para o usuário
  2. Teste alguns dias nos limites do DLS para determinar se eles estão em uma zona que usa o DLS.

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

Usando a abordagem do Unkwntech, escrevi uma function usando jQuery e PHP. Isso é testado e funciona!

Na página PHP em que você deseja ter o fuso horário como 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 session “tempo”, que estamos prestes a criar.

Na mesma página, no, você precisa primeiro de tudo include jQuery:

  

Também no, abaixo do jQuery, cole isto:

  

Você pode ou não ter notado, mas precisa alterar o URL para seu domínio real.

Uma última coisa. Você provavelmente está se perguntando o que é o heck timezone.php. Bem, é simplesmente isto: (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, primeiro carregará a página, executará o JavaScript e recarregará a página. Você então poderá ler a variável $ timezone e usá-la para o seu prazer! Ele retorna o deslocamento de fuso horário UTC / GMT atual (GMT -7) ou qualquer fuso horário em que você esteja.

Primeiro, entenda que a detecção de fuso horário em JavaScript é imperfeita. Você pode obter o deslocamento do fuso horário local para uma data e hora específica usando getTimezoneOffset em uma instância do object Date , mas isso não é o mesmo que um fuso horário completo da IANA, como America/Los_Angeles .

Existem algumas opções que podem funcionar:

  • A maioria dos navegadores modernos oferece suporte a fusos horários da IANA em sua implementação da API de internacionalização ECMAScript , para que você possa fazer isso:

     const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone; 

    O resultado é uma string contendo a configuração do 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 internacional . Expanda a seção DateTimeFormat e examine o recurso denominado resolvedOptions().timeZone defaults to the host environment .

  • Se você precisar oferecer suporte a um conjunto mais amplo de ambientes, como navegadores da Web mais antigos, poderá usar uma biblioteca para adivinhar o fuso horário. Eles trabalham primeiro tentando a API Intl se estiver disponível, e quando não estiver disponível, eles interrogam a function getTimezoneOffset do object Date , para vários pontos diferentes no tempo, usando os resultados para escolher um fuso horário apropriado de um dataset interno.

    O jsTimezoneDetect e o time -timezone possuem essa funcionalidade.

     // using jsTimeZoneDetect var tzid = jstz.determine().name(); // using moment-timezone var tzid = moment.tz.guess(); 

    Em ambos os casos, o resultado só pode ser considerado como um palpite. O palpite pode estar correto em muitos casos, mas não em todos eles.

    Além disso, essas bibliotecas precisam ser atualizadas periodicamente para compensar o fato de que muitas implementações mais antigas do JavaScript só estão cientes da regra atual do horário de verão para seu fuso horário local. Mais detalhes sobre isso aqui.

Em última análise, uma abordagem melhor é perguntar 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 pode se desviar disso no aplicativo.

Há também a 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 para um fuso horário usando um desses methods . Isso funciona bem em dispositivos móveis.

Eu ainda não vi uma resposta detalhada aqui que obtenha 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 economia de horário de verão e ativam o horário de verão em horários diferentes. Geralmente é importante obter a zona atual, não apenas o deslocamento atual.

Se você pretende armazenar este fuso horário, por exemplo, nas preferências do usuário, você deseja a zona e não apenas o deslocamento. Para conversões em tempo real, isso não importa muito.

Agora, para obter o fuso horário com o 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, eu achei mais fácil simplesmente usar este plugin robusto que retorna o fuso horário formatado Olsen:

https://github.com/scottwater/jquery.detect_timezone

Para enviar o deslocamento de fuso horário como um header 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 do fuso horário usando moment.tz.guess(); de http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/

Fácil, basta usar a function JavaScript getTimezoneOffset forma:

 -new Date().getTimezoneOffset()/60; 

Alguém sabe de algum serviço que irá corresponder IP à localização geográfica

Bem, para sua sorte, essa resposta pode ser encontrada em nosso site stackoverflow: Como obter o país de acordo com um determinado IP?

spoiler: http://www.hostip.info/use.html

Com a function de data do PHP, você obterá a data e hora do servidor no qual o site está localizado. A única maneira de obter o tempo do usuário é usar JavaScript.

Mas eu sugiro que você, se o seu site tem registro necessário, então a melhor maneira é perguntar ao usuário enquanto o registro como campo obrigatório. Você pode listar vários fusos horários na página de registro e salvá-lo no database. Depois disso, se o usuário fizer login no site, você poderá definir o fuso horário padrão para essa session, de acordo com o fuso horário selecionado pelos usuários. Você pode definir qualquer fuso horário específico usando a function PHP date_default_timezone_set . Isso define o fuso horário especificado para os usuários.

Basicamente, o fuso horário dos usuários é para o lado do cliente, então devemos usar o 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'])) { ?>  < ?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.

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; } 

simplesmente forneça seus horários no formato Timestamp do UNIX para essa function, o javascript já conhece o fuso horário do usuário.

como isso:

php:

 echo ''; 

isso sempre mostrará os horários corretamente com base no fuso horário que a pessoa definiu no relógio do computador, sem precisar perguntar nada a ninguém e salvá-lo em lugares, graças a deus!

A magia tudo parece estar em

 visitortime.getTimezoneOffset() 

Isso é legal, eu não sabia disso. Funciona no IE, etc? De lá, você deve ser capaz de usar JS para ajax, definir cookies, o que for. Eu provavelmente iria a rota do cookie eu mesmo.

Você precisará permitir que o usuário o altere. Nós tentamos usar a geolocalização (via maxmind) para fazer isso há um tempo atrás, e isso era errado razoavelmente – o suficiente para fazer com que não valesse a pena, então deixamos o usuário colocá-lo no perfil e mostramos um aviso para os usuários ainda não defini o deles.

Não use endereço IP para determinar definitivamente a localização (e fuso horário) – isso porque, com NAT, proxies (cada vez mais populares) e VPNs, os endereços IP não refletem necessariamente realisticamente a localização real do usuário, mas o local em que os servidores implementando esses protocolos residem.

Semelhante a como os Códigos de Área não são mais úteis para localizar um usuário de telefone, dada a popularidade da Portabilidade Numérica.

IP e outras técnicas mostradas acima são úteis para sugerir um padrão que o usuário possa ajustar / corrigir.

Se você estiver usando o OpenID para autenticação, o Simple Registration Extension resolveria o problema para usuários autenticados (você precisará converter de tz para numeric).

Outra opção seria inferir o fuso horário da preferência de país do agente do usuário. Este é um método um pouco grosseiro (não funciona para en-US), mas faz uma boa aproximação.

Uma maneira simples de fazer isso é usando:

 new Date().getTimezoneOffset(); 

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 #):

Já estava na hora

Em suma, a abordagem descrita depende da function getTimezoneOffset do JavaScript, que retorna o valor que é salvo no cookie da session e usado pelo code-behind para ajustar os valores de hora entre o GMT e a hora local. O bom é que o usuário não precisa especificar o fuso horário (o código faz isso automaticamente). Há mais envolvido (é por isso que eu ligo para o artigo), mas desde código torna muito fácil de usar. Eu suspeito que você pode converter a lógica para PHP e outras linguagens (contanto que você entenda o ASP.NET).

Simples com JS e PHP :

Mesmo que o usuário possa mexer com seu relógio interno e / ou fuso horário, a melhor maneira que encontrei até agora, para obter o deslocamento, permanece new Date().getTimezoneOffset(); . Sua não invasiva, não dá dores de cabeça e elimina a necessidade de contar com terceiros.

Digamos que eu tenha uma tabela de users que contenha um campo date_created int(13) , para armazenar timestamps unix;

Supondo que um cliente creates a new account , os dados são recebidos por post , e eu preciso insert/update a date_created column com o carimbo de data / hora unix do cliente, não do servidor.

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 assim a necessidade de armazená-lo em sessões e / ou cookies, além de nenhum outro servidor.

 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:ia");//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 timestamp assim:

 $date_created = //get from db $created = date("F j, Y, g:ia",$date_created);//return it to the user or whatever 

Agora, este exemplo pode se adequar às necessidades de alguém, quando se trata de inserir um first registro de data e hora … Quando se trata de um registro de data e hora adicional, você pode querer considerar inserir o valor de tzo na tabela de usuários para referência futura ou como session ou como cookie.

PS E se o usuário viajar e mudar de fuso horário. Faz o login no GMT + 4, viaja rapidamente para o GMT-1 e efetua o login novamente. Último login seria no futuro.

Eu acho … nós pensamos demais.

você poderia fazê-lo no cliente com o fuso horário e enviar o valor para o servidor; amostra de uso:

 > moment.tz.guess() "America/Asuncion" 

Experimente este código 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']; ?> 

Aqui está como eu faço isso. Isso definirá o fuso horário padrão do PHP para 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'])) { ?>  < ?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 ?> 

Uma opção possível é usar o campo de header de Date , que é definido no RFC 7231 e deve include o fuso horário. Naturalmente, não é garantido que o valor seja realmente o fuso horário do cliente, mas pode ser um ponto de partida conveniente.

Obter um nome de fuso horário do Banco de Dados TZ válido no PHP é um processo de duas etapas:

1) Com o Javascript, obtenha o deslocamento do fuso horário em minutos através de getTimezoneOffset . Esse deslocamento será positivo se o fuso horário local estiver atrás de UTC e negativo, se estiver à frente. Então 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 este deslocamento para o PHP.

2) No PHP, converta este offset em um nome válido de timezone com a function 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; 

Eu escrevi um post no blog sobre isso: http://usefulangle.com/post/31/detect-user-browser-timezone-name-in-php Ele contém uma demonstração também.