php - ¿Cómo detectar la zona horaria del usuario?
laravel get client timezone (6)
Esta pregunta ya tiene una respuesta aquí:
Necesito saber en qué zona horaria están mis usuarios en función de su encabezado IP o http.
Recibí muchas respuestas sobre este tema, pero no pude entender esa respuesta. Algunos dijeron use -new Date().getTimezoneOffset()/60
( desde aquí ). Pero, ¿qué significa?
Tengo un date_default_timezone_set("Asia/Calcutta");
en la raíz de mi página (index.php). Así que para esto tengo que obtener la zona horaria de forma dinámica y configurarla en lugar de Asia/Calcutta
.
¡Una solución es preguntarles! Especialmente en los sistemas de miembros donde puede capturar / registrar un usuario, déles una opción en ese punto. Simple pero exacto
Dependencias:
- http://www.maxmind.com/download/geoip/api/php/php-latest.tar.gz
http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
//Get remote IP $ip = $_SERVER[''REMOTE_ADDR'']; //Open GeoIP database and query our IP $gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD); $record = geoip_record_by_addr($gi, $ip); //If we for some reason didnt find data about the IP, default to a preset location. if(!isset($record)) { $record = new geoiprecord(); $record->latitude = 59.2; $record->longitude = 17.8167; $record->country_code = ''SE''; $record->region = 26; } //Calculate the timezone and local time try { //Create timezone $user_timezone = new DateTimeZone(get_time_zone($record->country_code, ($record->region!='''') ? $record->region : 0)); //Create local time $user_localtime = new DateTime("now", $user_timezone); $user_timezone_offset = $user_localtime->getOffset(); } //Timezone and/or local time detection failed catch(Exception $e) { $user_timezone_offset = 7200; $user_localtime = new DateTime("now"); } echo ''User local time: '' . $user_localtime->format(''H:i:s'') . ''<br/>''; echo ''Timezone GMT offset: '' . $user_timezone_offset . ''<br/>'';
Esto funciona bien ...
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled)
document.cookie = "tzo="+ (- new Date().getTimezoneOffset());
</script>
EOE;
if (!isset($_COOKIE[''tzo''])) {
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled) document.reload();
else alert("Cookies must be enabled!");
</script>
EOE;
die();
}
$ts = new DateTime(''now'', new DateTimeZone(''GMT''));
$ts->add(DateInterval::createFromDateString($_COOKIE[''tzo''].'' minutes''));
La información de la zona horaria del navegador no forma parte de la especificación HTTP, por lo que no puede obtenerla simplemente desde un encabezado.
Si tiene coordenadas de ubicación (desde un dispositivo móvil GPS, por ejemplo), puede encontrar la zona horaria utilizando uno de estos métodos . Sin embargo, la geolocalización por dirección IP no es una gran solución porque a menudo la IP es la de un ISP o servidor proxy que puede estar en otra zona horaria.
Existen algunas estrategias que puede utilizar para tratar de detectar el huso horario, como el uso de la biblioteca jsTimeZoneDetect , que es un excelente punto de partida, pero lo suficientemente imperfecto como para que no pueda confiar solo en eso. Si está utilizando moment.js, hay una función incorporada en la zona horaria de momento llamada moment.tz.guess()
que hace lo mismo.
La idea de usar la función getTimezoneOffset()
JavaScript es defectuosa porque no se está consiguiendo un huso horario, solo un desplazamiento para una fecha en particular. Consulte la sección wiki de la etiqueta TimeZone titulada "TimeZone! = Offset".
Como sea que lo mires, en última instancia, debes decidir sobre uno de dos enfoques:
- Pídale al usuario que le diga su zona horaria, a partir de algún tipo de lista desplegable o control de selector de zona horaria basada en el mapa .
O
- Solo envíe tiempo al navegador en UTC, y use JavaScript en el navegador para convertirlo a cualquier zona horaria local en la que el usuario pueda tener configurada su computadora.
Discuto esto con más detalle (desde la perspectiva de CA #) en esta respuesta .
La zona horaria no está disponible en el encabezado HTTP, pero el país (abreviatura) está en el encabezado ACCEPT_LANGUAGE. Será algo así como "en-US" (EE. UU. Es el código de país). Esto se puede combinar con la información de JavaScript para tener una buena idea de la zona horaria del usuario.
Esto es lo que estoy usando en JS:
function timezone() {
var now = new Date();
var jano = new Date(now.getFullYear(), 0, 1).getTimezoneOffset()/-60;
var julo = new Date(now.getFullYear(), 6, 1).getTimezoneOffset()/-60;
var tz = Math.min(jano, julo);
if (jano != julo) tz += ((jano < julo) ? ''S'' : ''W'') + Math.abs(jano - julo);
return tz;
}
Esto devuelve una cadena como "-6S1" para la zona central (desplazamiento de tiempo estándar de -6 horas, horario de verano activo en verano y agrega 1 hora). Uso una cookie para que esté disponible para PHP. PHP busca en la base de datos TZ las zonas que coinciden con este y el país. Por aquí (US, -6S1) hay 7 zonas coincidentes, la primera es "América / Chicago".
Por cierto, hay 2 zonas en la base de datos donde DST agrega algo más que 1 hora: Lord Howe Island (10.5W0.5) y Troll Station, Antarctica (0W2).
Para resumir la respuesta de Matt Johnson en términos de código:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.4/jstz.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
var tz = jstz.determine(); // Determines the time zone of the browser client
var timezone = tz.name(); //''Asia/Kolhata'' for Indian Time.
$.post("url-to-function-that-handles-time-zone", {tz: timezone}, function(data) {
//Preocess the timezone in the controller function and get
//the confirmation value here. On success, refresh the page.
});
});
</script>