為了某些專案的進度追蹤,改成逐周方式確認。在溝通過程中,發現週數老是對不上,原來大家的週數計算方式都不太一樣。我的紙本行事曆跟電腦行事曆也不太一樣。
原來,計算一週之始有好幾種方法,例如
- 1/1 日開始一定算第一周。
- 不管 1/1,從一年的第一個星期天開始算第一周。
- 不管 1/1,從一年的第一個星期一開始算第一周。
像是波斯灣阿拉伯國家是週六開始算第一周,巴基斯坦跟愛沙尼亞是把 1/7 當作一年開始來計算。即便是上述的幾種方式,在同一個國家內也有不同的偏好阿。像我的行事曆就是 1/1 開始當作第一周,而我的電腦則是把週日開始算為第一周。兩個相較起來就差了一週。
在 Linux 上,其實 en_US 跟 zh_TW 兩種不同的語系設定,開始週數是不同的。en_US 使用的是 1/1 開始那周算第一周,而 zh_TW 則是設定成第一個週一是第一周。用 ncal 看起來像是這樣
$ LC_TIME=en_US.UTF8 ncal -w 1 2009 January 2009 Mo 5 12 19 26 Tu 6 13 20 27 We 7 14 21 28 Th 1 8 15 22 29 Fr 2 9 16 23 30 Sa 3 10 17 24 31 Su 4 11 18 25 1 2 3 4 5
$ LC_TIME=zh_TW.UTF8 ncal -w 1 2009 一月 2009 一 5 12 19 26 二 6 13 20 27 三 7 14 21 28 四 1 8 15 22 29 五 2 9 16 23 30 六 3 10 17 24 31 日 4 11 18 25 52 1 2 3 4
上述的算法,時常造成同一周被定義兩次,他可能是去年的 53 周,又是今年的第 1 周。這樣很容易造成困擾。
為了避免這種糾紛產生,其實有一份 ISO 8601 定義了週數的算法。ISO 8601 除了制定時間字串的格式之外,也定義了週數的計算方式。規則稍微複雜一點,但是是為了避免一個周被計算兩次。
ISO 8601 的計算方式是
- 包含第一個週四的算第一周。
- 包含 1/4 的那一週。
- 第一週超過四天以上。
- 12/29 後的第一個週一。
詳細算法請見 ISO Week Date。你在 Linux 上,可以用 date 指令查到以下依照週一、週日、ISO 算法的週數
$ date +"Sunday %U Monday %W ISO %V" -d '2010-01-01' Sunday 00 Monday 00 ISO 53 $ date +"Sunday %U Monday %W ISO %V" -d '2010-01-03' Sunday 01 Monday 00 ISO 53 $ date +"Sunday %U Monday %W ISO %V" -d '2010-01-04' Sunday 01 Monday 01 ISO 01