Microsoft acaba de anunciar que un error de software al calcular las fechas (durante un año bisiesto) provocó una interrupción importante en Windows Azure la semana pasada.
¿Fue realmente un simple error de juicio DateTime.Now.AddYears(1)
en un año bisiesto?
¿Qué prácticas de codificación podrían haber evitado esto?
EDITAR
Como señaló dcstraw DateTime.Now.AddYears(1)
en un año bisiesto, de hecho devuelve la fecha correcta en .NET. Así que no es un error del marco, sino evidentemente un error en los cálculos de fecha.
Respuestas:
Enchufe desvergonzado:
Utilice una mejor API de fecha y hora
Las bibliotecas de fecha y hora .NET incorporadas son terriblemente difíciles de usar correctamente. Ellos no le permiten hacer todo lo que necesita, pero no se puede expresar con claridad a través del sistema de tipos.
DateTime
es un desastre ,DateTimeOffset
puede hacer que piense que en realidad está conservando la información de la zona horaria cuando no lo está, yTimeZoneInfo
no lo obliga a pensar en todo lo que debería considerar.Ninguno de estos proporciona una forma agradable de decir "solo una hora del día" o "solo una fecha", ni tampoco hacen una distinción clara entre "hora local" y "hora en una zona horaria en particular". Y si desea utilizar un calendario que no sea el gregoriano, debe pasar por la
Calendar
clase todo el tiempo.Por todo esto, estoy construyendo Noda Time , una biblioteca alternativa de fecha y hora construida en un puerto del "motor" de Joda Time , pero con una API nueva (y más sencilla) en la parte superior.
Algunos puntos en los que quizás quiera pensar, que son fáciles de pasar por alto si no los conoce:
TimeZoneInfo
generalmente está dispuesto a revelar, francamente. (No admite una zona horaria cuya idea de "hora estándar" cambie con el tiempo o que se convierta en horario de verano permanente).En cuanto a prácticas de desarrollo específicas:
DateTime.Now
oDateTime.UtcNow
; hace que sea más fácil (¡factible!) realizar pruebas unitariasfuente
Vale la pena señalar que el error probablemente no se debió a una línea como la que publicó:
DateTime.Now.AddYears(1)
Eso no crea una fecha inválida. Si tu corres:
(new DateTime(2012, 2, 29)).AddYears(1)
obtiene el 28 de febrero de 2013. No sé en qué está escrito el agente invitado de Azure, pero debe haber sido una llamada diferente que falló. Una mala forma de hacer esto en .NET habría sido:
new DateTime(today.Year + 1, today.Month, today.Day)
Eso lanza una excepción si
today
es un día bisiesto. Sin embargo, el blog de Microsoft sobre el problema de Azure decía que crearon una fecha no válida del 29 de febrero de 2013, lo que no estoy seguro de que sea posible hacerloDateTime
en .NET.No estoy diciendo eso
DateTime
y no soyDateTimeOffset
propenso a errores, solo que no creo que hayan causado este problema en particular.fuente
Las fechas específicas de prueba unitaria como John mencionó es una práctica de código que ayudará, sin embargo, nada supera lo que defino como una 'prueba de integración manual'
cambie el reloj en su servidor de desarrollo / banco de pruebas y observe lo que sucede cuando el tiempo pasa.
No se empantane en detalles específicos sobre si se trata de una 'práctica de codificación'. Obviamente, no puede hacer esto para todas las fechas del calendario; elija las fechas que le preocupan, ya sea el 29 de febrero a fin de mes fechas o fechas de cambio de horario de verano.
fuente