.NET DateTime.Now devuelve una hora incorrecta cuando se cambia la zona horaria

Este problema ocurrió durante el cambio de horario de verano. Después de que ocurriera el cambio, notamos que nuestra aplicación de servidor comenzó a escribir en el registro de tiempo incorrecto, una hora más adelante, lo que significa que .NET almacena en caché la compensación de zona horaria. Tuvimos que reiniciar nuestra aplicación para resolver este problema. Escribí una aplicación simple para reproducir este problema. Cuando cambio la zona horaria mientras se ejecuta la aplicación, la propiedad DateTime.Now sigue produciendo la hora en la zona horaria anterior. ¿Alguien sabe si hay una solución para este problema aparte de reiniciar la aplicación?

Sí, la zona horaria actual está en la memoria caché. Por una buena razón, evita problemas con el código dañado que usa DateTime.Now para implementar la medición del tiempo transcurrido. Tal código tiende a sufrir un ataque al corazón cuando el tiempo cambia de repente por una hora o más.

Tendrá que llamar a System.Globalization.CultureInfo.ClearCachedData () para restablecer el valor en caché. La próxima llamada a DateTime.Now ahora dará la nueva hora local. Si utiliza la clase .NET 3.5 TimeZoneInfo en absoluto, también deberá llamar a su método ClearCachedData (). Puede utilizar el evento SystemEvents.TimeChanged como desencadenante.

La recomendación más común es almacenar DateTime.UtcNow y, cuando desee mostrar la hora localizada al usuario, convierta a la contabilidad de tiempo local para el horario de verano.

.NET proporciona cálculos que implican el horario de verano con las clases DaylightTime y TimeZone , y el método ToLocalTime supuestamente puede convertir el UTC a la contabilidad local para el horario de verano.

La clase completamente calificada anterior estaba ligeramente desactivada, pero quizás cambió en .NET 3.5.

 System.Globalization.CultureInfo.CurrentCulture.ClearCachedData() 

tampoco olvide incluir (en C # .NET) o importar (con VB.NET) la referencia de biblioteca System.Globalization.CultureInfo

Llámalo justo antes de usar DateTime.Now . Aunque probablemente sea mejor llamarlo en el evento de inicio de su archivo Global.asax.

========== Además, asegúrese de estar comprobando la zona horaria en el servidor Windows mismo o en su máquina local, dependiendo de dónde se esté ejecutando el servidor web IIS.

En mi proyecto, necesitaba restablecer una serie de variables si se cambiaba la hora (o la zona horaria). Para poder ver el hecho de que ocurrió este evento, terminé usando un WindowsMessageFilter.

Estoy usando .Net 2.0, así que no pude usar (o tal vez estoy buscando en los lugares incorrectos) ClearCachedData, así que utilicé este enfoque con la ayuda de un pequeño reflection.

  Private mTZChangeFilter As WindowsMessageFilter mTZChangeFilter = New WindowsMessageFilter() AddHandler mTZChangeFilter.TimeChanged, AddressOf onTimeChanged Application.RemoveMessageFilter(mTZChangeFilter) Public Class WindowsMessageFilter Implements IMessageFilter  _ Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage ' Debug.Print(m.Msg.ToString) If m.Msg = 30 Then ResetTimeZone() RaiseEvent TimeChanged(Me) End If End Function Private Sub ResetTimeZone() Dim tz As Type = GetType(System.TimeZone) Dim mth As System.Reflection.MethodInfo Try mth = tz.GetMethod("ResetTimeZone", BindingFlags.NonPublic Or BindingFlags.Static) mth.Invoke(mth, Nothing) Catch ex As Exception Debug.Print(ex.ToString) End Try End Sub end class