Tengo un problema con el infame horario de verano.

Tengo una lista de puntos de datos, uno por cada hora del año. Para verificar si todos los puntos de datos están presentes, creo un iterador de tiempo como este:

DateTime timeIterator = new DateTime(year, 1, 1, 0, 0, 0);

Iterarlo con

timeIterator = timeIterator.AddHours(1);

Y compruebe en cada iteración si el punto en el tiempo está presente en la lista.

El problema surge cuando se trata del horario de verano. Soy mi ejemplo del año 2014, el reloj se mueve a las 30. de marzo de 0200 a 0300. Entonces, después de 0159 viene 0300. Pero DateTime.AddHours () ignora completamente el horario de verano. Si timeIterator está en {30.03.2014 01:00:00} y llamo a AddHours (1) obtengo {30.03.2014 02:00:00} que obviamente no existe.

Si ahora pruebo la pérdida con este punto de datos, (naturalmente) no está en la lista y arrojo un "error de punto de datos faltante" incorrecto.

¿Cómo puedo comprobar si mi fecha y hora es un momento válido?

Gracias de antemano,
Franco

3
Aaginor 14 dic. 2016 a las 16:15

2 respuestas

La mejor respuesta

¿Cómo puedo comprobar si mi fecha y hora es un momento válido?

No lo revises, asegúrate. Puede contar las horas en UTC y traducir cada punto a la hora local, por ejemplo.

DateTimeOffset timeIterator = new DateTimeOffset(new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Local));
timeIterator = timeIterator.AddHours(1);
timeIterator.LocalDateTime;

// assuming you have a TimeZoneInfo object, you can also get different local times:
TimeZoneInfo tzi = /* the timezone */;
TimeZoneInfo.ConvertTimeFromUtc(timeIterator.UtcDateTime, tzi);

Sin embargo, como comentó Damien_The_Unbeliever, esto solo resuelve una parte del problema, el programa ya no verificará la existencia de una fecha no válida. Un problema diferente surge cuando sus datos se almacenan con la hora local. Esto significa que la transición del horario de verano a la hora normal tendrá dos horas sucesivas con la misma representación DateTime local. Para evitar esta situación, los datos deben almacenarse con información completa (UTC o offset explícito) para que sea posible una posterior comparación.

Editar:

Si tiene un objeto TimeZoneInfo válido para la zona horaria de sus datos y no desea cambiar a DateTimeOffset por alguna razón, también puede usar las siguientes funciones:

TimeZoneInfo tzi = /* the timezone */;
DateTime timeIterator = /* the time */;
if (tzi.IsAmbiguousTime(timeIterator))
{
    /* Expect multiple data entries */
}
if (tzi.IsInvalidTime(timeIterator))
{
    /* Expect no data entries */
}
2
grek40 15 dic. 2016 a las 11:08

También tuve problemas con las zonas horarias. Te aconsejo que guardes las fechas como valor UTC

Luego transfórmalo: (tal vez use un método de extensión)

private DateTime TransformToTimezone(DateTime datetime)
{
            TimeZoneInfo beZone = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");

            //Convert to timezone
            return TimeZoneInfo.ConvertTimeFromUtc(datetime, beZone);
}
0
Officer Jonez 14 dic. 2016 a las 15:26