跨年过程中因日期格式化引发的生产故障:格式化方式YYYYMMdd和yyyyMMdd的区别
文章目錄
- 故障背景
- 故障分析
- 故障重現
- 解釋總結
故障背景
某公司進行一年一度的跨年上線工作,在2018年的12月30號上午忽然接到保障業務無法運行,而且影響全國業務。
故障分析
第一步:因為近期沒有業務上線活動,首先排除因上線因此引起的故障。
第二步:分析業務日志。發現業務中報錯的原因是沒有查到業務表中前期存的業務數據。
第三步:查詢前期存表操作,查找是什么原因導致業務數據沒有存到數據庫中。然后發現業務中并沒有拋出任何存表異常(這是一個坑,筆者也跳進去了饒了好幾次才發現)。此處解釋一下:因為業務數據量比較大,因此業務上采取的是分年月的分表規則進行業務信息存儲,同時此時屬于跨年的時間節點,業務上一般會提前一周將下一年的表結構刷入數據庫中。
第四步:故障定位。上面的數據庫確實沒報錯,然后通過顯示mybatis中sql語句方式,看到sql入的表是T_BUSI_201912的表,也就是說本來如表應該是T_BUSI_201812的表現在存到表T_BUSI_201912,很明顯,這里的分表日期計算錯了。因為T_BUSI_201912表結果已經提前刷入生產環境,因此沒有出現入庫異常。
故障重現
根據上面的分析,我們找到了錯誤的原因開發者使用的是YYYYMMdd格式化當前日期。那現在就用測試代碼重現一下當時的故障。測試代碼如下所示:
/*** 故障重現*/public static void troubleReproduce() throws ParseException {//業務中使用的日期格式化方式String formate1 = "YYYYMMdd";//比較格式化方式String formate2 = "yyyyMMdd";//這個是故障發生的時間String dateTime = "20181230";//這個是故障發生前一天的時間String dateTimeTest = "20181229";//這個是將字符串轉換成時間Date date = new SimpleDateFormat(formate2).parse(dateTime);Date dateTest = new SimpleDateFormat(formate2).parse(dateTimeTest);System.out.println("使用[" + formate1 + "]格式化前后{"+dateTime+"} -> " + (new SimpleDateFormat(formate1).format(date)));System.out.println("使用[" + formate2 + "]格式化前后{"+dateTime+"} -> " + (new SimpleDateFormat(formate2).format(date)));System.out.println("-----------------分割線---------------------");System.out.println("使用[" + formate1 + "]格式化前后{"+dateTimeTest+"} -> " + (new SimpleDateFormat(formate1).format(dateTest)));System.out.println("使用[" + formate2 + "]格式化前后{"+dateTimeTest+"} -> " + (new SimpleDateFormat(formate2).format(dateTest)));}打印結果如下:
使用[YYYYMMdd]格式化前后{20181230} -> 20191230 使用[yyyyMMdd]格式化前后{20181230} -> 20181230 -----------------分割線--------------------- 使用[YYYYMMdd]格式化前后{20181229} -> 20181229 使用[yyyyMMdd]格式化前后{20181229} -> 20181229這個例子就重現了案發現場,如果是2018年12月29號的時候系統都能正常運行,到了2018年12月30號的時候系統就無法正常運行了,應該存T_BUSI_201812表的數據錯誤的存入T_BUSI_201912中。
解釋總結
上面成功找到了問題的原因,那我們要刨根問題為什么YYYYMMdd和yyyyMMdd得到的結果是不一樣的,為什么YYYYMMdd出現的結果是不對的?
因為YYYY是week-based-year,表示當天所在的周屬于的年份,2018年的12月30號是周日,周日在西方人認為是一周的第一天,因此本周存在跨年(2019年),所以就算入下一個年份中了。 但是2018年12月29號是本周的最后一天,這一周都在2018年,因此顯示是正常的。
所以這一點程序員要謹記,盡量不要使用YYYY這樣的年份規則。
總結
以上是生活随笔為你收集整理的跨年过程中因日期格式化引发的生产故障:格式化方式YYYYMMdd和yyyyMMdd的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单示例立马搞懂Java日期格式中yyy
- 下一篇: 遍历Map的几种方式以及性能小结