2012-08-08 13 views
6

Ho cercato in giro da qualche ora su quale sia il modo migliore per utilizzare i fusi orari in un'applicazione web PHP/MySQL, trovare una risposta definitiva è difficile. Da quanto ho imparato finora è meglio memorizzare tutti gli elementi nel database in UTC (correggimi se sbaglio).Utilizzo di fusi orari in un'applicazione Web PHP

Quando un utente si registra, chiederà loro il fuso orario e quindi memorizzerà quello contro l'utente. Questo sarebbe in questo formato come un menu a discesa:

<option value="Europe/London">(GMT) Greenwich Mean Time : London</option> 

L'applicazione sto costruendo permetterà agli utenti di impostare accordi nel futuro con persone (incontri), molto simile a un calendario. Ovviamente nel corso di un anno diversi fusi orari hanno periodi di risparmio di luce diversi, non so in quale modo mi piacerebbe questo?

Un membro del Regno Unito organizza un incontro per le 3:00 PM del 24 gennaio 2013 e invita qualcuno che vive in California a questo incontro, come faccio a farlo in modo che l'americano veda quell'incontro nel suo fuso orario e l'utente del Regno Unito lo vede nel proprio fuso orario? (Nota che entrambi gli utenti sono registrati e hanno impostato il loro fuso orario).

Qualcuno ha una spiegazione chiara e forse alcuni esempi per questo? O puoi indicarmi dove posso trovarlo?

Grazie

+1

possibile duplicato di [Visualizzazione delle informazioni sul fuso orario e sul fuso orario dell'utente (cosa, non come)] (http://stackoverflow.com/questions/274823/displaying-time-and-timezone-information-to-the-user -what-not-how) o http://stackoverflow.com/questions/1285523/date-and-time-handling-in-applications-serving-clients-in-multiple-time-zones?rq=1 –

+0

UTC (precedentemente noto come GMT) e l'ora locale di Londra sono * non * la stessa cosa, lo sai. Londra osserva l'ora legale. –

+0

Lo so (io vivo nel Regno Unito), avrebbe dovuto rendere più chiaro anche l'ora legale. Ogni volta che penso di averlo risolto, l'ora legale sembra sempre di intralciare :) –

risposta

9

Ho affrontato questa situazione in modo estensivo in un'applicazione PHP/MySQL che ho scritto per un operatore di jet privato poco più di un anno fa. Esistono diverse strategie per gestire i fusi orari in queste due piattaforme, ma spiegherò come l'ho fatto. Imposta il server MySQL su UTC ed eseguo ogni script PHP nel fuso orario specificato dall'utente durante la procedura di registrazione per il profilo utente.

MySQL e PHP (PHP 5.2 e versioni successive) hanno entrambi datetime nativi. Il datetime di MySQL è un tipo di dati primitivo, mentre il PHP 5.2 e versioni successive offre il built-in DateTime class. Il datatype di MySQL datetime non include i metadati per il fuso orario, ma un oggetto DateTime di PHP include sempre un fuso orario. Se il costruttore PHP datetime non specifica il fuso orario facoltativo nel secondo argomento, il costruttore PHP datetime utilizza la variabile di ambiente php.

Sia MySQL che PHP hanno il fuso orario predefinito impostato nei file di configurazione. MySQL utilizza datetime set in the config file per ciascuna connessione db, a meno che l'utente non specifichi un fuso orario diverso dopo l'avvio della connessione con il comando SET time_zone = [timezone];. PHP imposta anche una variabile di ambiente timezone per ogni script utilizzando il fuso orario impostato nel file di configurazione del server e questa variabile d'ambiente può essere sostituita utilizzando la funzione PHP date_default_timezone_set() dopo l'avvio dello script.

La classe DateTime di PHP ha una proprietà denominata fuso orario, che è un PHP DateTimeZone object. L'oggetto DateTimeZone viene specificato utilizzando una stringa per il fuso orario esatto. Il list of timezones è completo, con centinaia di fusi orari individuali in tutto il mondo. I fusi orari di PHP terranno automaticamente conto dell'ora legale.

Quando l'utente genera un datetime nell'app Web, crea un oggetto datetime PHP nel fuso orario del profilo dell'utente. Quindi utilizzare il metodo setTimezone per modificare l'oggetto DateTime nel fuso orario UTC. Ora hai il datetime dell'utente in UTC ed è possibile memorizzare il valore nel database. Utilizzare il metodo DateTime format per esprimere i dati come una stringa nel formato accettato da MySQL.

Così l'utente genera un datetime, e ti fanno un oggetto PHP datetime nel fuso orario specificato dell'utente:

// set using an include file for user profile 
$user_timezone = new DateTimeZone('America/New_York'); 

// 1st arg in format accepted by PHP strtotime 
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone); 
$date_object1->setTimezone(new DateTimeZone('UTC')); 
$formated_string = $date_object1->format('Y-m-d H:i:s'); 
$query_string="INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')"; 

Quando si recupera il valore dal database, costruire in UTC e poi convertire in tempo dell'utente zona.

$query_string="SELECT `datetime1` FROM `t_table1`"; 
$date_object1=new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'); 
$date_object1->setTimezone($user_timezone); 
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a'); 

Usando questo metodo, i valori datetime sono sempre memorizzati in UTC all'interno del db, e l'utente sperimenta sempre i valori nel fuso orario sua/il suo profilo. PHP correggerà l'ora legale se necessario per ciascun fuso orario.

Un getcha: questa spiegazione non copre il datatype di timestamp MySQL. Raccomando di utilizzare il datetime di MySQL per memorizzare i valori datetime, non il datatype timestamp. Il datatype del timestamp è trattato nel manuale here.

Edit: È possibile produrre una matrice contenente ogni corda fuso orario PHP utilizzando listIdentifiers, che è un metodo statico della classe DateTimeZone.

+0

Questo cambierà automaticamente le date? Dite che un incontro era alle 1:00 del mattino per il Regno Unito il 10 agosto, se invito qualcuno dall'America mostrerebbe automaticamente quella riunione nel fuso orario corretto e il 9 agosto dopo aver preso il tempo libero? –

+0

Sì, la data cambierà dal 10 agosto al 9 agosto in questo scenario. Consiglio di fare alcuni test. Crea un datetime PHP nel Regno Unito, var_dump il valore, modifica il fuso orario dell'oggetto e quindi var_dump di nuovo. Un datetime è sia una data che un'ora insieme e sono una proprietà inseparabile dell'oggetto PHP. – steampowered

+0

Fantastico! La data e l'ora possono essere salvate separatamente o devono essere salvate nel database in una colonna? –

4

In MySQL, quello che dobbiamo fare è:

  1. Conservare scelto da qualche fuso orario di ciascun utente è possibile recuperarlo quando si sta facendo query di database per conto di tale utente. Puoi memorizzarlo come una stringa.
  2. destro prima di farlo lavorare per conto di un particolare utente (ad esempio, la conservazione o il recupero di orari degli appuntamenti e date) fanno SET time_zone = (stored time zone setting)

Questo farà sì che i fusi orari da convertire in modo appropriato per l'ora locale di ogni persona.

Edit:

Questo funziona perché

  1. MySQL tenta di utilizzare UTC (tempo universale, precedentemente noto come Greenwich Mean Time) per memorizzare gli oggetti DATETIME e dati TIMESTAMP in tabelle.
  2. Può farlo correttamente solo se conosce il fuso orario locale corretto per ciascun elemento di dati che viene fornito dalle applicazioni.
  3. Nelle applicazioni che non si preoccupano di fusi orari diversi, lo fa in un modo a livello di server MySQL. Vedi https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html. La maggior parte delle persone che eseguono applicazioni multinazionali e multi-fuso orario impostano i propri fusi orari del server su UTC, non sull'ora locale, perché rende lo molto più semplice da gestire per risolvere il problema.
  4. Non ha senso cercare di convertire un orario da UTC a ora locale a meno che non si conoscano anche la data e il fuso orario, poiché l'ora locale si attiva e disattiva in vari periodi dell'anno. Prova solo a farlo bene per tutti e tre di Israele, Arizona e New York, ti ​​sfido! Israele passa dalla luce del giorno e dall'ora solare a Pasqua e Rosh Hashanah; L'Arizona non cambia, e New York cambia al capriccio della legislatura federale degli Stati Uniti.
  5. Esiste un'impostazione time_zone per l'ambito di sessione (SET time_zone = something).Se non lo si imposta, utilizza la rappresentazione del fuso orario nell'articolo 3 sopra. Se lo si imposta, il server lo utilizzerà come fuso orario per convertire la propria rappresentazione interna nella rappresentazione che invia nelle query.
  6. È possibile ottenere un elenco dei nomi dei fusi orari disponibili nel server MySQL emettendo SELECT Name from mysql.time_zone_name. Questo può popolare il menu a discesa dal quale l'utente può selezionare il suo fuso orario. Se questa query non restituisce articoli, dai un'occhiata a fondo https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html.

Quindi, ciò significa che è possibile impostare l'impostazione time_zone della sessione su un fuso orario di un particolare utente e quindi tornare indietro tutte le volte nel fuso orario dell'utente. Inoltre, tutti gli articoli DATETIME o TIMESTAMPINSERT o UPDATE verranno convertiti dal fuso orario dell'utente alla rappresentazione interna di MySQL così come sono posizionati nelle tabelle.

Attenzione: nelle applicazioni Web con connessioni MySQL persistenti, il lavoro per una nuova richiesta utente erediterà l'impostazione time_zone della connessione. Non dimenticare di resettarlo per il nuovo utente.

Se si sta eseguendo una query che restituisce dati dell'ora locale per più di un utente e tali utenti si trovano in fusi orari diversi, non è possibile sfruttare questo set di funzionalità per sessione MySQL. È possibile aggirare questo problema eseguendo query diverse per utenti diversi e modificando l'impostazione time_zone tra di esse.

In alternativa, è possibile utilizzare la funzione di MySQL

CONVERT_TZ(datetime,'UTC','user_time_zone') 

o simili su ogni elemento.

In alternativa, Java e DotNET dispongono di propri sistemi di manipolazione del fuso orario di alta qualità. Quindi, puoi fare la scelta di eseguire il tuo server MySQL con l'impostazione time_zone di UTC e fare tutte le tue conversioni del fuso orario nella tua applicazione.

+0

Lo deduco che ogni volta che viene visualizzato sul sito viene visualizzato nel fuso orario dell'utente? Senza alcuna magia richiesta? –

+1

se esegui una query che ottiene il tempo da 2 utenti con fusi orari diversi: che cosa fai? –

+0

Vedere le mie modifiche ... –