ちょいと気になって週番号について調べてみた。それについて書いておこっと。
週番号、週 BANG!! GO!! (悪のり)
まず、週番号とは具体的に何ぞや、ということでこれを簡単に知るためには Wikipedia を見るのが手っ取り早いね。
日付と時刻の表記に関する国際規格
である ISO 8601 のページに書いてある説明を簡単にまとめると以下のようになるかな。
- ある年の第1週を01で表し、よって最終週は52または53となる
- 最初の木曜日を含む週がその年の第1週である
- 週番号は週の始まりを月曜日として数える
ほぅほぅ、いろいろと知らなかったことが書いてあった。
最終週の週番号が年によって52か53に変わるってのも知らなかったけど、更に木曜日を基準に考えているなんてことは全く知らなかった。
何故、木曜日が優遇されてるのかは分からないけど、これによって12月でも次の年の第1週に数えたり、1月でも前の年の最終週に数えたりということがあるということ。何か強大な圧力が作用してこうなったんだろうね!(勝手な想像)
明日、学校や会社で知識をひけらかしたらイイと思うよ。
週番号の求め方
さてさて、そんな週番号を求めるにはどうしたらいいか。親切なことに英語版 Wikipedia の ISO week date のページには計算の仕方が書いてあった。
ある日付から週番号を計算する
| 月 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 平年 | 0 | 31 | 59 | 90 | 120 | 151 | 181 | 212 | 243 | 273 | 304 | 334 |
| 閏年 | 0 | 31 | 60 | 91 | 121 | 152 | 182 | 213 | 244 | 274 | 305 | 335 |
ここでは、例として今日の日付で計算してみるかな。 (2010年5月12日 水曜日)
- 上のテーブルを使って累積日数を求める
- Ordinal day: 120+12=132
- 曜日を数値として数える (月曜日を1として日曜日を7とする)
- Weekday: 水曜日=3
- 累積日数から曜日を引いて10を足す
- (Ordinal day)-(Weekday)+10=132-3+10=139
- 7で割って端数は切り捨てる
- 139/7=19
- 求めた数字が0のときは前の年の最終週となり、53のときは次の年の第1週の場合もあるので確認する
- 今回はそのまま、週番号は19!
週番号は2010W19って表すとなんかいいよね。それだけw
ちなみに、最後の手順で0になったときは、前の年の最終週の週番号が52か53か分からないのでもう一度計算しないといけない。慣れれば0を計算で求める前に0になりそうなのは分かるようになるよね。いや、 sima は慣れてないから分からないけど。53になったときは、その年の12月31日が月、火、水曜日だったら次の年の第1週とすればイイはず、…多分。
ところで何で10を足すんだろ、深く考えずにまるまんま信じて計算したけど気になるっちゃあ気になるね。何でだろ。
ある週番号と曜日から日付を計算する
反対に週番号から日付を求める方法も書いてあったので、興味がある人は ISO week date を見るとイイと思うよ。決して説明が面倒になったとかそういうわけではな…。
誰も待ってない MortScript のスクリプト
話としては以上なんだけど、マニアックな言語 MortScript である日付の週番号を求めるスクリプトを書いたのでせっかくだから載せておこっと。確実に需要はないだろうけどw
# 今日の日付の場合
# u=TimeStamp()
# とある日付の場合
u=MakeTimeStamp(2010,5,12)
year=FormatTime("Y",u)
CallFunction("calcWeekNumber",week,u)
If(week=0)
year-=1
CallFunction("calcWeekNumber",week,MakeTimeStamp(year,12,31))
ElseIf(week=53)
lastday=FormatTime("w",MakeTimeStamp(year,12,31))
If(lastday>0 && lastday<4)
year+=1
week=1
EndIf
EndIf
weekdate=year&"W"&(week<10?"0":"")&week
Message(weekdate)
Sub calcWeekNumber
Local()
u=argv[1]
y=FormatTime("Y",u)
If(y MOD 4 =0 && (y MOD 100 <>0 || y MOD 400 =0))
# 閏年
ordinaldate=Array(0,31,60,91,121,152,182,213,244,274,305,335)
Else
# 平年
ordinaldate=Array(0,31,59,90,120,151,181,212,243,273,304,334)
EndIf
d=FormatTime("w",u)
d=(d=0?7:d)
Return(Floor((ordinaldate[FormatTime("m",u)*1]+FormatTime("d",u)-d+10)/7))
EndSub
Exit
MortScript はあまりにもマニアックなので、 JavaScript でも書いてみた。




