No dejes de divulgar nuestro espacio y códigos en tus redes, apóyanos para aumentar nuestra comunidad.
Solución:
No ajusta la fecha para los cambios de horario de verano en función de si está actualmente observándolos: lo ajusta en función de si se observa DST en el instante que estás describiendo. Entonces, en el caso de enero, no aplicaría el ajuste.
Allá es Sin embargo, hay un problema: algunas horas locales son ambiguas. Por ejemplo, la 1:30 a. m. del 31 de octubre de 2010 en el Reino Unido puede representar la 01:30 UTC o las 02:30 UTC, porque los relojes retroceden de las 2 a. m. a la 1 a. m. Puedes obtener de cualquier instante representado en UTC a la hora local que se mostraría en ese instante, pero la operación no es reversible.
Del mismo modo, es muy posible que tenga una hora local que nunca ocurra (la 1:30 a. m. del 28 de marzo de 2010 no sucedió en el Reino Unido, por ejemplo), porque a la 1 a. m. los relojes se adelantaron a las 2 a. m.
En resumen, si está tratando de representar un instante en el tiempo, puede usar UTC y obtener una representación inequívoca. Si está tratando de representar una hora en una zona horaria en particular, necesitará la zona horaria en sí (por ejemplo, Europa/Londres) y la representación UTC del instante o la fecha y hora locales con el desplazamiento en ese momento en particular (para desambiguar las transiciones de DST). Otra alternativa es solamente almacenar UTC y el desplazamiento de este; eso le permite saber la hora local en ese instante, pero significa que no puede predecir cuál será la hora local un minuto después, ya que realmente no conoce la zona horaria. (Esto es lo que DateTimeOffset
tiendas, básicamente).
Esperamos que esto sea razonablemente fácil de manejar en Noda Time, pero aún así deberá tener en cuenta que es una posibilidad.
EDITAR:
El código que has mostrado es incorrecto. Este es el por qué. Cambié la estructura del código para que sea más fácil de ver, pero verá que está realizando las mismas llamadas.
var tzi = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
var aussieTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
var serverLocalTime = aussieTime.ToLocalTime();
var utcTime = serverLocalTime.ToUniversalTime();
Entonces, pensemos ahora mismo, que son las 13:38 en mi hora local (UTC+1, en Londres), las 12:38 UTC, las 22:39 en Sídney.
Su código dará:
aussieTime = 22:39 (correct)
serverLocalTime = 23:39 (*not* correct)
utcTime = 22:39 (*not* correct)
Debería no llamar ToLocalTime
sobre el resultado de TimeZoneInfo.ConvertTimeFromUtc
– asumirá que está siendo llamado en un UTC DateTime
(a menos que en realidad tenga una especie de DateTimeKind.Local
que no lo hará en este caso).
Entonces, si está guardando con precisión 22:39 en este caso, no son guardar con precisión la hora actual en UTC.
Es bueno que esté intentando almacenar las fechas y horas como UTC. En general, es mejor y más fácil pensar en UTC como el actual fecha y hora y hora local son solo seudónimos para eso. Y UTC es absolutamente crítico si necesita hacer cálculos matemáticos en los valores de fecha/hora para obtener intervalos de tiempo. Por lo general, manipulo las fechas internamente como UTC y solo las convierto a la hora local cuando se muestra el valor al usuario (si es necesario).
El error que está experimentando es que está asignando incorrectamente la zona horaria local a los valores de fecha/hora. En enero en el Reino Unido es incorrecto interpretar una hora local como si estuviera en una zona horaria de verano. Debe utilizar la zona horaria que estaba en vigor en la hora y la ubicación que representa el valor de la hora.
Traducir el tiempo hacia atrás para la visualización depende completamente de los requisitos del sistema. Puede mostrar las horas como la hora local del usuario o como la hora de origen de los datos. Pero de cualquier manera, los ajustes de horario de verano/ahorro de luz diurna deben aplicarse de manera adecuada para la zona horaria y la hora de destino.