Memorizzazione di date e orari in SQL [chiuso]

-1

Ho uno strumento su cui sto lavorando che consente alle persone di creare riunioni. Possono selezionare Data, Ora e amp; Fuso orario in cui si verifica questo incontro.

Ho bisogno di determinare il modo migliore per archiviare i dati in SQL.

L'obiettivo finale è che un utente possa fare clic su "Visualizza riunioni" e mostrerà loro tutte le riunioni. Tuttavia, devono anche essere in grado di selezionare il fuso orario in cui desiderano visualizzare le riunioni e che deve modificare i tempi per riflettere ciò che hanno scelto.

Qual è l'approccio migliore per farlo?

    
posta SBB 08.01.2015 - 19:05
fonte

2 risposte

2

Come persona che ha dovuto risolvere problemi relativi al fuso orario, SEMPRE memorizzare i dati in UTC. Traducilo nel fuso orario che hanno selezionato solo per la visualizzazione.

Se SQL Server consente di archiviare l'offset UTC come parte del datetime, non è un grosso problema. Tuttavia, in MySQL, la data è appena archiviata assente dal contesto del fuso orario. Ecco un esempio calzante, che spero di poter dare un senso:)

L'utente salva un tempo 2:00 EST per il giorno in cui l'ora legale viene rimossa. Quindi, diciamo che lo memorizzi in Ora centrale, quindi viene memorizzato come 1:00 CST (ma la parte CST non è memorizzata in MySQL). Quando il codice lo estrae come 1:00, presume solo che l'ora legale sia ancora attiva perché non è stata forzata indietro. Quindi, per la visualizzazione, lo si cambia nel fuso orario dell'utente, che lo anticipa di un'ora a 2am EDT. Tuttavia, alle 2:00 EDT, il fuso orario viene riportato all'1am EST. Quindi, l'utente è entrato in EST 2am, ma è risultato in 1am EST all'uscita.

Sto provando a correggere alcuni codici legacy con esattamente questo problema. Nei nostri registri, a causa di questo problema, quando proviamo a tracciare quel periodo di tempo, ci ritroviamo con 3 ore 1 am2am invece di 2 per la transizione e il tempo 2am - 3am è completamente perso per il fuso orario orientale. I problemi si verificano solo due volte l'anno e la transizione dall'DST è la peggiore ... ma non sarebbe mai stato un problema se i tempi fossero stati memorizzati in UTC poiché UTC non ha mai avuto cambiamenti di orario.

Questo potrebbe non essere un problema che incontrerai nel tuo caso d'uso, ma, IMHO, è meglio solo archiviare sempre in UTC e tradurre nella vista, in quanto questo non ha inconvenienti di cui io sia a conoscenza per nessun tipo dell'applicazione che ha già a che fare con più fusi orari.

Una piccola eccezione, tuttavia ... diciamo che stai memorizzando un evento ricorrente . Succede alle 18:00 orientale il martedì tutto l'anno. Per un esempio del genere, se lo hai archiviato come 23:00 UTC ... parte dell'anno, l'evento verrebbe eseguito alle 19:00. Quindi, per un esempio del genere, vuoi solo gestire il segnatempo separato da qualsiasi contesto di data.

[UPDATE] analisi del fuso orario PHP

$dataFromDb = $row;
// get it from DB and assume DB is in UTC
$myDateTime = new DateTime($row['dateTime'], new DateTimeZone('UTC'));
// convert it to desired timezone
$myDateTime->setTimezone( new DateTimeZone('America/Chicago') );
echo $myDateTime->format('c'); //format in ISO-8601 format (very transportable)

È quindi possibile inviare il formato ISO a JavaScript. Tuttavia, JavaScript prenderà qualsiasi ora tu lo invii e lo visualizzi nel fuso orario LOCAL dell'utente. Quindi, se vuoi visualizzare il fuso orario orientale anche a qualcuno in orario centrale, dovrai forzarlo nel fuso orario orientale in JS. Questo è un DOLORE senza momentjs. Quindi, se non vuoi che visualizzi l'ora nell'ora locale dell'utente, e non vuoi aggiungere momentjs al tuo progetto, allora è MOLTO più facile gestire semplicemente tutte le conversioni in PHP e inviare la stringa come lo vuoi formattato da PHP e non lasciare che JS lo manchi.

Per salvare in DB, stesso processo:

//get selected timezone and date/time from user:
$dateTime = new DateTime( $_POST['dateTime'], new DateTimeZone($_POST['timezone']));
$dateTime->setTimezone( new DateTimeZone('UTC') );
$dbColumn = $dateTime->format('Y-m-d H:i:s');

NOTA : non sto facendo la convalida in quanto sopra per semplicità e supponendo che DateTime venga creato correttamente ... in realtà non credo che i dati dell'utente diventeranno effettivamente una data valida.

    
risposta data 08.01.2015 - 19:27
fonte
2

Se utilizzi SQL Server 2008 o versione successiva, ti consigliamo di DATETIMEOFFSET tipo di dati. Memorizza esattamente ciò che desideri: data + ora + fuso orario. Ciò significa che non devi scrivere codice per tradurre il valore in / da UTC. Significa anche che nessuno può dimenticare di tradurre il valore in / da UTC e corrompere i dati.

PS: questo tipo di dati si traduce direttamente in DateTimeOffset tipo di dati nel codice .NET, se questo aiuta.

    
risposta data 09.01.2015 - 12:00
fonte

Leggi altre domande sui tag