Firma Microsoft właśnie ogłosiła, że błąd oprogramowania w obliczaniu dat (ponad rok przestępny) spowodował poważną awarię systemu Windows Azure w zeszłym tygodniu.
Czy to naprawdę był zwykły błąd w ocenie DateTime.Now.AddYears(1)
sytuacji w roku przestępnym?
Jakie praktyki kodowania mogły temu zapobiec?
EDYCJA
Jak wskazał dcstraw DateTime.Now.AddYears(1)
w roku przestępnym, w rzeczywistości zwraca poprawną datę w .NET. Więc to nie jest błąd frameworka, ale ewidentnie błąd w obliczeniach Date.
Odpowiedzi:
Bezwstydna wtyczka:
Użyj lepszego interfejsu API daty i czasu
Wbudowane biblioteki daty i czasu .NET są strasznie trudne w użyciu. Oni nie pozwalają zrobić wszystko, czego potrzeba, ale nie można wyrazić się jasno za pośrednictwem systemu typu.
DateTime
to bałagan ,DateTimeOffset
może cię uświadomić, że faktycznie przechowujesz informacje o strefie czasowej, gdy nie jesteś, iTimeZoneInfo
nie zmusza do myślenia o wszystkim, co powinieneś rozważyć.Żaden z nich nie zapewnia przyjemnego sposobu na powiedzenie „tylko pory dnia” lub „tylko daty”, ani też nie czyni wyraźnego rozróżnienia między „czasem lokalnym” a „czasem w określonej strefie czasowej”. A jeśli chcesz korzystać z kalendarza innego niż gregoriański, musisz
Calendar
cały czas przechodzić przez zajęcia.Dlatego właśnie buduję Noda Time - alternatywną bibliotekę dat i godzin zbudowaną na porcie "silnika" Joda Time , ale z nowym (i odchudzonym) API na wierzchu.
Kilka punktów, o których warto pomyśleć, a które łatwo przeoczyć, jeśli ich nie znasz:
TimeZoneInfo
szczerze mówiąc więcej, niż jest ogólnie skłonny ujawnić. (Nie obsługuje strefy czasowej, w której idea „czasu standardowego” zmienia się w czasie lub która przechodzi w stały czas letni).Jeśli chodzi o konkretne praktyki rozwojowe:
DateTime.Now
lubDateTime.UtcNow
; ułatwia to (wykonalne!) testy jednostkoweźródło
Warto zauważyć, że błąd prawdopodobnie nie był spowodowany taką linią, jaką opublikowałeś:
DateTime.Now.AddYears(1)
To nie tworzy nieprawidłowej daty. Jeśli biegasz:
(new DateTime(2012, 2, 29)).AddYears(1)
otrzymasz 28 lutego 2013 r. Nie wiem, w jakim języku jest napisany agent gościa platformy Azure, ale musiało to być inne połączenie, które się nie powiodło. Zły sposób na zrobienie tego w .NET to:
new DateTime(today.Year + 1, today.Month, today.Day)
To rzuca wyjątek, jeśli
today
jest dzień przestępny. Jednak na blogu firmy Microsoft dotyczącym problemu z platformą Azure podano, że utworzono nieprawidłową datę 29 lutego 2013 r., Co, nie jestem pewien, jest możliwe do zrobieniaDateTime
w .NET.Nie mówię tego
DateTime
iDateTimeOffset
nie są podatne na błędy, po prostu nie sądzę, że spowodowałyby ten konkretny problem.źródło
Testy jednostkowe w konkretnych datach, jak wspomniał John, to jedna praktyka kodowania, która pomoże, ale nic nie przebije tego, co określam jako „ręczny test integracji”
zmień zegar na swoim serwerze deweloperskim / testowym i obserwuj, co się stanie, gdy upłynie czas.
Nie ugrzęźnij w szczegółach, czy jest to `` praktyka kodowania '' - Oczywiście nie możesz tego zrobić dla każdej daty w kalendarzu - wybierz daty, które Cię interesują, na przykład 29 lutego, koniec miesiąca daty lub daty zmiany czasu na letni.
źródło