html - zona - timezone javascript




Determinar la zona horaria de un usuario (16)

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

Tal vez de un encabezado HTTP o parte de la cadena de user-agent ?


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

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

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 la función getTimezoneOffset JavaScript, que devuelve el valor que se guarda en la cookie de sesión y es utilizado por el código subyacente para ajustar los valores de tiempo entre GMT y hora local. Lo bueno es que el usuario no necesita especificar la zona horaria (el código lo hace automáticamente). Hay más involucrado (por eso lo vinculo al artículo), pero el código proporcionado lo hace realmente fácil de usar. Sospecho que puede convertir la lógica a PHP y otros idiomas (siempre que entienda ASP.NET).


Aquí hay una forma más completa.

  1. Obtener el offset de zona horaria para el usuario.
  2. Pruebe algunos días en los límites del horario de verano para determinar si se encuentran en una zona que utiliza el horario de verano.

Un extracto está abajo:

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

Obtención de TZ y DST desde JS (a través de Way Back Machine)


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

Pero le sugiero que, si su sitio requiere registro, la mejor manera es preguntar al usuario mientras tiene que registrarse 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 establecer la zona horaria predeterminada para esa sesión según la zona horaria seleccionada por los usuarios.

Puede configurar cualquier zona horaria específica mediante 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 es del 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 mediante 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.


Es simple con JavaScript y PHP:

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

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

Suponiendo que un cliente creates a new account , los datos se reciben por post y debo insert/update la date_created column con la marca de tiempo Unix del cliente, no la del servidor.

Como el timezoneOffset es necesario en el momento de la inserción / actualización, se pasa como un elemento adicional de $ _POST cuando el cliente envía el formulario, eliminando así la necesidad de almacenarlo en sesiones y / o cookies, y no hay visitas 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 el date_created, puede convertir la marca de tiempo de la siguiente 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, este ejemplo puede ajustarse a las necesidades de uno, cuando se trata de insertar una first marca de tiempo ... Cuando se trata de una marca de tiempo adicional, o tabla, es posible que desee considerar la inserción del valor tzo en la tabla de usuarios para referencia futura, o configuración Como sesión o como cookie.

PS PERO qué pasa si el usuario viaja y cambia las zonas horarias. 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 que ... pensamos demasiado.


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

En cuanto a la geolocalización, he usado MaxMind GeoIP en varios proyectos y funciona bien, aunque no estoy seguro de que proporcionen datos de zona horaria. Es un servicio que usted paga y le proporciona actualizaciones mensuales a su base de datos. Proporcionan envoltorios en varios idiomas web.


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 para esta función; JavaScript ya conoce la zona horaria del usuario.

Me gusta 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 en función de la zona horaria que la persona haya configurado en el reloj de su computadora. No es necesario preguntar nada a nadie y guardarlo en lugares, ¡gracias a Dios!


La magia en la que todo parece estar.

visitortime.getTimezoneOffset()

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

Sin embargo, deberás permitir que el usuario lo cambie. Tratamos de usar la geolocalización (a través de maxmind) para hacer esto hace un tiempo, y fue un error bastante frecuente, lo suficiente como para que no valga la pena hacerlo, así que dejamos que el usuario lo configure en su perfil y muestre un aviso a los usuarios que Aún no he puesto el suyo.


No hay encabezados HTTP que informen la zona horaria de los clientes hasta el momento, aunque se ha sugerido que se incluya en la especificación HTTP.

Si fuera yo, probablemente intentaría obtener la zona horaria utilizando el JavaScript del lado del cliente y luego enviarlo al servidor utilizando Ajax o algo así.


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

  1. Con JavaScript, obtenga el desplazamiento de la zona horaria en minutos a través de getTimezoneOffset . Este desplazamiento será positivo si la zona horaria local está detrás de UTC y negativa si está adelante. Por lo que debe 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 la función 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>

He escrito una publicación en el blog: Cómo detectar la zona horaria del usuario en PHP . También contiene una demo.


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 puede hacer algo similar para obtener el nombre de la zona horaria real utilizando moment.tz.guess(); de http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/


Puede hacerlo en el cliente con moment-timezone y enviar el valor al servidor; uso de la muestra:

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

Si está utilizando OpenID para la autenticación, la 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 de la preferencia de país del agente de usuario. Este es un método un tanto tosco (no funcionará para en-US), pero es una buena aproximación.


Una forma simple de hacerlo es usando:

new Date().getTimezoneOffset();

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

En la página de PHP donde desea tener la zona horaria como una variable, tenga este fragmento de código en algún lugar 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 por crear.

En la misma página, en el <encabezado>, primero debe incluir jQuery:

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

También en <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 o no haberlo notado, pero necesita cambiar la URL a su dominio real.

Una última cosa. Probablemente te estés preguntando qué diablos es timezone.php. Bueno, es simplemente esto: (cree un nuevo archivo llamado timezone.php y apúntelo con la URL anterior)

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

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







timezone-offset