Mejores prácticas para la serialización DateTime en .NET 3.5

Hace unos 4 años, seguí este artículo de MSDN sobre las mejores prácticas de uso de DateTime para construir un cliente .Net en .Net 1.1 y servicios web ASMX (con el servidor SQL 2000 como servidor). Todavía recuerdo los problemas de serialización que tuve con DateTime y el esfuerzo de prueba que requirió para los servidores en diferentes zonas horarias.

Mi pregunta es la siguiente: ¿Existe algún documento similar de mejores prácticas para algunas de las nuevas tecnologías, como WCF y SQL Server 2008, especialmente con la incorporación de nuevos tipos de fecha y hora para almacenar la información de zona horaria?

Este es el ambiente:

  1. SQL Server 2008 en hora del Pacífico.
  2. Capa de servicios web en una zona horaria diferente.
  3. Los clientes podrían estar utilizando .Net 2.0 o .Net 3.5 en diferentes zonas horarias. Si lo hace fácil, podemos forzar a todos a actualizar a .Net 3.5. 🙂

¿Alguna buena sugerencia / mejores prácticas para los tipos de datos que se utilizarán en cada capa?

Creo que la mejor manera de hacerlo es pasar siempre el objeto como UTC y convertir a la hora local en los clientes. Al hacerlo, hay un punto de referencia común para todos los clientes.

Para convertir a UTC, llame a ToUniversalTime en el objeto DateTime. Luego, en los clientes, llame a ToLocalTime para obtenerlo en su zona horaria actual.

Un gran problema es que la serialización de WCF no es compatible con xs: Date. Este es un gran problema, ya que si lo único que quieres es una fecha, no debes forzarte a preocuparte por las zonas horarias. El siguiente problema de conexión analiza algunos de los problemas: http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=349215

Si desea representar un punto en el tiempo sin ambigüedades, es decir, no solo la parte de fecha, puede usar la clase DateTimeOffset si tiene .NET 3.5 en el cliente y el servidor. O para la interoperabilidad, siempre pase los valores de fecha / hora como UTC.

UTC / GMT sería consistente en el entorno distribuido.

Una cosa importante es que especifique datetimeKind después de completar su propiedad DateTime con el valor de la base de datos.

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

Ver MSDN

Siempre que la capa de servicios web y la capa de cliente utilicen el tipo .NET DateTime, se debe serializar y deserializar correctamente como una fecha / hora local estándar de SOAP con información de zona horaria como:

2008-09-15T13: 14: 36.9502109-05: 00

Si de manera absoluta y positiva debe conocer la zona horaria en sí (es decir, lo anterior podría ser la Hora Estándar del Este o la Hora del Día Central), necesita crear su propio tipo de datos que exponga esas piezas como tales:

 [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; } } 

entonces tu respuesta sería como:

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

Tuve buena suerte con solo mantener el tipo de datos DateTime y siempre almacenarlo como GMT. En cada capa, ajustaría el valor GMT al valor local para la capa.