Determinar o fuso horário de um usuário

610

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-agentstring?

Kevin Dente
fonte
6
Pergunte ao usuário. Se você obtiver o fuso horário no computador do usuário e ele estiver configurado errado, então o que?
Rob Williams
40
Então o usuário provavelmente não se importa?
Agnoster #
2
Você quer dizer stackoverflow.com/q/1091372/218196 ?
Felix Kling
2
Infelizmente, as respostas a esta pergunta também permitem a criação de perfil e a criação de cercas de usuário.
William Entriken
1
Por que você precisa conhecer o fuso horário do usuário?
Braiam 5/10

Respostas:

325
-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.

JD Isaacks
fonte
5
E os usuários que usam telefones celulares com navegadores sem suporte a javascript? Eu gosto da pergunta, o usuário pergunta sobre cabeçalhos HTTP, agente do usuário ... existe uma maneira de tornar esse trabalho do lado do servidor, o mais preciso possível?
Nischal
19
Isso nem sempre funciona para o horário de verão. Obter o deslocamento do fuso horário faz exatamente o que diz. É o deslocamento. Uma ZONA de tempo é na verdade uma área geográfica. Isso não funcionará para o horário de verão, pois você não sabe em que hemisfério o usuário vive ou se o país deles ainda tem horário de verão. Por que não usar isso:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo
20
Eu imploro para diferir com Keyo. A definição de getTimezoneOffset () (de acordo com o padrão ECMA ecma-international.org/ecma-262/5.1/#sec-15.9.5.26 ) é "Retorna a diferença entre a hora local e a hora UTC em minutos". - em outras palavras, deve levar em consideração o horário de verão. A documentação da Mozilla diz "O horário de verão impede que esse valor seja constante, mesmo para um determinado local".
xgretsch
12
@xgretsch: obtém o deslocamento atual do usuário do GMT. Tudo bem se você estiver apresentando outra hora que ocorre no mesmo dia (a menos que a data atual seja uma data de mudança, onde isso pode estar errado). No entanto, existem muitos fusos horários com o mesmo deslocamento em relação ao GMT e eles podem ter datas de alternância diferentes ou não usar o horário de verão.
Mike Dimmick
13
Uma coisa a observar aqui; alguns lugares (como Terra Nova, no Canadá) têm fusos horários que ficam fora de meia hora; portanto, depois de dividir por 60, sua resposta pode não ser um número inteiro.
Jason Walton
193

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.

Ishmaeel
fonte
5
E quando um usuário está baixando um arquivo .ics que deve ter um horário de início específico para sua localização (por exemplo, das 9 às 11 horas em todo o país)? Eles não devem ter que dizer qual é o fuso horário deles.
Marcy Sutton
33
@Ishmaeel: mas os usuários fazer viagens internacionais e que não deve precisa dizer a sua fuso horário de cada vez que o login de algum fuso horário não-nativo
Rajat Gupta
10
Isso não responde à pergunta, o que implica claramente que ele está procurando uma solução tecnológica.
G-Wiz
5
O @gWiz OP está pedindo uma solução padrão. Isso é bastante padrão.
amigos estão dizendo sobre simone
4
A melhor solução provavelmente seria uma combinação de perguntar ao usuário (por exemplo, fornecer uma lista suspensa de fuso horário na parte superior de um relatório), enquanto padronizar a seleção suspensa para um fuso horário determinado por GPS quando o usuário estiver em um celular dispositivo que fornece informações de localização e, por outro lado, o padrão é UTC.
Triynko
133

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.

Mads Kristiansen
fonte
16
Estranhamente, esta é a única resposta correta para a pergunta, que pergunta como fazê-lo no lado do servidor. Suspeito que o motivo de outras respostas com mais votos seja porque, quando você percebe que precisa fazer isso do lado do cliente, acaba usando as outras respostas. Mas IMHO alguém que vota outra resposta também deve vogar esta.
TTT
Acredito que o melhor método é usar o local geo-ip para classificar os possíveis fusos horários e, por padrão, escolher o primeiro que seja (próximo) correspondente ao deslocamento do tempo do agente do usuário (é necessário JavaScript). Mesmo depois disso, você deve fornecer uma maneira de corrigir o fuso horário, mesmo que esse método selecione o incorreto.
Mikko Rantalainen
@MikkoRantalainen cuidado ao usar proxies, pois nem sempre eles se anunciam nos cabeçalhos.
Matthieu
@ Matthieu existe uma resposta melhor hoje em dia: stackoverflow.com/a/11836123/334451 #
Mikko Rantalainen
2
Esta é literalmente a única resposta que realmente abordou a questão colocada.
Lscoughlin #
54

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.

pix0r
fonte
Votei esta resposta porque a latitude e longitude obtidas de bancos de dados como o GeoIP (que tem uma versão gratuita disponível a partir de agora) podem ser combinadas com bancos de dados que convertem essa coordenada em um fuso horário. Eu acho que o GeoNames possui um segundo banco de dados.
Peter O.
As versões atuais (gratuitas e pagas) dos bancos de dados / APIs MaxMind GeoIP, de fato, fornecem informações de fuso horário (ele retorna "Europa / Londres" para o meu fuso horário). Não me lembro se a versão antiga do sistema GeoIP fez o mesmo, mas funciona muito bem agora! Os campos MaxMind são nomeados "time_zone", "time_zone_name".
Matthew Slyman
51

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 getTimezoneOffsetem uma instância do Dateobjeto, 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 DateTimeFormatseçã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.

    • 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 IntlAPI, se estiver disponível, e quando não está disponível, interrogam a getTimezoneOffsetfunção do Dateobjeto, 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.

Matt Johnson-Pint
fonte
O uso da localização geográfica do usuário (ou seja, a localidade) para deduzir o fuso horário também é falho. Os usuários podem querer usar um fuso horário específico em seu dispositivo que não seja o fuso horário local, mesmo que ele possa exibir o mesmo horário (ou não). Por exemplo, os viajantes costumam deixar seus dispositivos com o fuso horário definido em sua localidade usual e não esperam ver datas e horários usando um deslocamento diferente sem serem avisados. Eu poderia estar falando por experiência pessoal aqui ... ;-)
RobG
Não posso dizer se você está me trollando, Rob. ;) Mas nenhuma dessas abordagens usa a localidade, mas a configuração do dispositivo, portanto, alinha-se ao seu ponto. (Apenas a abordagem alternativa mencionada no último parágrafo usaria localização actual.)
Matt Johnson-Pint
Fazendo uma integração com uma nota de terminologia: "localidade" não é enfaticamente a localização geográfica do usuário. "Localidade" é um grupo de configurações como idioma, formato numérico, calendário etc. Por exemplo, a localidade de_DE especifica alemão como idioma padrão, o euro como moeda padrão, vírgulas como separador decimal, pontos como separador de milhares e gregoriano como o calendário. Veja developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
azernik em
49

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

Adão
fonte
14
As respostas apenas ao link são desencorajadas, porque se o link desaparecer, a resposta deixará de ser útil; e porque, sem seguir o link, os leitores não sabem se é uma boa resposta. Nesse caso, você pode esclarecer que se trata de uma biblioteca de terceiros que adota uma abordagem de identificação baseada em banco de dados e talvez explique alguns dos princípios de sua operação.
IMSoP 02/02
1
Este! Este é o caminho a percorrer. Biblioteca simples, lida com o horário de verão corretamente. Outras respostas estão cheias de WTF e muitas não fazem horário de verão.
Dirbaio 1/11/16
1
Esta biblioteca é muito inteligente. Ele funciona consultando o deslocamento atual para o UTC e ajustando a hora do objeto Date do JavaScript adicionando ou subtraindo segundos até o deslocamento para o UTC mudar. Usando esse método, esta biblioteca descobre muitas alterações de horário de verão para identificar exclusivamente o fuso horário. Eu acho que a biblioteca poderia ter um desempenho ainda melhor se fizesse pesquisa binária em vez de pesquisa linear. O valor de retorno é uma chave de informações do fuso horário da IANA (também conhecida como banco de dados do fuso horário da Olson).
Mikko Rantalainen
3
Essa biblioteca não é mais necessária. Navegadores modernos oferecem suporte à API Intl, que retorna a sequência de fuso horário da IANA. Veja esta resposta .
Dan Dascalescu 17/03/19
42

Aqui está uma maneira mais completa.

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

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)

Joseph Lust
fonte
Isso funcionou para mim! Leia os comentários na postagem do blog para obter algumas atualizações no código.
Arlomedia 15/04
Isso ainda retornará apenas o deslocamento padrão para o fuso horário, como +02: 00. Não fornecerá informações suficientes para determinar o fuso horário do usuário, como Africa/Johannesburgou Europe/Istanbul. Veja o wiki da tag de fuso horário .
Matt Johnson-Pint
32

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.

Westy92
fonte
eu faço assim, mas eu poderia ter algo que verifica o $ _SESSION atual [ 'tempo'] e só obter o javascript para recarregar se a sua diferente
Christopher perseguição
1
Provavelmente, é mais fácil usar um Cookie do que uma Sessão para transportá-lo, pois o bloqueio e a desserialização da sessão PHP podem causar lentidão no seu aplicativo. Para máxima eficiência, você pode copiar o valor na sessão e excluir o cookie para que ele não seja enviado nas solicitações subsequentes.
IMSoP 02/02/2015
25

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/

philfreo
fonte
1
Isso retorna apenas o deslocamento do fuso horário atual - não o fuso horário . Veja o wiki da tag de fuso horário .
226148 Matt Johnson-Pint
Editado para incluir informações sobre como fazer o mesmo no nome do fuso horário.
27417 philfreo
24

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:

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

Keyo
fonte
22

Com a datefunçã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.

Sanjay Khatri
fonte
22

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.

Jaime G
fonte
21

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!

Envis
fonte
$ unix_timestamp_ofshiz? Algo está faltando aqui e não funciona muito bem, embora isso pareça ser uma boa resposta.
20

Fácil, basta usar a getTimezoneOffsetfunção JavaScript da seguinte forma:

-new Date().getTimezoneOffset()/60;
JoeyFur62
fonte
1
Esta é uma função Javascript, não uma função PHP.
Cincodenada
Além disso, ele retorna apenas o deslocamento do fuso horário atual - não o fuso horário . Veja o wiki da etiqueta de fuso horário .
226148 Matt Johnson-Pint
3
Esta é apenas uma cópia da resposta aceita, por que você está votando nela.
Rambatino 12/10
19

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.

Orion Edwards
fonte
15

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 resumo, a abordagem descrita depende da getTimezoneOffsetfunçã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).

Alek Davis
fonte
1
O link está morto. Eu acho que este é o link alternativo: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan
1
O artigo também está disponível em formato PDF aqui: app.box.com/shared/bfvvmidtyg
Ivaylo Slavov
O método de conversão da hora do servidor UTC para a hora local do cliente descrita neste artigo está incorreto. O uso do deslocamento atual do cliente para ajustar os horários UTC no servidor resultará em horários "locais" incorretos por metade do ano para os locais dos clientes que observam o horário de verão. Considere este cenário: um cliente no Reino Unido em 14 de janeiro de 2013 (GMT + 0000, horário padrão) define uma data e hora de 21 de agosto de 2015 às 14:00 (GMT + 0100, horário de verão). Isso é normalizado no servidor para 21 de agosto de 2015 às 13:00 UTC. No dia em que isso ocorre, o deslocamento do cliente é 0, portanto, o tempo enviado de volta ao cliente será 21 de agosto de 2015 às 13:00.
Stephen Blair
Ponto válido, mas não afirmei que essa seja uma solução à prova de balas. Se você precisar implementar uma solução realmente sensível ao tempo, por exemplo, um aplicativo de reserva de passagem de trem, precisará encontrar uma solução mais abrangente (e complexa). No entanto, para muitos aplicativos, isso não seria um problema. Porque em muitos casos, queremos localizar valores GMT para a sessão atual. Agora, se você tiver um aplicativo que precise salvar um carimbo de data e hora para alguns, mesmo no futuro, e não possa tolerar o DTS, uma maneira adequada seria apresentar uma opção para economizar tempo diretamente no GMT. Se você conhece uma opção melhor, compartilhe.
Alek Davis
14

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.

Dmitry Shechtman
fonte
13

É 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, usersque 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/updateo date_created columncom 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 tzocomo $_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 firstcarimbo 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.

cara
fonte
13

Você poderia fazer isso no cliente com fuso horário e enviar o valor ao servidor; uso da amostra:

> moment.tz.guess()
"America/Asuncion"
Tomas Tomecek
fonte
5
O nome da função diz tudo sobre a sua precisão ;-)
Legends
Atualmente, moment.js não é mais recomendado. Atualmente, existem alternativas muito menores ( dayjs , date-fns ). O momento é enorme .
Dan Dascalescu 17/03/19
11

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

  1. 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.

  2. 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.

Ângulo útil
fonte
1
Eu acho que um processo mais simples é ligar Intl.DateTimeFormat().resolvedOptions().timeZonee enviá-lo para o servidor web. Ref: stackoverflow.com/questions/9772955/...
Michael Tsang
9

Uma maneira simples de fazer isso é usando:

new Date().getTimezoneOffset();
Naeem Ul Wahhab
fonte
8
Por que você repostou uma resposta idêntica (de John Isaacks) de 2 anos atrás: stackoverflow.com/a/1809974/836407 ?
chown
2
Além disso, ele retorna apenas o deslocamento do fuso horário atual - não o fuso horário . Veja o wiki da tag de fuso horário .
Matt Johnson-Pint
8

Uma opção possível é usar o Datecampo 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.

Berislav Lopac
fonte
1
Infelizmente, esse cabeçalho parece ser projetado principalmente para respostas, não solicitações: "Um agente do usuário PODE enviar um campo de cabeçalho Data em uma solicitação, embora geralmente não o faça, a menos que se acredite que ele transmita informações úteis para o servidor". Acabei de verificar e o Firefox não envia.
IMSoP 02/02
8

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
?>
Dane Iracleous
fonte
1
Isso não leva em conta os ajustes de "horário de verão" - um usuário em Dublin corresponderia à sua 'Europa / Dublin' no inverno, mas a 'Europa / Belgrado' no verão. Se você usará o deslocamento atual, tudo o que você pode razoavelmente assumir é esse deslocamento, não um identificador geográfico.
IMSoP 02/02
8

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'];
?>
pckabeer
fonte