2020年到了,祝大家新年快樂!
2020年是一個閏年(Leap Year),閏年是會出故障的。八年前,2012年2月29日,我在Azure的時候我們就出了一個大故障:
https://azure.microsoft.com/en-us/blog/summary-of-windows-azure-service-disruption-on-feb-29th-2012/常見的錯誤認知
1、 一年總是365天
2、2月總是28天
3、閏年是每四年一次
其實,閏年并不是每四年一次。2000是閏年,但1900年和2100都不是閏年。
哪裡容易出閏年相關的Bug
1、在一個日期值上加或減時間的代碼。尤其是加減1年或1個月的代碼
2、各種根據資料庫查詢結果生成的報表和圖示,月度和年度統計可能會少算1天
3、證書/密碼/密鑰/緩存 等的過期時間,可能會比預期的早了一天,或者可能設定了一個非法的過期時間
4、固定長度的數組。例如,一個長度為365的數組遇到閏年可能就不夠了,可能會數組越界。
5、UI元件,例如月曆、日期選擇元件,以及用戶端輸入校驗相關的代碼。
閏年的哪些日子要特别注意
2019年12月31日:這是閏年前一年的最後一天。2019年的最後一天加365天,并不是2020年的最後一天,而會是2020年的倒數第二天(即2020年12月30日)。
2020年1月1日:閏年的第一天。閏年的第一天加365天,并不是下一年的1月1日,而是今年的12月31日。
2020年1月31日:這一天加28天,并不是下個月(2月)的最後一天。
2020年2月1日:這一天加28天,并不是下個月(3月)的第一天。
2020年2月28日:這是2月29日的前一天。有問題的代碼可能會錯誤的把這天當成2月的最後一天,試圖加1天得到3月1日。但實際上這一天加1天是2月29日。
2020年2月29日:這是閏年多出來的一天。如果代碼以為2月總是隻有28天,那代碼可能出現各種問題,例如:
入參校驗會認為一個合法輸入(2020/2/29)是非法的,用
{ year+1 , month , day }
的方式來加減1年的話會産生一個非法日期。
2020年3月1日:2月29日後面的那天。代碼如果在3月1日上減28天,會得到2月2日(而不是預期中的2月1日);減365天的話會得到2019年3月2日(而不是預期中的3月1日)。
2020年12月31日:一年的第366天。
代碼如果不能正确處理一年的第366天,可能也會導緻問題。例如,2008年12月31日,第三方軟體中的問題導緻了所有Microsoft Zune裝置無法使用,詳情參考:
http://www.theguardian.com/technology/blog/2009/jan/01/zune-firmware-mistake代碼如果假設1年永遠是365天,聲明了一個固定大小為365的數組,那在一年的第366天可能會發生數組越界。
數組越界如果發生在 C/C++ 語言編寫的代碼裡,可能導緻記憶體溢出攻擊漏洞。
閏秒
除了閏年,還有一個東西叫閏秒,詳情參考:
https://en.wikipedia.org/wiki/Leap_second不過由于在阿裡巴巴集團大部分同學平時相處的都是應用層代碼,處理的都是日月年,最多也就精細到小時和分鐘,閏秒對我們的影響相對小很多。閏秒對于GPS等一些對時間的精密度要求比較高的系統會影響比較大。
本文作者:
鄭子穎,花名南門,現任職螞蟻金服 國際事業群 品質和技術風險部 資深總監。上海交通大學計算機系碩士畢業後加入微軟,2018年加入螞蟻金服。從事軟體開發18年,工作重心主要圍繞着測試、品質以及工程效能。目前,我團隊正在國内和海外多地招聘測試開發崗位,歡迎海内外專業人士加入我們,職位詳情:
https://hire.alibaba-inc.com/i18n/positionDetail.html?positionId=576717