Procedura consigliata per memorizzare DateTime in base a TimeZone

15

Sviluppo di un'applicazione Web che dovrebbe consentire all'Utente di pianificare un appuntamento in base al proprio fuso orario. E sto memorizzando lo User datetime pianificato come server datetime nel campo del database. Durante la visualizzazione delle informazioni sulla pianificazione è stato recuperato il valore dal database e convertito in timzone dell'utente. elaborazione in codice base Sto convertendo il DateTime in base al fuso orario dell'utente. Si prega di suggerire è questa best practice o qualsiasi modo semplice esiste?

    
posta user46506 25.08.2013 - 11:18
fonte

4 risposte

33

Benvenuto in uno dei problemi più difficili nella programmazione non computazionale, che rappresenta correttamente date e orari per gli utenti finali.

Realisticamente, i timestamp dovrebbero essere memorizzati in una singola rappresentazione fissa indipendentemente da come verranno interpretati, perché non importa quanto duramente ci provi, avrai sempre casi ambigui e non puoi risolverli senza una rappresentazione fissa. E hai scelto uno dei peggiori casi d'uso: la pianificazione di un appuntamento. L'unico caso di uso comune peggiore è il viaggio aereo, in cui un viaggio potrebbe iniziare in un fuso orario e terminare in un altro, possibile in una precedente ora locale.

Sempre, sempre, SEMPRE memorizza in UTC e viene visualizzato nel fuso orario preferito o specificato esplicitamente dell'utente. Se possibile, fai in modo che l'utente ti dica in che fuso orario credono che il timestamp sia quando inseriscilo ( eg , avere un campo timezone esplicito e precompilarlo con la loro zona preferita).

    
risposta data 25.08.2013 - 21:36
fonte
3

Il modo più semplice per gestire le informazioni su data / ora dipende dai requisiti dell'applicazione.

Se la data e l'ora vengono immesse dall'utente e il server non esegue alcuna elaborazione con quelle informazioni data / ora eccetto che per memorizzarle in un database e non ci si può aspettare che il tempo immesso si adatti alla posizione in cui è visualizzato (ad esempio, l'utente ha inserito "8:00 PM" e dovrebbe essere visualizzato come "8:00 PM" indipendentemente da dove viene visualizzato il mondo), quindi il modo più semplice è quello di memorizzare il DateTime come ora locale senza informazioni sul fuso orario.

D'altra parte, se il server deve utilizzare il DateTime immesso come trigger per fare qualcosa, o se il tempo deve essere regolato correttamente al fuso orario corrente, allora l'opzione migliore è quella di memorizzare il DateTime come ora UTC e regolare a ora locale (per la posizione corrente dell'utente) ogni volta che lo si legge dal database.

    
risposta data 25.08.2013 - 12:06
fonte
2

È importante non confondere due concetti correlati.

Se stai manipolando un punto nel tempo reale, ovvero un orario specifico in un giorno specifico, l'unico modo per farlo è utilizzare sempre il valore UTC universale. Non tentare mai di memorizzarlo come valore rilevante per il fuso orario. Quando si visualizza questo valore temporale per un utente, convertire sempre il fuso orario dell'utente in quel momento. (E non dimenticare che l'ora e la data dipendono dal fuso orario.)

L'altro concetto è quello di una "espressione temporale" come "8:00 PM ogni martedì". Hai menzionato specificamente che consente alle persone di pianificare appuntamenti e se hai appuntamenti ricorrenti, hai bisogno di un'espressione del genere. Non conosco alcun linguaggio di espressioni standard, ma qualunque cosa tu usi, sarà relativo al fuso orario della persona che lo ha specificato. Sarebbe meglio renderlo esplicito per es. "20:00 ogni martedì nel fuso orario del Pacifico". Nel caso di un'espressione di tempo, lo memorizzi sempre come una stringa e non implichi mai formati di orario di sistema.

Vedi ulteriori discussioni su questo sul mio blog

    
risposta data 26.08.2013 - 19:01
fonte
1

Molte risposte qui indicano la memorizzazione come UTC. Ma stai molto attento a questo. Ad esempio, se si pianifica un appuntamento alle 12:00, ma l'appuntamento avviene dopo la modifica all'ora legale, che cosa accadrà? UTC non conserva alcuna informazione sul fatto che dst fosse attivo quando l'appuntamento è stato memorizzato. Un sacco di grandi e famosi sistemi hanno commesso questo errore, in cui un utente invia un'e-mail alle 9:00 in estate, e in inverno l'ora inviata mostra 8am, perché il calcolo di ritorno da UTC dipende da quando si guarda il datetime, non attivo quando è stato registrato il datetime.

Molto meglio è supporre che il tuo utente desideri avere sempre le volte che ha scelto. Nessuna conversione UTC, nessuna conversione di orario, nessuna informazione sul fuso orario, niente. Prendere un appuntamento dalle 8:00 alle 12:00 il 21 marzo 2016 è proprio questo. Non utilizzare l'ora locale o l'ora UTC, ma il tempo non specificato (in json questo non ha né z né +, in pratica, in .NET questo ha DateTime.Kind = DateTimeKind.Unspecified).

Ovviamente, se il tuo caso d'uso è che sei un'azienda che tiene riunioni con qualcuno da fusi orari diversi e vuoi vedere queste informazioni in, ad esempio, un calendario aziendale, ma permetti agli utenti di vedere che ora è nel loro fuso orario, diventa più complicato. Il tempo deve essere corretto per persone diverse in diversi fusi orari (il fornitore e il cliente).

In questi casi, potresti anche voler registrare quando l'appuntamento è stato salvato nel database, in quale fuso orario e se includeva dst o no. In questo modo, puoi sempre calcolare l'ora locale a qualsiasi altra cosa, o a ciò che sarebbe ora o a ciò che intendeva essere storicamente. Perché i fusi orari non sono molto statici, rendendo le cose ancora più complicate.

Fortunatamente, è qui che arrivano le librerie come link e sono altamente raccomandate. Lavorano con date molto più coerenti. Anche in questo caso, consiglierei di includere tutte le variabili e la logica datetime nei propri wrapper, utilizzando le interfacce in modo che possano essere prese in giro, e quindi è possibile comunque passare alla logica in un secondo momento.

    
risposta data 09.09.2016 - 22:58
fonte

Leggi altre domande sui tag