윤년 버그로부터 보호하기 위해 설계된 코딩 관행을 어떻게 개발할 수 있습니까? [닫은]
마이크로 소프트는 지난주 윈도우 애저에서 날짜를 계산할 때 소프트웨어 오류 (윤년 이상)로 인해 심각한 중단이 발생 했다고 발표 했습니다.
DateTime.Now.AddYears(1)
윤년에 대한 판단에서 정말 단순한 오류였습니까 ?
어떤 코딩 관행이 이것을 막을 수 있었습니까?
편집 dcstraw DateTime.Now.AddYears(1)
가 윤년에 지적했듯이 실제로 .NET에서 올바른 날짜를 반환합니다. 따라서 프레임 워크 버그는 아니지만 날짜 계산의 버그 인 것 같습니다.
뻔뻔한 플러그 :
더 나은 날짜 및 시간 API 사용
내장 된 .NET 날짜 및 시간 라이브러리는 제대로 사용하기가 매우 어렵습니다. 그들은 당신이 필요한 모든 것을 할 수 있게 해주지 만, 당신은 타입 시스템을 통해 자신을 명확하게 표현할 수 없습니다 . DateTime
은 엉망 이고, DateTimeOffset
그렇지 않을 때 실제로 시간대 정보를 보존하고 TimeZoneInfo
있다고 생각하게 만들 수 있으며 고려해야 할 모든 것에 대해 생각하도록 강요하지 않습니다.
이들 중 어느 것도 "단지 시간"또는 "단지 날짜"를 말하는 좋은 방법을 제공하지 않으며 "현지 시간"과 "특정 시간대의 시간"을 명확하게 구분하지 않습니다. 그레고리력이 아닌 다른 캘린더를 사용 Calendar
하려면 전체 시간 동안 수업 을 진행해야합니다 .
이 모든 것이 내가 Joda Time "엔진" 의 포트를 기반으로 구축 되었지만 새로운 (그리고 더 간결한) API가 위에 있는 대체 날짜 및 시간 라이브러리 인 Noda Time을 구축하는 이유 입니다.
당신이 생각하고 싶을 수있는 몇 가지 사항들, 당신이 그것을 모르면 놓치기 쉬운 :
- 현지 날짜 / 시간을 특정 시간대에 매핑하는 것은 생각만큼 간단하지 않습니다. 일광 절약 전환으로 인해 특정 현지 날짜 / 시간이 한 번, 두 번 (모호함) 또는 0 번 (건너 뛰었 음) 발생할 수 있습니다.
- 시간대는 역사적으로 다양
TimeZoneInfo
합니다. 솔직히 말해서 일반적으로 공개하고자하는 것보다 더 많습니다 . ( "표준 시간"이라는 개념이 시간이 지남에 따라 변경되거나 영구적 인 일광 절약 시간으로 전환되는 시간대는 지원하지 않습니다.) - zoneinfo 데이터베이스를 사용하더라도 시간대 ID가 반드시 안정적인 것은 아닙니다. (CLDR은이 문제를 해결합니다. 결국 Noda Time에서 지원하고 싶은 것입니다.)
- 날짜와 시간의 텍스트 표현은 순서뿐 아니라 날짜 구분 기호, 시간 구분 기호 및 생식력 달 이름과 같은 이상한 것들이 악몽입니다.
- 하루의 시작이 항상 자정은 아닙니다. 예를 들어 브라질에서는 봄 일광 절약 전환이 벽시계를 오후 11:59:59에서 오전 1 시로 이동합니다.
- 어떤 경우에는 (내가 알고있는) 시간대가 하루 종일 건너 뛰도록 강요 할 수 있습니다. 2011 년 12 월 30 일은 사모아에서 발생하지 않았습니다! 나는 대부분의 개발자가 아마도 이것을 무시할 수 있다고 생각하지만 ...
- 그레고리력이 아닌 다른 달력을 사용하려는 경우,주의를 기울이고 그것이 어떻게 작동 할 것으로 예상하는지 정말로 알고 있는지 확인하십시오.
특정 개발 관행에 관한 한 :
- 당신이 진정으로 표현하려는 것이 무엇인지 생각해보십시오. Noda Time의 핵심 이점은 개발자가 데이터를 표현하기 위해 다양한 유형 중에서 선택하도록 강요하는 것입니다. 제대로하면 다른 모든 것이 더 간단 해집니다.
- 생각할 수있는 모든 것을 단위 테스트합니다. 물론 시스템이 수행하는 작업에 따라 다르지만 특히 다른 시간대, 일광 절약 전환 동안 발생하는 작업, 물론 윤년을 고려합니다.
- 나는 명시 적으로
DateTime.Now
or를 호출하는 대신 현재 시간을 알려주는 서비스 인 "시계와 같은 인터페이스"를 삽입하는 것이 좋습니다DateTime.UtcNow
. 단위 테스트를 더 쉽게 (실행 가능합니다!) - "지금"으로 여러 작업을 수행하는 경우 "지금"을 반복적으로 요청하지 말고 해당 날짜 / 시간을 한 번 가져와 기억하십시오. 그렇지 않으면 값이 호출 사이에 불행한 방식으로 변경 될 수 있습니다.
- "모든 것이 UTC로 표시됩니까?"가 항상 답은 아닙니다. " '지금부터 2 주 후'가 정확히 언제 내 현지 시간대로 표시됩니까?" 그런 다음 현지 날짜 / 시간과 시간대 를 저장해야합니다 .
버그가 게시 한 것과 같은 줄로 인한 것이 아니라는 점은 주목할 가치가 있습니다.
DateTime.Now.AddYears(1)
그것은 잘못된 날짜를 생성하지 않습니다. 실행하는 경우 :
(new DateTime(2012, 2, 29)).AddYears(1)
2013 년 2 월 28 일을 받게됩니다. Azure의 게스트 에이전트가 무엇으로 작성되었는지 모르겠지만 실패한 다른 호출 이었음에 틀림 없습니다. .NET에서 이것을 수행하는 나쁜 방법은 다음과 같습니다.
new DateTime(today.Year + 1, today.Month, today.Day)
today
윤일 이면 예외 가 발생합니다 . 그러나 Azure 문제에 대한 Microsoft 블로그는 2013 년 2 월 29 일의 잘못된 날짜를 생성했다고 말했습니다.이 날짜는 DateTime
.NET에서 수행 할 수 있는지 확실하지 않습니다 .
나는 그것을 말하는 게 아니에요 DateTime
그리고 DateTimeOffset
나는 그들이이 특정 문제가 발생하는 것 생각하지 않는다 단지, 오류가 발생하기 쉬운되지 않습니다.
윤년 버그로부터 보호하기 위해 설계된 코딩 관행을 어떻게 개발할 수 있습니까? 어떤 코딩 관행이 이것을 막을 수 있었습니까?
John이 언급 한대로 단위 테스트 특정 날짜는 도움이되는 하나의 코드 실행이지만 내가 '수동 통합 테스트'로 정의한 것보다 나은 것은 없습니다.
개발 / 테스트 베드 서버의 시계를 변경하고 시간이 지날 때 어떤 일이 발생하는지 확인하십시오.
이것이 '코딩 관행'인지에 대한 세부 사항에 얽매이지 마십시오-분명히 달력의 모든 날짜에 대해 이것을 할 수는 없습니다-관심있는 날짜를 선택하십시오 .2 월 29 일, 월말 날짜 또는 일광 절약 전환 날짜.
'Program Tip' 카테고리의 다른 글
P 요소 안에 중첩 될 수있는 HTML5 요소 목록? (0) | 2020.10.05 |
---|---|
sqlalchemy의 선언적 ORM 확장을 사용하는 경우 다중 열 인덱스 (0) | 2020.10.05 |
자바 스크립트에서 부동 소수점 정밀도 다루기 (0) | 2020.10.05 |
Gradle : 둘 이상의 프로젝트 변형 : myLib이 소비자 속성과 일치합니다. (0) | 2020.10.05 |
누락 된 주석으로 인해 런타임에 ClassNotFoundException이 발생하지 않는 이유는 무엇입니까? (0) | 2020.10.05 |