Esiste un modo standard per un server Web di determinare il fuso orario di un utente all'interno di una pagina Web?
Forse da un'intestazione HTTP o parte della user-agent
stringa?
Esiste un modo standard per un server Web di determinare il fuso orario di un utente all'interno di una pagina Web?
Forse da un'intestazione HTTP o parte della user-agent
stringa?
Risposte:
-new Date().getTimezoneOffset()/60;
Il metodo getTimezoneOffset()
sottrarrà il tuo orario dal GMT e restituirà il numero di minuti. Quindi, se vivi in GMT-8, restituirà 480.
Per dirlo in ore, dividi per 60. Inoltre, nota che il segno è l'opposto di quello che ti serve: sta calcolando l'offset GMT dal tuo fuso orario, non l'offset del tuo fuso orario rispetto a GMT. Per risolvere questo problema, basta moltiplicare per -1.
Nota anche che w3school dice:
Il valore restituito non è una costante, a causa della pratica di utilizzare l'ora legale.
>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Il modo più popolare (== standard?) Per determinare il fuso orario che ho visto in giro è semplicemente chiedere agli utenti stessi. Se il tuo sito Web richiede un abbonamento, questo potrebbe essere salvato nei dati del profilo degli utenti. Per gli utenti anon, le date potrebbero essere visualizzate come UTC o GMT o alcune di queste.
Non sto cercando di essere un genio intelligente. È solo che a volte alcuni problemi hanno soluzioni migliori al di fuori di qualsiasi contesto di programmazione.
Non ci sono intestazioni HTTP che segnalino il fuso orario dei client finora, sebbene sia stato suggerito di includerlo nella specifica HTTP.
Se fossi in me, probabilmente proverei a recuperare il fuso orario utilizzando JavaScript lato client e quindi a inviarlo al server utilizzando Ajax o qualcosa del genere.
JavaScript è il modo più semplice per ottenere l'ora locale del cliente. Suggerirei di utilizzare un XMLHttpRequest per inviare l'ora locale e, in caso contrario, al fuso orario rilevato in base al loro indirizzo IP.
Per quanto riguarda la geolocalizzazione, ho usato MaxMind GeoIP su diversi progetti e funziona bene, anche se non sono sicuro che forniscano dati sul fuso orario. È un servizio per cui paghi e forniscono aggiornamenti mensili al tuo database. Forniscono wrapper in diverse lingue Web.
Innanzitutto, capire che il rilevamento del fuso orario in JavaScript è imperfetto. È possibile ottenere l' offset del fuso orario locale per una data e un'ora particolari utilizzando getTimezoneOffset
su un'istanza Date
dell'oggetto, ma non è esattamente la stessa di un fuso orario IANA completo come America/Los_Angeles
.
Ci sono alcune opzioni che possono funzionare però:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tzid);
Il risultato è una stringa contenente l'impostazione del fuso orario IANA del computer su cui è in esecuzione il codice.
Gli ambienti supportati sono elencati nella tabella di compatibilità Intl . Espandi la DateTimeFormat
sezione e osserva la funzione denominata resolvedOptions().timeZone defaults to the host environment
.
Alcune librerie, come Luxon, usano questa API per determinare il fuso orario attraverso funzioni come luxon.Settings.defaultZoneName
.
Intl
API se è disponibile e quando non è disponibile, interrogano la getTimezoneOffset
funzione Date
dell'oggetto, per diversi punti nel tempo, usando i risultati per scegliere un fuso orario appropriato da un set di dati interno.Sia jsTimezoneDetect che moment-timezone hanno questa funzionalità.
// using jsTimeZoneDetect
var tzid = jstz.determine().name();
// using moment-timezone
var tzid = moment.tz.guess();
In entrambi i casi, il risultato può essere solo considerato un'ipotesi. L'ipotesi può essere corretta in molti casi, ma non tutti.
Inoltre, queste librerie devono essere periodicamente aggiornate per contrastare il fatto che molte implementazioni JavaScript meno recenti sono a conoscenza solo della regola corrente dell'ora legale per il loro fuso orario locale. Maggiori dettagli su questo qui.
In definitiva, un approccio migliore è effettivamente chiedere all'utente il proprio fuso orario. Fornisci un'impostazione che possono cambiare. Puoi utilizzare una delle opzioni di cui sopra per scegliere un'impostazione predefinita , ma non rendere impossibile deviare da quello nella tua app.
C'è anche l'approccio completamente diverso di non fare affidamento sull'impostazione del fuso orario del computer dell'utente. Invece, se riesci a raccogliere le coordinate di latitudine e longitudine, puoi risolverle in un fuso orario usando uno di questi metodi . Funziona bene su dispositivi mobili.
Ecco una solida soluzione JavaScript per determinare il fuso orario in cui si trova il browser.
>>> var timezone = jstz.determine();
>>> timezone.name();
"Europe/London"
https://bitbucket.org/pellepim/jstimezonedetect
Appendice 1: Ora questo progetto si trova su GitHub: https://github.com/pellepim/jstimezonedetect
Ecco un modo più completo.
Di seguito è riportato un estratto:
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;
}
Ottenere TZ e DST da JS (tramite Way Back Machine)
Africa/Johannesburg
o Europe/Istanbul
. Vedi il tag del fuso orario wiki .
Usando l'approccio di Unkwntech, ho scritto una funzione usando jQuery e PHP. Questo è testato e funziona!
Nella pagina PHP in cui si desidera avere il fuso orario come variabile, tenere questo frammento di codice da qualche parte vicino alla parte superiore della pagina:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
Questo leggerà la variabile di sessione "time", che ora stiamo per creare.
Nella stessa pagina, nella <head>, devi prima di tutto includere jQuery:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
Anche in <head>, sotto jQuery, incollalo:
<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>
Potresti averlo notato o meno, ma devi cambiare l'URL nel tuo dominio reale.
Un'ultima cosa. Probabilmente ti starai chiedendo che diamine timezone.php è. Bene, è semplicemente questo: (crea un nuovo file chiamato timezone.php e puntalo con l'URL sopra)
<?php
session_start();
$_SESSION['time'] = $_GET['time'];
?>
Se funziona correttamente, caricherà prima la pagina, eseguirà JavaScript e ricaricherà la pagina. Potrai quindi leggere la variabile $ timezone e usarla a tuo piacere! Restituisce la differenza di fuso orario UTC / GMT corrente (GMT -7) o qualunque fuso orario ci si trovi.
Per inviare l'offset del fuso orario come intestazione HTTP su richieste AJAX con jQuery
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
}
});
Si può anche fare qualcosa di simile per ottenere il nome del fuso orario effettivo utilizzo moment.tz.guess();
da http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/
Non ho ancora visto una risposta dettagliata qui che ottiene il fuso orario. Non è necessario geocodificare per indirizzo IP o utilizzare PHP (lol) o indovinare erroneamente da un offset.
Innanzitutto un fuso orario non è solo un offset rispetto al GMT. È un'area di terra in cui le regole del tempo sono stabilite dagli standard locali. Alcuni paesi hanno l'ora legale e accendono l'ora legale in momenti diversi. Di solito è importante ottenere la zona attuale, non solo l'offset corrente.
Se si intende memorizzare questo fuso orario, ad esempio nelle preferenze dell'utente si desidera la zona e non solo l'offset. Per le conversioni in tempo reale non importa molto.
Ora, per ottenere il fuso orario con JavaScript puoi usare questo:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
Tuttavia, ho trovato più semplice utilizzare questo robusto plug-in che restituisce il fuso orario in formato Olsen:
Con la date
funzione PHP otterrai la data e l'ora del server su cui si trova il sito. L'unico modo per ottenere il tempo dell'utente è utilizzare JavaScript.
Ma ti consiglio di farlo, se il tuo sito ha richiesto la registrazione, il modo migliore è chiedere all'utente mentre si ha la registrazione come campo obbligatorio. È possibile elencare vari fusi orari nella pagina di registro e salvarli nel database. Successivamente, se l'utente accede al sito, è possibile impostare il fuso orario predefinito per quella sessione in base al fuso orario selezionato dagli utenti.
Puoi impostare qualsiasi fuso orario specifico usando la funzione PHP date_default_timezone_set
. Questo imposta il fuso orario specificato per gli utenti.
Fondamentalmente il fuso orario degli utenti va al lato client, quindi per questo dobbiamo usare JavaScript.
Di seguito è riportato lo script per ottenere il fuso orario degli utenti utilizzando 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();
?>
Ma secondo il mio punto di vista, è meglio chiedere agli utenti se la registrazione è obbligatoria nel tuo progetto.
Non utilizzare l'indirizzo IP per determinare definitivamente la posizione (e quindi il fuso orario), poiché con NAT, i proxy (sempre più popolari) e le VPN, gli indirizzi IP non riflettono necessariamente realisticamente la posizione effettiva dell'utente, ma la posizione in cui il i server che implementano tali protocolli risiedono.
Simile a come i prefissi statunitensi non sono più utili per localizzare un utente del telefono, data la popolarità della portabilità del numero.
L'indirizzo IP e altre tecniche mostrate sopra sono utili per suggerire un valore predefinito che l'utente può regolare / correggere.
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;
}
Fornisci semplicemente i tuoi tempi in formato timestamp Unix a questa funzione; JavaScript conosce già il fuso orario dell'utente.
Come questo:
PHP:
echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';
Questo mostrerà sempre i tempi correttamente in base al fuso orario che la persona ha impostato sul suo orologio del computer. Non c'è bisogno di chiedere nulla a nessuno e salvarlo in luoghi, grazie a dio!
Facile, basta usare la getTimezoneOffset
funzione JavaScript in questo modo:
-new Date().getTimezoneOffset()/60;
La magia sembra essere tutta dentro
visitortime.getTimezoneOffset()
Fantastico, non lo sapevo. Funziona in Internet Explorer, ecc.? Da lì dovresti essere in grado di utilizzare JavaScript su Ajax, impostare i cookie, qualunque cosa. Probabilmente seguirei il percorso dei cookie da solo.
Tuttavia, dovrai consentire all'utente di modificarlo. Abbiamo provato a utilizzare la geolocalizzazione (tramite maxmind) per farlo un po 'di tempo fa, ed era abbastanza spesso ragionevolmente sbagliato - abbastanza per non valerne la pena, quindi lasciamo semplicemente che l'utente lo imposti nel loro profilo e mostrasse un avviso agli utenti che non hanno ancora impostato il loro.
Ecco un articolo (con codice sorgente) che spiega come determinare e utilizzare l'ora localizzata in un'applicazione ASP.NET (VB.NET, C #):
In breve, l'approccio descritto si basa sulla getTimezoneOffset
funzione JavaScript , che restituisce il valore salvato nel cookie di sessione e utilizzato da code-behind per regolare i valori di ora tra GMT e l'ora locale. La cosa bella è che l'utente non ha bisogno di specificare il fuso orario (il codice lo fa automaticamente). C'è di più (questo è il motivo per cui mi collego all'articolo), ma il codice fornito lo rende davvero facile da usare. Ho il sospetto che tu possa convertire la logica in PHP e in altre lingue (purché tu capisca ASP.NET).
Se si utilizza OpenID per l'autenticazione, l' estensione di registrazione semplice risolverebbe il problema per gli utenti autenticati (sarà necessario convertire da tz a numerico).
Un'altra opzione sarebbe quella di dedurre il fuso orario dalla preferenza del paese dell'agente utente. Questo è un metodo piuttosto rozzo (non funzionerà per gli Stati Uniti), ma fornisce una buona approssimazione.
È semplice con JavaScript e PHP:
Anche se l'utente può pasticciare con il suo orologio interno e / o fuso orario, il modo migliore che ho trovato finora, per ottenere l'offset, rimane new Date().getTimezoneOffset();
. Non è invasivo, non fa male alla testa ed elimina la necessità di affidarsi a terzi.
Supponiamo che io abbia una tabella, users
che contiene un campo date_created int(13)
, per memorizzare i timestamp di Unix;
Supponendo un client creates a new account
, i dati vengono ricevuti da post
, e ho bisogno insert/update
del date_created column
con il timestamp Unix del client, non di quello del server.
Dal momento che timezoneOffset è necessario al momento dell'inserimento / aggiornamento, viene passato come elemento $ _POST aggiuntivo quando il client invia il modulo, eliminando così la necessità di memorizzarlo in sessioni e / o cookie e nessun hit aggiuntivo sul server.
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;
Dire che il server riceve tzo
come $_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);
Inserisci / aggiorna date_created=$user_timestamp
.
Quando si recupera date_created, è possibile convertire il timestamp in questo modo:
$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever
Ora, questo esempio può adattarsi alle proprie esigenze, quando si tratta di inserire un first
timestamp ... Quando si tratta di un timestamp o tabella aggiuntiva, è possibile prendere in considerazione l'inserimento del valore tzo nella tabella degli utenti per riferimento futuro o impostarlo come sessione o come cookie.
PS MA cosa succede se l'utente viaggia e cambia fuso orario. Accede a GMT + 4, viaggia velocemente a GMT-1 ed effettua nuovamente l'accesso. L'ultimo accesso sarebbe in futuro.
Penso ... pensiamo troppo.
Potresti farlo sul client con moment-timezone e inviare il valore al server; utilizzo del campione:
> moment.tz.guess()
"America/Asuncion"
Ottenere un nome di fuso orario del database TZ valido in PHP è un processo in due fasi:
Con JavaScript, ottieni la differenza di fuso orario in pochi minuti getTimezoneOffset
. Questo offset sarà positivo se il fuso orario locale è dietro UTC e negativo se è avanti. Quindi è necessario aggiungere un segno opposto all'offset.
var timezone_offset_minutes = new Date().getTimezoneOffset();
timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;
Passa questo offset a PHP.
In PHP converti questo offset in un nome di fuso orario valido con la funzione 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>
Ho scritto un post sul blog: Come rilevare il fuso orario dell'utente in PHP . Contiene anche una demo.
Intl.DateTimeFormat().resolvedOptions().timeZone
e inviarlo al web server. Rif: stackoverflow.com/questions/9772955/…
Un modo semplice per farlo è usando:
new Date().getTimezoneOffset();
Un'opzione possibile è utilizzare il Date
campo di intestazione, che è definito in RFC 7231 e dovrebbe includere il fuso orario. Naturalmente, non è garantito che il valore sia davvero il fuso orario del cliente, ma può essere un comodo punto di partenza.
Ecco come lo faccio. Ciò imposterà il fuso orario predefinito di PHP sul fuso orario locale dell'utente. Basta incollare quanto segue nella parte superiore di tutte le pagine:
<?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
?>