Pregunta

¿Existe una forma estándar para que un servidor web pueda determinar la zona horaria de un usuario dentro de una página web?

Quizás desde un encabezado HTTP o parte del user-agent ¿cadena?

No hay solución correcta

Otros consejos

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

El método getTimezoneOffset() restará su hora de GMT y devolverá la cantidad de minutos.Entonces, si vives en GMT-8, devolverá 480.

Para poner esto en horas, divídalo por 60.Además, observe que el signo es lo opuesto a lo que necesita: calcula la diferencia de GMT con respecto a su zona horaria, no la diferencia de su zona horaria con respecto a GMT.Para solucionar este problema, simplemente multiplique por -1.

También tenga en cuenta que w3escuela dice:

El valor devuelto no es una constante, debido a la práctica de usar el horario de verano.

La forma más popular (==¿estándar?) de determinar la zona horaria que he visto es simplemente preguntando a los propios usuarios. Si su sitio web requiere suscripción, esto podría guardarse en los datos del perfil de los usuarios.Para usuarios anónimos, las fechas podrían mostrarse como UTC o GMT o algo así.

No estoy tratando de ser un sabelotodo.Es sólo que a veces algunos problemas tienen mejores soluciones fuera de cualquier contexto de programación.

Hasta el momento no hay encabezados HTTP que informen la zona horaria del cliente, aunque se ha sugerido incluirlo en la especificación HTTP.

Si fuera yo, probablemente intentaría buscar la zona horaria usando JavaScript del lado del cliente y luego enviarla al servidor usando Ajax o algo así.

JavaScript es la forma más sencilla de obtener la hora local del cliente.Yo sugeriría usar un Solicitud XMLHttp para devolver la hora local y, si eso falla, recurrir a la zona horaria detectada según su dirección IP.

En cuanto a geolocalización, he utilizado MaxMind GeoIP en varios proyectos y funciona bien, aunque no estoy seguro de si proporcionan datos de zona horaria.Es un servicio por el que paga y proporciona actualizaciones mensuales a su base de datos.Proporcionan contenedores en varios idiomas web.

Aquí hay una solución JavaScript sólida para determinar la zona horaria en la que se encuentra el navegador.

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

https://bitbucket.org/pellepim/jstimezonedetect

Aquí tienes una forma más completa.

  1. Obtener el desplazamiento de la zona horaria para el usuario
  2. Pruebe algunos días en los límites del horario de verano para determinar si están en una zona que utiliza el horario de verano.

A continuación se muestra un extracto:

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

Obtener TZ y DST de JS (a través de Way Back Machine)

Primero, comprenda que la detección de zona horaria en JavaScript es imperfecta.Puedes conseguir el local. desplazamiento de zona horaria para una fecha y hora particular usando getTimezoneOffset en una instancia de la Date objeto, pero eso no es lo mismo que un completo Zona horaria IANA como America/Los_Angeles.

Sin embargo, hay algunas opciones que pueden funcionar:

  • La mayoría de los navegadores modernos admiten zonas horarias de la IANA en su implementación del API de internacionalización de ECMAScript, entonces puedes hacer esto:

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

    El resultado es una cadena que contiene la configuración de zona horaria de la IANA de la computadora donde se ejecuta el código.

    Se enumeran los entornos compatibles. en la tabla de compatibilidad internacional.Ampliar la DateTimeFormat sección y observe la función denominada resolvedOptions().timeZone defaults to the host environment.

    • Algunas bibliotecas, como Luxón Utilice esta API para determinar la zona horaria a través de funciones como luxon.Settings.defaultZoneName.
  • Si necesita admitir un conjunto más amplio de entornos, como navegadores web más antiguos, puede utilizar una biblioteca para crear una estimación fundamentada en la zona horaria.Funcionan probando primero el Intl API si está disponible, y cuando no está disponible, interrogan al getTimezoneOffset función de la Date objeto, para varios momentos diferentes en el tiempo, utilizando los resultados para elegir una zona horaria adecuada de un conjunto de datos internos.

    Ambos jsTimezoneDetect y momento-zona horaria tener esta funcionalidad.

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

    En ambos casos, el resultado sólo puede considerarse una suposición.La suposición puede ser correcta en muchos casos, pero no en todos.

    Además, estas bibliotecas deben actualizarse periódicamente para contrarrestar el hecho de que muchas implementaciones de JavaScript más antiguas solo conocen la actual regla de horario de verano para su zona horaria local. Más detalles sobre eso aquí.

En última instancia, un mejor enfoque es preguntarle al usuario su zona horaria.Proporcione una configuración que puedan cambiar.Puede utilizar una de las opciones anteriores para elegir un por defecto configuración, pero no haga imposible desviarse de ella en su aplicación.

También existe el enfoque completamente diferente de no dependiendo en absoluto de la configuración de zona horaria de la computadora del usuario.En cambio, si puede recopilar coordenadas de latitud y longitud, puede resolverlas en una zona horaria usando uno de estos métodos.Esto funciona bien en dispositivos móviles.

Utilizando el enfoque de Unkwntech, escribí una función usando jQuery y PHP.¡Esto está probado y funciona!

En la página PHP donde desea tener la zona horaria como variable, coloque este fragmento de código cerca de la parte superior de la página:

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

Esto leerá la variable de sesión "tiempo", que ahora estamos a punto de crear.

En la misma página, en <head>, primero debes incluir jQuery:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

También en el <head>, debajo de jQuery, pega esto:

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

Puede que lo hayas notado o no, pero debes cambiar la URL a tu dominio real.

Una última cosa.Probablemente te estés preguntando qué diablos es timezone.php.Bueno, es simplemente esto:(crea un nuevo archivo llamado zona horaria.php y señalelo con la URL anterior)

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

Si esto funciona correctamente, primero cargará la página, ejecutará JavaScript y recargará la página.¡Entonces podrás leer la variable $timezone y usarla a tu gusto!Devuelve el desplazamiento de la zona horaria UTC/GMT actual (GMT -7) o cualquier zona horaria en la que se encuentre.

Todavía no he visto una respuesta detallada aquí que obtenga la zona horaria.No debería necesitar geocodificar por dirección IP ni usar PHP (risas) ni adivinar incorrectamente a partir de un desplazamiento.

En primer lugar, una zona horaria no es sólo una diferencia con respecto a GMT.Es una zona de terreno en la que las reglas horarias están marcadas por los estándares locales.Algunos países tienen horario de verano y activarán el horario de verano en diferentes horarios.Generalmente es importante obtener la zona real, no solo el desplazamiento actual.

Si tiene la intención de almacenar esta zona horaria, por ejemplo, en las preferencias del usuario desea la zona y no solo el desplazamiento.Para conversiones en tiempo real no importará mucho.

Ahora, para obtener la zona horaria con javascript puedes usar esto:

>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.

Sin embargo, me resultó más fácil usar este complemento robusto que devuelve la zona horaria con formato Olsen:

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

Para enviar el desplazamiento de la zona horaria como un encabezado HTTP en solicitudes AJAX con jQuery

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
    }
});

También puedes hacer algo similar para obtener el nombre de la zona horaria real usando moment.tz.guess(); de http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/

Con el PHP date función obtendrá la fecha y hora del servidor en el que se encuentra el sitio.La única forma de conseguir tiempo para el usuario es utilizar JavaScript.

Pero le sugiero que, si su sitio requiere registro, la mejor manera es pedirle al usuario que tenga el registro como campo obligatorio.Puede enumerar varias zonas horarias en la página de registro y guardarlas en la base de datos.Después de esto, si el usuario inicia sesión en el sitio, puede configurar la zona horaria predeterminada para esa sesión según la zona horaria seleccionada por los usuarios.

Puede configurar cualquier zona horaria específica utilizando la función PHP date_default_timezone_set.Esto establece la zona horaria especificada para los usuarios.

Básicamente, la zona horaria de los usuarios va al lado del cliente, por lo que debemos usar JavaScript para esto.

A continuación se muestra el script para obtener la zona horaria de los usuarios utilizando PHP y 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();
?>

Pero según mi punto de vista, es mejor preguntar a los usuarios si el registro es obligatorio en su proyecto.

Fácil, solo usa JavaScript getTimezoneOffset funcionar así:

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

Simplemente proporcione sus tiempos en formato de marca de tiempo Unix a esta función;JavaScript ya conoce la zona horaria del usuario.

Como esto:

PHP:

echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';

Esto siempre mostrará las horas correctamente según la zona horaria que la persona haya configurado en el reloj de su computadora.No hay necesidad de preguntarle nada a nadie y guardarlo en lugares, ¡gracias a Dios!

Toda la magia parece estar en

visitortime.getTimezoneOffset()

Eso es genial, no sabía nada de eso.¿Funciona en Internet Explorer, etc.?Desde allí deberías poder usar JavaScript para Ajax, configurar cookies, lo que sea.Probablemente yo mismo elegiría la ruta de las galletas.

Sin embargo, deberá permitir que el usuario lo cambie.Intentamos usar la geolocalización (a través de maxmind) para hacer esto hace un tiempo, y fue incorrecto con bastante frecuencia, lo suficiente como para que no valga la pena hacerlo, así que simplemente dejamos que el usuario lo configure en su perfil y mostramos un aviso a los usuarios que Aún no han configurado el suyo.

No utilice la dirección IP para determinar definitivamente la ubicación (y por lo tanto la zona horaria); esto se debe a que con NAT, servidores proxy (cada vez más populares) y VPN, las direcciones IP no necesariamente reflejan de manera realista la ubicación real del usuario, sino la ubicación en la que se encuentra el usuario. residen los servidores que implementan esos protocolos.

De manera similar a cómo los códigos de área de EE. UU. ya no son útiles para localizar a un usuario de teléfono, dada la popularidad de la portabilidad numérica.

La dirección IP y otras técnicas mostradas arriba son útiles para sugiriendo un valor predeterminado que el usuario puede ajustar/corregir.

Si por casualidad estás usando ID abierto para autenticación, Extensión de registro simple resolvería el problema para los usuarios autenticados (deberá convertir de tz a numérico).

Otra opción sería inferir la zona horaria a partir de la preferencia de país del agente de usuario.Este es un método algo tosco (no funcionará para en-US), pero es una buena aproximación.

Aquí hay un artículo (con código fuente) que explica cómo determinar y usar la hora localizada en una aplicación ASP.NET (VB.NET, C#):

Ya es hora

En resumen, el enfoque descrito se basa en JavaScript. getTimezoneOffset función, que devuelve el valor que se guarda en la cookie de sesión y se utiliza mediante el código subyacente para ajustar los valores de tiempo entre GMT y la hora local.Lo bueno es que el usuario no necesita especificar la zona horaria (el código lo hace automáticamente).Hay más cosas involucradas (es por eso que vinculo al artículo), pero el código proporcionado hace que sea realmente fácil de usar.Sospecho que puedes convertir la lógica a PHP y otros lenguajes (siempre que comprendas ASP.NET).

Es simple con JavaScript y PHP:

Aunque el usuario puede alterar su reloj interno y/o zona horaria, la mejor manera que encontré hasta ahora para obtener la compensación sigue siendo new Date().getTimezoneOffset();.No es invasivo, no produce dolores de cabeza y elimina la necesidad de depender de terceros.

Di que tengo una mesa, users, que contiene un campo date_created int(13), para almacenar marcas de tiempo de Unix;

Asumiendo un cliente creates a new account, los datos son recibidos por post, y necesito insert/update el date_created column con la marca de tiempo Unix del cliente, no la del servidor.

Dado que timezoneOffset es necesario en el momento de la inserción/actualización, se pasa como un elemento $_POST adicional cuando el cliente envía el formulario, eliminando así la necesidad de almacenarlo en sesiones y/o cookies, y tampoco hay accesos adicionales al 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 el servidor recibe 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);

Insertar/actualizar date_created=$user_timestamp.

Al recuperar la fecha_creada, puede convertir la marca de tiempo de esta manera:

$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever

Ahora bien, este ejemplo puede ajustarse a las necesidades de uno cuando se trata de insertar un first marca de tiempo...Cuando se trata de una marca de tiempo o tabla adicional, es posible que desee considerar insertar el valor tzo en la tabla de usuarios para referencia futura, o configurarlo como sesión o como cookie.

PDPERO ¿qué pasa si el usuario viaja y cambia de zona horaria?Inicia sesión en GMT+4, viaja rápido a GMT-1 y vuelve a iniciar sesión.El último inicio de sesión sería en el futuro.

Creo...Pensamos demasiado.

Podrías hacerlo en el cliente con momento-zona horaria y enviar el valor al servidor;uso de muestra:

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

Una forma sencilla de hacerlo es utilizando:

new Date().getTimezoneOffset();

Obtener un nombre de zona horaria válido para la base de datos TZ en PHP es un proceso de dos pasos:

  1. Con JavaScript, obtenga un desplazamiento de la zona horaria en minutos getTimezoneOffset.Este desplazamiento será positivo si la zona horaria local está por detrás de UTC y negativo si está por delante.Por lo tanto, debes agregar un signo opuesto al desplazamiento.

    var timezone_offset_minutes = new Date().getTimezoneOffset();
    timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;
    

    Pase este desplazamiento a PHP.

  2. En PHP, convierta este desplazamiento en un nombre de zona horaria válido con nombre_zona_horaria_de_abbr función.

    // 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>
    

He escrito una publicación de blog al respecto: Cómo detectar la zona horaria del usuario en PHP.También contiene una demostración.

Una posible opción es utilizar el Date campo de encabezado, que se define en RFC 7231 y se supone que incluye la zona horaria.Por supuesto, no se garantiza que el valor sea realmente la zona horaria del cliente, pero puede ser un punto de partida conveniente.

Así es como lo hago.Esto establecerá la zona horaria predeterminada de PHP en la zona horaria local del usuario.Simplemente pegue lo siguiente en la parte superior de todas sus 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
?>

Pruebe 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top