Determinar la zona horaria de un usuario

votos
539

¿Hay alguna manera estándar para un servidor web para poder determinar la zona horaria de un usuario en una página web?

Tal vez de una cabecera HTTP o parte de la cadena de agente de usuario?

Publicado el 01/08/2008 a las 00:42
fuente por usuario
En otros idiomas...                            


25 respuestas

votos
77

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

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

Respondida el 01/08/2008 a las 13:19
fuente por usuario

votos
47

Javascript es la forma más fácil de obtener la hora local del cliente. Sugeriría usar una XMLHttpRequestpara devolver la hora local, y si eso falla, recurrir a la zona horaria detectada en función de 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 si proporcionan datos de zona horaria. Es un servicio que paga y proporciona actualizaciones mensuales para su base de datos. Proporcionan envoltorios en varios idiomas web.

Respondida el 01/08/2008 a las 16:11
fuente por usuario

votos
174

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

No estoy tratando de ser inteligente. Es solo que a veces algunos problemas tienen soluciones más finas fuera de cualquier contexto de programación.

Respondida el 03/08/2008 a las 20:30
fuente por usuario

votos
14

La magia parece estar en todo

visitortime.getTimezoneOffset()

Eso es genial, no sabía de eso. Funciona en IE, etc.? Desde allí, debería poder usar JS para ajax, establecer cookies, lo que sea. Probablemente yo mismo iré a la ruta de las galletas.

Sin embargo, deberá permitir que el usuario lo cambie. Intentamos utilizar la geolocalización (a través de maxmind) para hacer esto hace un tiempo, y fue un error razonablemente a menudo, lo suficiente para que no valga la pena hacerlo, por lo que solo permitimos que el usuario lo establezca en su perfil y muestre un aviso a los usuarios que no han establecido el suyo todavía

Respondida el 03/08/2008 a las 21:40
fuente por usuario

votos
16

Alguien sabe de algún servicio que coincida con IP a la ubicación geográfica

Bueno, afortunadamente para ti esa respuesta se puede encontrar en nuestro propio sitio web stackoverflow: ¿cómo obtener el país según una determinada IP?

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

Respondida el 04/08/2008 a las 12:11
fuente por usuario

votos
11

Si está utilizando OpenID para la autenticación, Simple Registration Extension resolvería el problema para los usuarios autenticados (necesitará convertir de tz a numérico).

Otra opción sería inferir el huso horario de la preferencia de país del agente de usuario. Este es un método algo crudo (no funcionará en en-US), pero hace una buena aproximación.

Respondida el 30/08/2008 a las 10:29
fuente por usuario

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

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

Para poner esto en horas, divida por 60. Además, observe que el signo es lo contrario de lo que necesita: calcula el desplazamiento de GMT desde su zona horaria, no el desplazamiento de la zona horaria desde GMT. Para solucionar esto, simplemente multiplique por -1.

También tenga en cuenta que w3school dice:

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

Respondida el 27/11/2009 a las 18:52
fuente por usuario

votos
10

Aquí está un artículo (con código fuente) que explica cómo determinar y utilizar el tiempo localizada en un (, VB.NET C #) aplicación ASP.NET:

Ya es hora

En resumen, el enfoque descrito se basa en el código JavaScript getTimezoneOffsetfunción, que devuelve el valor que se guarda en la cookie de sesión y utilizada por código subyacente para ajustar los valores de tiempo entre GMT y la hora local. Lo bueno es que el usuario no tiene que especificar la zona horaria (el código lo hace automáticamente). Hay más involucrados (esto es por lo que enlace al artículo), pero el código proporcionado hace que sea muy fácil de usar. Sospecho que puede convertir la lógica para PHP y otros lenguajes (siempre y cuando usted entienda ASP.NET).

Respondida el 25/05/2010 a las 01:11
fuente por usuario

votos
16

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

Pero te sugiero que, si su sitio es necesario registrarse haber entonces la mejor manera es preguntar usuario, mientras que el registro como campo obligatorio. Usted puede enumerar varias zonas horarias en la página de registro y salvar lo que la base de datos. Después de esto, si el usuario inicie sesión en el sitio entonces usted puede definir la zona horaria predeterminada para esa sesión de acuerdo con la zona horaria seleccionada de los usuarios. Se puede establecer cualquier zona horaria específica usando la función PHP date_default_timezone_set. Este sistema la zona horaria especificada para los usuarios.

Básicamente zona horaria de los usuarios es que pasa a lado del cliente, por lo que debemos utilizar JavaScript para esto.

A continuación se muestra la secuencia de comandos para obtener la zona horaria de los usuarios usando 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.

Respondida el 16/09/2010 a las 06:59
fuente por usuario

votos
34

Aquí está una manera más completa.

  1. Obtener la zona horaria compensado por el usuario
  2. Probar algunos días en los límites de DLS para determinar si se encuentran en una zona que utiliza DLS.

Excepto continuación:

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

Conseguir TZ y el horario de verano a partir de JS (a través Way Back Machine)

Respondida el 30/03/2011 a las 21:48
fuente por usuario

votos
26

Utilizando el enfoque de Unkwntech, escribí una función utilizando jQuery y PHP. Esto es probado, y funciona!

En la página PHP en el que se desea tener la zona horaria como una variable, tiene 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 permitirá la lectura de la variable de sesión "tiempo", que ahora estamos a punto de crear.

En la misma página, en el, es necesario en primer lugar de incluir jQuery:

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

También en el, por debajo del jQuery, pega 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://domain.com/timezone.php",
                data: 'time='+ visitortimezone,
                success: function(){
                    location.reload();
                }
            });
        }
    });
</script>

Usted puede o no puede haber notado, pero hay que cambiar la dirección URL de su dominio real.

Una última cosa. Probablemente se preguntan lo que el timezone.php diablos es. Bueno, es simplemente esto: (crear un nuevo archivo llamado timezone.php y apuntan a que con la URL anterior)

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

Si esto funciona correctamente, primero cargar la página, ejecutar el código JavaScript y vuelva a cargar la página. A continuación, será capaz de leer la variable de zona horaria $ y utilizarlo para su placer! Devuelve el actual UTC / GMT desplazamiento de zona horaria (GMT -7) o cualquier zona horaria que se encuentra.

Respondida el 09/04/2011 a las 20:16
fuente por usuario

votos
15

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 proporcionar a sus tiempos en formato de marca de tiempo Unix a 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á los tiempos correctamente sobre la base de la zona horaria que la persona ha puesto en su reloj de la computadora, sin necesidad de pedir nada a nadie y guardarlo en lugares gracias a Dios!

Respondida el 28/08/2011 a las 00:00
fuente por usuario

votos
11

Una forma sencilla de hacerlo es mediante el uso de:

new Date().getTimezoneOffset();
Respondida el 01/12/2011 a las 12:08
fuente por usuario

votos
7

He aquí cómo lo hago. Esto hará que la zona horaria por defecto de PHP a la zona horaria local del usuario. Simplemente pegue el siguiente en la parte superior de todas las 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
?>
Respondida el 28/01/2012 a las 09:21
fuente por usuario

votos
16

Fácil, sólo tiene que utilizar el código JavaScript getTimezoneOffsetfunción de este modo:

-new Date().getTimezoneOffset()/60;
Respondida el 27/05/2012 a las 18:25
fuente por usuario

votos
7

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'];
?>
Respondida el 30/07/2012 a las 09:08
fuente por usuario

votos
39

Aquí es una solución robusta JavaScript para determinar la zona horaria del navegador está en.

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

https://bitbucket.org/pellepim/jstimezonedetect

Respondida el 06/08/2012 a las 22:22
fuente por usuario

votos
18

Todavía no he visto una respuesta detallada aquí donde se pone el huso horario. No debería ser necesario para codificar geográficamente por dirección IP o usar PHP (lol) o incorrectamente adivinar a partir de un desplazamiento.

En primer lugar una zona horaria no es sólo un desplazamiento con respecto a GMT. Es un área de terreno en el que las reglas de tiempo son establecidos por las normas locales. Algunos países tienen horario de verano, y se encenderán el horario de verano en momentos diferentes. Por lo general es importante para obtener la zona real, no sólo la corriente compensada.

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

Ahora, para obtener la zona horaria con javascript puede utilizar esto:

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

Sin embargo, me pareció más fácil de usar, simplemente esta sólida plugin que devuelve la zona horaria formato Olsen:

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

Respondida el 30/08/2012 a las 06:08
fuente por usuario

votos
18

Para enviar el desplazamiento como una cabecera HTTP de peticiones AJAX con la zona horaria de 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 real de zona horaria mediante el uso moment.tz.guess();de http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/

Respondida el 13/09/2012 a las 03:05
fuente por usuario

votos
14

No utilice la dirección IP para determinar definitivamente la ubicación (y hense zona horaria) - eso es porque con el NAT, proxies (cada vez más popular), y redes privadas virtuales, direcciones IP no reflejan necesariamente realista ubicación real del usuario, pero la ubicación en la que los servidores aplican dichos protocolos residen.

Similar a cómo los códigos de área ya no es útil para la localización de un usuario de teléfono son, dada la popularidad de la portabilidad de números.

IP y otras técnicas que se muestran arriba son útiles para que sugiere un defecto que el usuario puede ajustar / correcto.

Respondida el 02/01/2013 a las 19:05
fuente por usuario

votos
18

En primer lugar, entender que la detección de zona horaria en JavaScript es imperfecta. Usted puede obtener el local de desplazamiento de zona horaria para una fecha y hora determinada utilizando getTimezoneOffseten una instancia del Dateobjeto, pero eso no es exactamente lo mismo que una completa zona horaria IANA como America/Los_Angeles.

Hay algunas opciones que pueden trabajar sin embargo:

  • La mayoría de los navegadores modernos soportan las zonas horarias IANA en la implementación de la API de ECMAScript internacionalización , por lo que se puede hacer esto:

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

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

    Los entornos compatibles se enumeran en la tabla de compatibilidad Intl . Expandir la DateTimeFormatsección, y mirar a la función de llamada resolvedOptions().timeZone defaults to the host environment.

  • Si tiene que soportar un conjunto más amplio de entornos, tales como navegadores antiguos, se puede utilizar una biblioteca para hacer una conjetura educada en la zona horaria. Ellos trabajan por haber usado primero la IntlAPI si está disponible, y cuando no está disponible, interrogan a la getTimezoneOffsetfunción del Dateobjeto, por varios puntos diferentes en el tiempo, utilizando los resultados para elegir una zona horaria adecuada a partir de un conjunto de datos interna.

    Tanto jsTimezoneDetect y momento-zona horaria tienen 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 ser pensado como una conjetura. La conjetura puede ser correcto en muchos casos, pero no todos ellos.

    Además, estas bibliotecas tienen que ser actualizados periódicamente para contrarrestar el hecho de que muchos más viejos implementaciones de JavaScript sólo son conscientes de la actual horario de verano regla de tiempo para su zona horaria local. Más detalles sobre eso aquí.

En última instancia, un enfoque mejor es preguntar en realidad el usuario por su zona horaria. Proporcionar un entorno que pueden cambiar. Puede utilizar una de las opciones anteriores para elegir un valor predeterminado configuración, pero no que sea imposible desviarse de que en su aplicación.

También está el enfoque totalmente diferente de no depender de la configuración de zona horaria del ordenador del usuario en absoluto. En cambio, si se puede recoger las coordenadas de latitud y longitud, puede resolver los a una zona horaria con uno de estos métodos . Esto funciona bien en dispositivos móviles.

Respondida el 25/03/2014 a las 04:47
fuente por usuario

votos
6

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

Respondida el 09/09/2014 a las 00:25
fuente por usuario

votos
8

Simple con JSy PHP:

A pesar de que el desorden usuario puede, con su reloj y / o la zona horaria interna, la mejor manera que he encontrado hasta el momento, para realizar el desplazamiento, permanece new Date().getTimezoneOffset();. Su no invasivo, no da dolores de cabeza y elimina la necesidad de depender de terceros.

Decir que tengo una tabla usersque contiene un campo date_created int(13), para el almacenamiento de las marcas de tiempo UNIX;

Suponiendo un cliente creates a new account, los datos son recibidos por post, y necesito insert/updateel date_created columncon marca de tiempo Unix del cliente, no el servidor de.

Desde el timezoneOffset es necesario en el momento de la inserción / actualización, se pasa como un elemento de $ _POST adicional cuando el cliente envía el formulario, lo que elimina la necesidad de almacenar en las sesiones y / o galletas, y ningún servidor adicional golpea tampoco.

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

Insertar / actualización date_created=$user_timestamp.

Al recuperar la date_created, puede convertir la marca de tiempo, así:

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

Ahora bien, este ejemplo puede adaptarse a las necesidades de uno, cuando se trata de la inserción de una firstmarca de tiempo ... Cuando se trata de una marca de tiempo adicional, o una mesa, u puede que desee considerar la inserción del valor tzo en la tabla de usuarios para futura referencia, o configurarlo como la sesión o como una galleta.

PS pero lo que si el usuario se desplaza y cambia las zonas horarias. Logs en al GMT + 4, viajan rápido a GMT-1 y los registros de nuevo. Última entrada sería en el futuro.

Creo ... que pensamos demasiado.

Respondida el 15/09/2014 a las 02:19
fuente por usuario

votos
5

usted podría hacerlo en el cliente con el momento, la zona horaria y enviar el valor al servidor; ejemplos de uso:

> moment.tz.guess()
"America/Asuncion"
Respondida el 13/09/2016 a las 03:19
fuente por usuario

votos
5

Obtención de una base de datos TZ nombre de zona horaria válida en PHP es un proceso de dos pasos:

1) Con Javascript, consigue compensar zona horaria en minutos a través getTimezoneOffset. Este desplazamiento será positivo si la zona horaria local está detrás de UTC y negativo si está por delante. 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;

Pasar este desplazamiento a PHP.

2) En PHP convierta este desplazamiento en un nombre de zona horaria válida con timezone_name_from_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;

He escrito una entrada de blog en él: http://usefulangle.com/post/31/detect-user-browser-timezone-name-in-php Contiene una demostración también.

Respondida el 10/01/2017 a las 08:56
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more