Pergunta

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

Talvez de um cabeçalho HTTP ou parte do user-agent corda?

Nenhuma solução correta

Outras dicas

-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 - ele está calculando o deslocamento do GMT em relação ao seu fuso horário, não o deslocamento do seu fuso horário em relação ao GMT.Para corrigir isso, basta multiplicar por -1.

Observe também que w3escola diz:

O valor retornado não é constante, devido à prática de usar o tempo de economia do dia.

A maneira mais popular (==padrão?) de determinar o fuso horário que vi é simplesmente perguntando aos próprios usuários. Se o seu site exigir assinatura, ela poderá ser salva nos dados do perfil dos usuários.Para usuários anônimos, as datas podem ser exibidas como UTC ou GMT ou algo assim.

Não estou tentando ser um espertinho.Acontece que às vezes alguns problemas têm soluções melhores fora de qualquer contexto de programação.

Não há cabeçalhos 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 JavaScript do lado do cliente e depois enviá-lo ao servidor usando Ajax ou algo assim.

JavaScript é a maneira mais fácil de obter a hora local do cliente.Eu sugeriria usar um Solicitação XMLHttp para enviar de volta a hora local e, se isso falhar, retornar ao fuso horário detectado com base em seu endereço IP.

No que diz respeito à geolocalização, usei 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.

Aqui está uma solução JavaScript robusta 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á uma forma mais completa.

  1. Obtenha a diferença de fuso horário do 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 máquina Way Back)

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

Existem algumas opções que podem funcionar:

  • A maioria dos navegadores modernos suporta fusos horários da IANA na implementação do API de internacionalização ECMAScript, então você pode fazer isso:

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

    O resultado é uma string contendo a configuração de fuso horário IANA do computador onde o código está sendo executado.

    Os ambientes suportados estão listados na tabela de compatibilidade internacional.Expandir o DateTimeFormat seção e observe o recurso chamado resolvedOptions().timeZone defaults to the host environment.

    • Algumas bibliotecas, como Luxon use esta API para determinar o fuso horário por meio de funções como luxon.Settings.defaultZoneName.
  • Se precisar oferecer suporte a um conjunto mais amplo de ambientes, como navegadores da Web mais antigos, você poderá usar uma biblioteca para criar um palpite fundamentado no fuso horário.Eles trabalham primeiro tentando o Intl API, se estiver disponível, e quando não estiver disponível, eles interrogam o getTimezoneOffset função do Date objeto, para vários momentos diferentes, usando os resultados para escolher um fuso horário apropriado a partir de um conjunto de dados interno.

    Ambos jsTimezoneDetect e momento-fuso horário tem 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 uma suposição.A suposição pode estar correta em muitos casos, mas não em todos.

    Além disso, essas bibliotecas precisam ser atualizadas periodicamente para neutralizar o fato de que muitas implementações de JavaScript mais antigas só estão cientes do atual regra de 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 qual é o fuso horário.Forneça uma configuração que eles possam alterar.Você pode usar uma das opções acima para escolher um padrão configuração, mas não torne impossível desviar-se dela em seu aplicativo.

Há também a abordagem totalmente diferente de não dependendo da configuração de fuso horário do computador do usuário.Em vez disso, se você puder coletar coordenadas de latitude e longitude, poderá resolvê-las para um fuso horário usando um desses métodos.Isso funciona bem em dispositivos móveis.

Usando a abordagem da Unkwntech, escrevi uma função usando jQuery e PHP.Isso foi testado e funciona!

Na página PHP onde você deseja ter o fuso horário como variável, coloque este trecho de código em algum lugar próximo ao topo da página:

<?php
    session_start();
    $timezone = $_SESSION['time'];
?>

Isto irá 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 isto:

<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 é timezone.php.Bem, é simplesmente isto:(crie um novo arquivo chamado fuso horário.php e aponte para ele com o URL acima)

<?php
    session_start();
    $_SESSION['time'] = $_GET['time'];
?>

Se funcionar corretamente, primeiro carregará a página, executará o JavaScript e recarregará a página.Você poderá então ler a variável $timezone e usá-la como quiser!Ele retorna o deslocamento atual do fuso horário UTC/GMT (GMT -7) ou qualquer fuso horário em que você esteja.

Ainda não vi aqui uma resposta detalhada que indique o fuso horário.Você não deve precisar geocodificar por endereço IP ou usar PHP (risos) ou adivinhar incorretamente a partir de um deslocamento.

Em primeiro lugar, um fuso horário não é apenas uma diferença em relação ao GMT.É uma área de terreno 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, você deseja o fuso horário 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 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 este plugin robusto que retorna o fuso horário formatado em Olsen:

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

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

Com o PHP date função você obterá a data e hora do servidor em que o site está localizado.A única maneira de obter tempo do usuário é usar JavaScript.

Mas eu sugiro que você faça isso, se o seu site possui cadastro obrigatório então a melhor forma é solicitar ao usuário que tenha o cadastro como campo obrigatório.Você pode listar vários fusos horários na página de registro e salvá-los no banco de dados.Depois disso, se o usuário fizer login no site, você poderá definir o fuso horário padrão para essa sessão de acordo com o fuso horário selecionado pelo usuário.

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, então 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 no meu ponto de vista, é melhor perguntar aos usuários se o cadastro é obrigatório no seu projeto.

Fácil, basta usar o JavaScript getTimezoneOffset funcionar assim:

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

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/hora Unix para esta função;JavaScript já conhece o fuso horário do usuário.

Assim:

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 perguntar nada a ninguém e guardar em lugares, graças a Deus!

A magia toda parece estar em

visitortime.getTimezoneOffset()

Que legal, eu não sabia disso.Funciona no Internet Explorer etc.?A partir daí você poderá usar JavaScript para Ajax, definir cookies, qualquer coisa.Eu provavelmente seguiria o caminho dos biscoitos.

Você precisará permitir que o usuário altere isso.Tentamos usar a geolocalização (via maxmind) para fazer isso há algum tempo, e isso estava errado com bastante frequência - o suficiente para fazer com que não valesse a pena fazer isso, então deixamos o usuário definir isso em seu perfil e mostrar um aviso aos usuários que ainda não defini o deles.

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

Semelhante à forma 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 numérica.

O endereço IP e outras técnicas mostradas acima são úteis para sugerindo um padrão que o usuário pode ajustar/corrigir.

Se acontecer de você estar usando OpenID para autenticação, Extensão de registro simples resolveria o problema para usuários autenticados (você precisará converter de tz para numérico).

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

Aqui está um artigo (com código-fonte) que explica como determinar e usar a hora localizada em um aplicativo ASP.NET (VB.NET, C#):

Já estava na hora

Resumindo, a abordagem descrita depende do JavaScript getTimezoneOffset função, que retorna o valor que é salvo no cookie da sessão e usado pelo code-behind para ajustar os valores de horário entre GMT e horário local.O legal é que o usuário não precisa especificar o fuso horário (o código faz isso automaticamente).Há mais coisas envolvidas (é por isso que coloco um link para o artigo), mas o código fornecido torna-o realmente fácil de usar.Suspeito que você possa converter a lógica para PHP e outras linguagens (desde que entenda ASP.NET).

É simples com JavaScript e PHP:

Mesmo que o usuário possa mexer em seu relógio interno e/ou fuso horário, a melhor maneira que encontrei até agora, de obter o deslocamento, continua sendo new Date().getTimezoneOffset();.É não invasivo, não dá dor de cabeça e elimina a necessidade de recorrer a terceiros.

Digamos que eu tenha uma mesa, users, que contém um campo date_created int(13), para armazenar carimbos de data/hora Unix;

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

Como o timezoneOffset é necessário no momento da inserção/atualização, ele é passado como um elemento extra $_POST quando o cliente envia o formulário, eliminando assim a necessidade de armazená-lo em sessões e/ou cookies, e também sem acessos adicionais ao 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: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/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 adicional ou tabela, você pode considerar inserir o valor tzo na tabela de usuários para referência futura ou defini-lo como sessão ou como cookie.

P.S.MAS e se o usuário viajar e mudar de fuso horário.Efetua login em GMT+4, viaja rapidamente para GMT-1 e efetua login novamente.O último login seria no futuro.

Eu penso...pensamos demais.

Você poderia fazer isso no cliente com momento-fuso horário e envie o valor para o servidor;uso de amostra:

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

Uma maneira simples de fazer isso é usando:

new Date().getTimezoneOffset();

Obter um nome válido de fuso horário do banco de dados TZ em PHP é um processo de duas etapas:

  1. Com JavaScript, obtenha deslocamento de fuso horário em minutos por meio de getTimezoneOffset.Este deslocamento será positivo se o fuso horário local estiver atrás do UTC e negativo se estiver adiantado.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 esse deslocamento para o PHP.

  2. Em PHP, converta esse deslocamento em um nome de fuso horário válido com fuso horário_nome_de_abbr função.

    // 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 uma postagem no blog sobre isso: Como detectar o fuso horário do usuário em PHP.Ele também contém uma demonstração.

Uma opção possível é usar o Date campo de cabeçalho, que é definido em RFC 7231 e deve incluir o fuso horário.É claro que não é garantido que o valor seja realmente o fuso horário do cliente, mas pode ser um ponto de partida conveniente.

Veja 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']))
    {
    ?>
        <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
?>

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'];
?>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top