ひと月の週数を求める(その2:月曜始まり対応)

   2012/11/18

先日、ひと月の週数を
Calendar.getActualMaximum(Calendar.WEEK_OF_MONTH);で求める方法を書きました(→こちら)が
「月曜始まりの場合にはどうすればよいか?」というご質問を頂きました。

こんにちは、管理人イガジーです。
確かに、最近の手帳などでは「月曜始まり」が多くなっていますね。

そこで、自前で求めるメソッド(関数)を考えてみました。
ひと月の日数と、その月の1日が何曜日か、が分かれば求められそうですね。
「その月の1日が何曜日か」は、
int dow=c.get(Calendar.DAY_OF_WEEK);で得られます。
この結果は int で、1〜7の値になります。(1=日曜,2=月曜,…)

Calendar.SUNDAY,Calendar.MONDAY, ….などのStatic Field値が
定義されているのですが、今回は端折ります。

(dow+5)%7; という計算をすると、月曜始まり時の1日の位置(オフセット値)が
得られます。具体的には、次のようになります。
日曜: dow=1 , (dow+5)%7= 6
月曜: dow=2 , (dow+5)%7= 0
火曜: dow=3 , (dow+5)%7= 1
水曜: dow=4 , (dow+5)%7= 2

土曜: dow=7 , (dow+5)%7= 5
このオフセット値とひと月の日数を加算して7で割り、
余りを切り上げると週数が得られます。

日曜始まりの時は、(dow+6)%7; でオフセット値が得られます。
日曜: dow=1 , (dow+6)%7= 0
月曜: dow=2 , (dow+6)%7= 1

土曜: dow=7 , (dow+6)%7= 6

int ws という変数に、日曜始まり(0)か、月曜始まり(1)を入れるとすると
両方まとめて(dow+6-ws)%7; という計算で済みます。

まとめると、次のようなメソッドになります。
(※ ここの month は0始まりです。0=1月、1=2月…)

int weeks(int year, int month, int ws){ // ws=1:Mondaystart 0:SundayStart
	Calendar c=new GregorianCalendar(year,month,1);
	int dow=c.get(Calendar.DAY_OF_WEEK);
	int days=c.getActualMaximum(Calendar.DAY_OF_MONTH);
	int crn=(dow+6-ws)%7;
	days+=crn;
	int md=days%7;
	int wks=days/7;
	if (md!=0) ++wks;
	return wks;
}

端折るのが嫌だ(きちんとフィールド値で処理するべきだ)
と思う方は、dowをswitch/caseで処理してください。

switch (dow){
  case: Calendar.SUNDAY: crn=(7-ws)%7; break;
  case: Calendar.MONDAY: crn=1-ws; break;
...
  case: Calendar.SATURDAY: crn=6-ws; break;
}