Best practice per la serializzazione DateTime in .NET 3.5

Circa 4 anni fa, ho seguito questo articolo MSDN per le best practice di utilizzo DateTime per la creazione di un client .Net su .Net 1.1 e servizi web ASMX (con server SQL 2000 come back-end). Ricordo ancora i problemi di serializzazione che avevo con DateTime e lo sforzo di test necessario per i server in fusi orari diversi.

Le mie domande sono queste: esiste un documento di buone pratiche simile per alcune delle nuove tecnologie come WCF e SQL server 2008, in particolare con l’aggiunta di nuovi tipi di datetime per la memorizzazione di informazioni sensibili al fuso orario.

Questo è l’ambiente:

  1. SQL Server 2008 su Pacific Time.
  2. Livello dei servizi Web in un fuso orario diverso.
  3. I client potrebbero utilizzare .Net 2.0 o .Net 3.5 su diversi fusi orari. Se lo rende facile, possiamo costringere tutti a eseguire l’upgrade a .Net 3.5. 🙂

Qualche buon suggerimento / best practice per i tipi di dati da utilizzare in ogni livello?

Penso che il modo migliore per farlo sia passare sempre l’object come UTC e convertirlo in ora locale sui client. In tal modo, esiste un punto di riferimento comune per tutti i client.

Per convertire in UTC, chiamare ToUniversalTime sull’object DateTime. Quindi, sui client, chiama ToLocalTime per ottenere il fuso orario corrente.

Un grosso problema è che la serializzazione WCF non supporta xs: Date. Questo è un grosso problema, perché se tutto ciò che vuoi è una data, non dovresti essere costretto a preoccuparti dei fusi orari. Il seguente problema di connessione illustra alcuni dei problemi: http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=349215

Se vuoi rappresentare un punto nel tempo senza ambiguità, cioè non solo la parte data, puoi usare la class DateTimeOffset se hai .NET 3.5 su client e server. O per l’interoperabilità, passa sempre i valori di data / ora come UTC.

UTC / GMT sarebbe coerente nell’ambiente distribuito.

Una cosa importante è specificare il datetimeKind dopo aver popolato la proprietà DateTime con il valore dal database.

 dateTimeValueUtcKind = DateTime.SpecifyKind(dateTimeValue, DateTimeKind.Utc); 

Vedi MSDN

Finché il livello dei servizi Web e il livello client utilizzano il tipo .NET DateTime, è necessario serializzarli e deserializzarli correttamente come informazioni locali di data / ora con fuso orario SOAP come:

2008-09-15T13: 14: 36,9502109-05: 00

Se si deve assolutamente conoscere il fuso orario stesso (ad esempio, quanto sopra potrebbe essere Eastern Standard Time o Central Daylight Time), è necessario creare il proprio tipo di dati che espone tali pezzi in quanto tali:

 [Serializable] public sealed class MyDateTime { public MyDateTime() { this.Now = DateTime.Now; this.IsDaylightSavingTime = this.Now.IsDaylightSavingTime(); this.TimeZone = this.IsDaylightSavingTime ? System.TimeZone.CurrentTimeZone.DaylightName : System.TimeZone.CurrentTimeZone.StandardName; } public DateTime Now { get; set; } public string TimeZone { get; set; } public bool IsDaylightSavingTime { get; set; } } 

allora la tua risposta sarà simile a:

 2008-09-15T13:34:08.0039447-05:00 Central Daylight Time true 

Ho avuto fortuna con il semplice mantenimento del tipo di dati DateTime e l’ho sempre archiviato come GMT. In ogni livello, avrei regolato il valore GMT sul valore locale per il livello.