Determina il fuso orario di un utente


610

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


6
Chiedi all'utente. Se si ottiene il fuso orario dal computer dell'utente ed è impostato in modo errato, che cosa?
Rob Williams,

40
Quindi probabilmente all'utente non importa?
agnoster l'


2
Sfortunatamente, le risposte a questa domanda consentono anche la profilazione dell'utente e il geofencing.
William Entriken,

1
Perché è necessario conoscere il fuso orario dell'utente?
Braiam,

Risposte:


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


5
Che dire degli utenti che usano telefoni cellulari con browser senza supporto javascript? Mi piace la domanda, l'utente fa domande su intestazioni HTTP, agente utente ... c'è un modo per rendere questo lato server il più preciso possibile?
Nischal,

19
Questo non funziona sempre per l'ora legale. Ottieni offset fuso orario fa esattamente quello che dice. È l'offset. Un fuso orario è in realtà un'area geografica. Questo non funzionerà per l'ora legale poiché non sai in quale emisfero vive l'utente o se il suo paese ha anche l'ora legale. Perché non usare questo invece:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo

20
Mi permetto di dissentire da Keyo. La definizione di getTimezoneOffset () (secondo lo standard ECMA ecma-international.org/ecma-262/5.1/#sec-15.9.5.26 ) è "Restituisce la differenza tra l'ora locale e l'ora UTC in minuti". - in altre parole, dovrebbe tener conto dell'ora legale. La documentazione di Mozilla afferma che "L'ora legale impedisce a questo valore di essere una costante anche per una determinata locale".
xgretsch,

12
@xgretsch: ottiene l' offset corrente dell'utente dal GMT. Va bene se stai presentando un'altra ora che si verifica nello stesso giorno (a meno che la data corrente non sia una data di cambio, in cui potrebbe essere errata). Tuttavia, ci sono molti fusi orari che hanno lo stesso offset rispetto al GMT e possono avere date di cambio diverse o non utilizzare l'ora legale.
Mike Dimmick,

13
Una cosa da notare qui; alcuni luoghi (come Terranova in Canada) hanno fusi orari che sono spenti per mezz'ora, quindi dopo aver diviso per 60 la tua risposta potrebbe non essere un numero intero.
Jason Walton,

193

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.


5
Che dire di quando un utente sta scaricando un file .ics che dovrebbe avere un orario di inizio specifico per la propria posizione (es. 9-11 in tutto il paese)? Non dovrebbero DOVREBBE dire quale sia il loro fuso orario.
Marcy Sutton,

33
@Ishmaeel: ma gli utenti viaggiano a livello internazionale e non dovrebbero dover dire il loro fuso orario ogni volta che accedono da un fuso orario non nativo
Rajat Gupta,

10
Questo non risponde alla domanda, il che implica chiaramente che sta cercando una soluzione tecnologica.
G-Wiz,

5
@gWiz OP richiede una soluzione standard. Questo è piuttosto standard.
Simon Bergot,

4
La soluzione migliore sarebbe probabilmente una combinazione di chiedere all'utente (ad esempio fornendo un fuso orario a discesa nella parte superiore di un rapporto), mentre si imposta automaticamente la selezione a discesa su un fuso orario determinato dal GPS quando l'utente è su un cellulare dispositivo che fornisce informazioni sulla posizione e altrimenti predefinito su UTC.
Triynko,

133

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.


16
Stranamente, questa è l'unica risposta corretta alla domanda, che chiede come farlo sul lato server. Ho il sospetto che la ragione per cui ci sono altre risposte con più voti è perché una volta che ti rendi conto che devi farlo sul lato client, finisci per usare le altre risposte. Ma IMHO, chiunque abbia votato per un'altra risposta dovrebbe votare anche questa.
TTT

Credo che il metodo migliore sia utilizzare la posizione geo-ip per ordinare i possibili fusi orari e, per impostazione predefinita, selezionare il primo che corrisponde (vicino) all'offset temporale dell'agente utente (JavaScript richiesto). Anche dopo, devi fornire un modo per correggere il fuso orario anche dopo che questo metodo selezionerà quello errato.
Mikko Rantalainen,

@MikkoRantalainen stai attento quando usi i proxy, dato che non si pubblicizzano sempre nelle intestazioni.
Matthieu,

@Matthieu esiste una risposta migliore al giorno d'oggi: stackoverflow.com/a/11836123/334451
Mikko Rantalainen

2
Questa è letteralmente l'unica risposta che ha effettivamente affrontato la domanda posta.
lscoughlin,

54

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.


Ho votato questa risposta perché la latitudine e la longitudine ottenute da database come GeoIP (che ha una versione gratuita disponibile fin d'ora) possono essere combinate con database che convertono tale coordinata in un fuso orario. Penso che GeoNames abbia un database simile.
Peter O.

Le versioni attuali (sia gratuite che a pagamento) dei database / API MaxMind GeoIP forniscono effettivamente informazioni sul fuso orario (restituisce "Europa / Londra" per il mio fuso orario). Non riesco a ricordare se la vecchia versione del loro sistema GeoIP fatto lo stesso, ma ora funziona molto bene! I campi MaxMind sono denominati "time_zone", "time_zone_name".
Matthew Slyman,

51

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 getTimezoneOffsetsu un'istanza Datedell'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 DateTimeFormatsezione 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.

    • Se è necessario supportare un set più ampio di ambienti, ad esempio browser Web meno recenti, è possibile utilizzare una libreria per fare un'ipotesi plausibile sul fuso orario. Funzionano prima provando l' IntlAPI se è disponibile e quando non è disponibile, interrogano la getTimezoneOffsetfunzione Datedell'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.


Anche l'uso della posizione geografica dell'utente (ovvero la sua lingua) per dedurre il fuso orario è imperfetto. Gli utenti potrebbero voler utilizzare un fuso orario specifico sul proprio dispositivo che non sia il fuso orario locale, anche se potrebbe visualizzare lo stesso orario (o meno). Ad esempio, i viaggiatori lasciano spesso i loro dispositivi con il fuso orario impostato sulla loro normale località e non si aspettano di vedere le date e gli orari utilizzare un offset diverso senza essere avvisati. Potrei parlare qui per esperienza personale ... ;-)
RobG

Non so se mi stai prendendo in giro Rob. ;) Ma nessuno di questi approcci utilizza le impostazioni locali, ma piuttosto l'impostazione sul dispositivo, quindi si allinea al punto. (Solo l'approccio alternativo menzionato nell'ultimo paragrafo userebbe la posizione corrente.)
Matt Johnson-Pint

Rintocchi con una nota terminologia: "locale" è decisamente non è la posizione geografica dell'utente. "Locale" è un gruppo di impostazioni come lingua, formato numerico, calendario, ecc. Ad esempio, la locale de_DE specifica il tedesco come lingua predefinita, l'euro come valuta predefinita, le virgole come separatore decimale, i periodi come separatore delle migliaia e il gregoriano come il calendario. Vedi developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
azernik

49

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


14
Le risposte al solo link sono scoraggiate, perché se il link scompare, la risposta cessa di essere utile; e perché senza seguire il link, i lettori non sanno se fornisce una buona risposta. In questo caso, potresti chiarire che si tratta di una libreria di terze parti che adotta un approccio all'identificazione basato su database e forse spiegare alcuni dei principi del suo funzionamento.
IMSoP

1
Questo! Questa è la strada da percorrere. Libreria semplice, gestisce correttamente l'ora legale. Altre risposte sono piene di WTF e molte non fanno l'ora legale.
Dirbaio

1
Questa libreria è molto intelligente. Funziona eseguendo una query sull'offset corrente su UTC, quindi regolando l'ora dell'oggetto Data JavaScript aggiungendo o sottraendo i secondi fino a quando l'offset alle modifiche UTC. Utilizzando questo metodo, questa libreria individua molte modifiche all'ora legale sufficienti per identificare in modo univoco il fuso orario. Penso che la libreria potrebbe avere prestazioni ancora migliori se eseguisse la ricerca binaria anziché la ricerca lineare. Il valore restituito è una chiave di informazioni sulla zona IANA (ovvero il database dei fusi orari Olson).
Mikko Rantalainen,

3
Questa libreria non è più necessaria. I browser moderni supportano l'API Intl, che restituisce la stringa del fuso orario IANA. Vedere questa risposta .
Dan Dascalescu,

42

Ecco un modo più completo.

  1. Ottieni l'offset del fuso orario per l'utente
  2. Prova alcuni giorni sui limiti dell'ora legale per determinare se si trovano in una zona che utilizza l'ora legale.

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)


Questo ha funzionato per me! Leggi i commenti sotto il post del blog per un paio di aggiornamenti al codice.
arlomedia,

Ciò restituirà solo l' offset standard per il fuso orario, ad esempio +02: 00. Non ti fornirà informazioni sufficienti per determinare il fuso orario dell'utente, come Africa/Johannesburgo Europe/Istanbul. Vedi il tag del fuso orario wiki .
Matt Johnson-Pint,

32

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.


mi piace, ma potrei avere qualcosa che controlla l'attuale $ _SESSION ['time'] e ottenere il javascript per ricaricare solo se è diverso
Christopher Chase,

1
Probabilmente è più facile usare un Cookie che una Sessione per trasportarlo, poiché bloccare e annullare la serializzazione della sessione PHP può causare rallentamenti nella tua app. Per la massima efficienza, è possibile copiare il valore nella sessione ed eliminare il cookie in modo che non venga inviato nelle richieste successive.
IMSoP

25

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/


1
Ciò restituisce solo l' offset del fuso orario corrente , non il fuso orario . Vedi il tag del fuso orario wiki .
Matt Johnson-Pint,

Modificato per includere informazioni su come fare lo stesso per il nome del fuso orario.
philfreo,

24

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:

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


22

Con la datefunzione 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.


22

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.


21

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!


$ unix_timestamp_ofshiz? Qui manca qualcosa e non funziona del tutto, anche se sembra che potrebbe essere una buona risposta.

20

Facile, basta usare la getTimezoneOffsetfunzione JavaScript in questo modo:

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

1
Questa è una funzione Javascript, non una funzione PHP.
Cincodenada,

Inoltre, restituisce solo l' offset del fuso orario corrente , non il fuso orario . Vedi il tag del fuso orario wiki .
Matt Johnson-Pint,

3
Questa è solo una copia della risposta accettata, per cui hai anche votato.
Rambatino,

19

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.


15

Ecco un articolo (con codice sorgente) che spiega come determinare e utilizzare l'ora localizzata in un'applicazione ASP.NET (VB.NET, C #):

È quasi ora

In breve, l'approccio descritto si basa sulla getTimezoneOffsetfunzione 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).


1
Il link è morto. Penso che questo sia il link alternativo: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan

1
L'articolo è disponibile anche in formato PDF qui: app.box.com/shared/bfvvmidtyg
Ivaylo Slavov

Il metodo di conversione dell'ora del server UTC nell'ora del client locale descritto in questo articolo è errato. L'uso dell'offset del client corrente per regolare gli orari UTC sul server comporterà tempi "locali" errati per la metà dell'anno per i client locali che osservano l'ora legale. Considera questo scenario: un cliente nel Regno Unito il 14 gennaio 2013 (GMT + 0000 ora solare) imposta una data e un'ora il 21 agosto 2015 alle 14:00 (GMT + 0100 ora legale). Questo viene normalizzato sul server al 21 agosto 2015 alle 13:00 UTC. Il giorno in cui ciò si verifica, l'offset del client è 0, quindi il tempo inviato al client sarà il 21 agosto 2015 alle 13:00.
Stephen Blair,

Punto valido, ma non ho affermato che si tratti di una soluzione a prova di proiettile. Se devi implementare una soluzione che tenga conto del tempo, ad esempio un'applicazione per la prenotazione dei biglietti del treno, devi trovare una soluzione più completa (e complessa). Tuttavia, per molte app questo non sarebbe un problema. Perché in molti casi vogliamo localizzare i valori GMT per la sessione corrente. Ora, se hai un'applicazione che deve salvare un timestamp per alcuni anche in futuro e non può tollerare DTS, un modo corretto sarebbe quello di presentare un'opzione per risparmiare tempo direttamente in GMT. Se conosci un'opzione migliore, ti preghiamo di condividere.
Alek Davis,

14

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.


13

È 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, usersche 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/updatedel date_created columncon 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 tzocome $_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 firsttimestamp ... 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.



11

Ottenere un nome di fuso orario del database TZ valido in PHP è un processo in due fasi:

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

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


1
Penso che un processo più semplice sia chiamare Intl.DateTimeFormat().resolvedOptions().timeZonee inviarlo al web server. Rif: stackoverflow.com/questions/9772955/…
Michael Tsang


8

Un'opzione possibile è utilizzare il Datecampo 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.


1
Sfortunatamente, quell'intestazione sembra essere progettata principalmente per le risposte, non per le richieste: "Un agente utente PU send inviare un campo di intestazione Data in una richiesta, sebbene generalmente non lo farà a meno che non si ritenga che trasmetta informazioni utili al server". Ho appena controllato e Firefox non lo invia.
IMSoP

8

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

1
Ciò non tiene conto delle regolazioni dell '"ora legale": un utente a Dublino corrisponderebbe alla tua "Europa / Dublino" in inverno, ma a "Europa / Belgrado" in estate. Se stai per utilizzare l'offset corrente, tutto ciò che puoi ragionevolmente supporre è quell'offset, non un identificatore geografico.
IMSoP

8

Prova questo codice 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'];
?>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.