Strategia del fuso orario

Sto creando un’applicazione MVC 3 in cui gli utenti potrebbero non essere nello stesso fuso orario, quindi il mio intento era quello di archiviare tutto in UTC e convertire da UTC a ora locale nelle visualizzazioni e localtime in UTC sugli invii.

Facendo un po ‘di navigazione anche se non sembrano esserci molte buone soluzioni per questo. Per essere onesti, mi aspettavo che un attributo fosse disponibile per convertire automaticamente l’ora UTC in ora locale, ma sembra non esistere.

Mi sento solo cercando di essere diligente sulla conversione manuale di ogni input in UTC e la conversione manuale di ogni vista alla visualizzazione dell’ora locale sarà molto incline agli errori e porterà a bug difficili da rilevare in cui il tempo non viene convertito da o verso.

Qualche suggerimento su come comportarsi come una strategia generale?

EDIT Tutti sembrano molto bloccati sul pezzo “come faccio a ottenere il fuso orario del cliente”, che come menziono in uno dei commenti non è la mia preoccupazione. Sto bene con un’impostazione utente che determina il loro fuso orario, quindi presumo di sapere già qual è il fuso orario del client … che non risolve il mio problema.

In questo momento, su ogni vista quando eseguo il rendering di una data, dovrei chiamare un metodo per renderlo nel fuso orario locale da utc. Ogni volta che invio una data per l’invio al server ho bisogno di convertirlo dal fuso orario locale a UTC. Se mi dimentico di farlo, ci saranno dei problemi … o una data inoltrata sarà sbagliata o i rapporti sul lato client e i filtri saranno errati.

Quello che speravo esistesse era un metodo più automatico, soprattutto perché il modello di visualizzazione è fortemente digitato in MVC 3 Speravo che la sum della magia fosse in grado di renderizzare almeno automaticamente in un fuso orario, se non gestire la sottomissione, proprio come il il formato della data o l’intervallo possono essere controllati da un attributo.

Quindi mi piace

[DateRange] Public DateTime MyDate 

Potrei avere qualcosa di simile

 [ConvertToUTC(offset)] Public DateTime MyDate 

Ad ogni modo, immagino che il mio unico approccio sarebbe quello di scrivere un’annotazione dati personalizzata per renderlo in un fuso orario e un override sul raccoglitore modello MVC 3 in modo che le date in entrata vengano convertite a meno che non vogliate racchiudere mai una data in un metodo chiamata. Quindi, a meno che qualcuno non abbia ulteriori commenti o suggerimenti, sarà una di quelle due opzioni, sono solo sorpreso che qualcosa non esiste già per farlo.

Se implementerò una soluzione, sicuramente la pubblicherò.

Modifica 2 Qualcosa di simile a questo http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx per MVC 3 viste e modelli di visualizzazione è quello che sto cercando.

Modifica finale Ho contrassegnato come corretta la risposta all’epidosi, ma ho anche alcuni commenti da aggiungere. Ho trovato qualcosa di simile qui: http://dalldorf.com/blog/2011/06/mvc3-timezones-1/ Con un’implementazione di ottenere il fuso orario dal client inserendolo nel cookie per le persone che lo desiderano nella parte 2 (link sotto poiché il collegamento nella prima parte dell’articolo alla parte 2 non funziona) http://dalldorf.com/blog/2011/09/mvc3-timezones-2/

È importante notare con questi approcci che DEVI modificare Editfor e Displayfor invece di cose come TextForFor, poiché solo EditFor e DisplayFor utilizzano i provider di metadati utilizzati per indicare a MVC come visualizzare la proprietà di quel tipo sul modello. Se si accede ai valori del modello direttamente nella vista (@ Model.MyDate) non verrà eseguita alcuna conversione.

È ansible gestire il problema della conversione di UTC nell’ora locale dell’utente utilizzando DisplayTemplate a livello di sito Web per DateTime.

Dalle tue visualizzazioni useresti @ Html.DisplayFor (n => n.MyDateTimeProperty)

Il secondo problema è più difficile da affrontare. Per convertire l’ora locale dell’utente in UTC, è ansible sovrascrivere DefaultModelBinder . In particolare il metodo SetProperty . Ecco un’implementazione ingenua che dimostra il punto. Si applica solo per DateTime ma potrebbe essere facilmente esteso a DateTime? . Quindi impostalo come raccoglitore predefinito in Global.asax

 public class MyDefaultModelBinder : DefaultModelBinder { protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value) { //special case for DateTime if(propertyDescriptor.PropertyType == typeof(DateTime)) { if (propertyDescriptor.IsReadOnly) { return; } try { if(value != null) { DateTime dt = (DateTime)value; propertyDescriptor.SetValue(bindingContext.Model, dt.ToUniversalTime()); } } catch (Exception ex) { string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); bindingContext.ModelState.AddModelError(modelStateKey, ex); } } else { //handles all other types base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value); } } } 

Innanzitutto, si tratta principalmente di un duplicato di Come posso determinare il fuso orario di un utente Web? , Sono d’accordo con il voto a maggioranza per questa risposta:

Il modo più popolare (== standard?) Per determinare il fuso orario che ho visto è semplicemente chiedere all’utente. Se il tuo sito web richiede l’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.

Detto questo, l’approccio più comune all’impostazione automatica di questo valore è l’uso di date getTimezoneOffset () di javascript. Questo può quindi essere inviato al server tramite un cookie o una richiesta Ajax e memorizzato con il profilo, la sessione o il cookie dell’utente.

In definitiva, penso ancora che dovresti consentire agli utenti di modificare questa impostazione in modo da poter determinare non solo lo scostamento UTC, ma anche le informazioni sul fuso orario e sull’ora legale.

Quando si raccolgono input dalla conversione degli utenti da e verso UTC tramite DateTime dovrebbe essere sufficiente. DateTimeOffset è ottimo quando il client è un codice gestito; tuttavia, con puro html / javascript non ti offrirà molto. Inoltre, le informazioni aggiuntive di DateTimeOffset non sono necessariamente necessarie per la maggior parte delle applicazioni a meno che non si intenda visualizzare ad altri utenti le informazioni sul fuso orario di origine.

Mi sento solo cercando di essere diligente sulla conversione manuale di ogni input in UTC e la conversione manuale di ogni vista alla visualizzazione dell’ora locale sarà molto incline agli errori e porterà a bug difficili da rilevare in cui il tempo non viene convertito da o verso.

Non dovresti dipendere dalla diligenza per la corretta formattazione e analisi della data e dell’ora. Il framework .NET dovrebbe gestirlo per te, per i principianti vedi ” Come: Impostare Cultura e Cultura dell’interfaccia utente per la Globalizzazione della Pagina Web di ASP.NET “.

Commento conclusivo

Francamente questo è tutto un dolore al collo. Abbiamo buttato giù l’implementazione alcuni anni fa e iniziato a trasferire tutte le informazioni su data e ora in UTC, quindi usiamo Javascript per convertire in formato ora locale e display. Questo è davvero l’unico modello di lavoro IMHO.

È ansible utilizzare qualcosa come MomentJS per visualizzare le date / orari. Aiuta con la formattazione e le ore locali.

Questo non è ansible automaticamente, dovrai fare del lavoro manuale.

1 Se non si desidera memorizzare il fuso orario dell’utente in db

1.1 Senza masterpage: come csharptest.net suggerito di usare lo script java getDateTimeOffset () per ottenere l’offset del fuso orario, impostare il valore nel cookie, scrivere un modulo per controllare i cookie se il cookie non è presente inserire il codice dello script java e il cookie usando il modulo.

1.2 Usare la masterpage: stessa cosa ma non è necessario scrivere il modulo per il controllo.

2 Memorizza il fuso orario dell’utente in db (il più semplice e il più semplice) Non è necessario utilizzare javascript per ottenere il fuso orario semplicemente convertendo datetime in base al fuso orario dell’utente.