系統跨年的那些事兒

大家過年好!

 

跨年夜除了好好享受假期,系統上從技術上到業務上,都有值得關注的事兒。一年才觸發一次,頻率低,風險高。更需謹慎。

 

由於今年是我的本命年。本命年犯太歲。「太歲當頭坐 ,無喜必有禍」。本命年順的話,一順百順,鴻運當頭,勢不可擋。所以今天的標題全用大紅色~~

 

經典跨年Bug

在2021年的最後兩分鐘,我懷著忐忑和期待的心情迎接著本命年。並匆忙寫下下面的程式碼:

 

import cn.hutool.core.date.DateTime;
public void test() throws Exception {
System.out.println(new DateTime().toString("YYYY-MM-dd HH:MM:SS"));
}

 

運行結果:

2022-12-31 23:12:651

 

很多朋友知道我側重於穩定性方面的研究,但是最近提這個詞提的少了。在《架構-穩定性建設邏輯問題實戰總結》《穩定性的海因里希法則》里我也總結過:穩定性更多的是意識,不是方法。
穩定性方法本質就是兩點:

  • 多問幾個為什麼

  • 多問幾個如果發生了某某問題怎麼辦


這裡本質上就是一個「為什麼」的問題:所用的技術一定要深入理解。這個運行結果可能和一些人想像的不一致,本質上不是技術上的坑,而是對於日期格式化符號沒有理解。
在Java的SimpleDateFormat類注釋中有一張表,如下表所示:

 

 

 

在規定中,y表示year,而Y表示Week Year!

 

什麼是Week Year

 

我們知道,不同的國家對於一周的開始和結束的定義是不同的。如在中國,我們把星期一作為一周的第一天,而在美國,他們把星期日作為一周的第一天。因為不同人對於日期和時間的表示方法有不同的理解,於是,大家就共同制定了了一個國際規範:ISO 8601 。

 

國際標準化組織的國際標準ISO 8601是日期和時間的表示方法,全稱為《數據存儲和交換形式·資訊交換·日期和時間的表示方法》。

 

在 ISO 8601中。week year是說某一周只能屬於一個年份。2021年12月31日不能既屬於今年的最後一個星期,又是明年的第一個星期。

 

對於一年的第一個week year有以下3種等效說法:

1,本年度第一個星期四所在的星期

2,本年度第一個至少有4天在同一星期內的星期

3,星期一在去年12月29日至今年1月4日以內的星期

 

按照這個規範,2021年12月30日是星期四,滿足是新一年的第一個星期。那就是說打從2021年12月26日(星期日,ISO 8601中這是一周的第一天)開始,week year就已經是2022年了,新年已經到來了6天了!

 

日期格式化符號里M大寫的代表月份,小寫m代表分鐘,大寫S代表毫秒,小寫s代表秒。而一個日期格式化符號出現多少次就代表最少佔多少位,不夠的前面補0。



public void test() throws Exception {
System.out.println(new DateTime(DateTime.of("2021-12-26","yyyy-MM-dd"))
.toString("yyyy-MM-dd HH:mm:sssss"));

}

 

運行結果:

2021-12-26 00:00:00000

 

業務經典問題

2022年1月1日 0點10分。已經收到一些消息:網上反映QQ紅包伺服器炸了、QQ紅包發不出去,拼多多紅包提現慢、不能提現,微信紅包提示使用人數過多等。說明大家對新年活動的參與度很高嘛。
其實在各個領域都有一些跨年的業務要特殊處理。最常見的一個例子就是「年終決算」。在各個銀行,年終決算就是要把賬結清。如果一邊在做業務,一邊在算賬,很難算清楚。所以很多系統乾脆暫停業務來進行年終決算。

年終決算並不是會計等領域的特定名詞。早年的農村生產大隊也要進行年終決算。辦年終結算首先要列出6個指標來:
1,生產隊總收入
2,生產隊凈收入3,可分配收入4,全年勞動日值,也就是說社員勞動一天折算的工分換成現金有多少錢5,每戶社員應當分配的數額
6,每戶社員應當分配的實物和現金數量

是不是聽起來相當專業,據說那時候每個生產隊都會有一兩個這方面的高手,精通珠算。讓人不禁感嘆:高手在民間。