こんなのとか
2013/12
Sun Mon Tue Wed Thu Fri Sat
01 02 03 04 05 06 07
08 09 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 01 02 03 04
こんな感じの。
2013/12
Mon Tue Wed Thu Fri Sat Sun
25 26 27 28 29 30 01
02 03 04 05 06 07 08
09 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 01 02 03 04 05
実際のソースは以下。
class OneMonthCalendar {
def beginningOfWeek = "Sun"
def year = new Date().year + 1900
def month = new Date().month + 1
def weekSequence = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
def List<Date> getCalendar() {
// Javaは日曜日を0として6までの数値を返してくる。
// それに対応する週の項目
def week = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
// 表示する週の順番の指定。
weekSequence = week.drop(week.indexOf(beginningOfWeek)) + week.take(week.indexOf(beginningOfWeek))
// 基本となる年月
def baseDate = new Date("$year/$month/1")
// Dateオブジェクトから末日を求める
def getLastDay = {Date date -> date.toCalendar().getActualMaximum(Calendar.DATE)}
def thisMonth= (1..getLastDay(baseDate)).step(1).collect{new Date("$year/$month/$it")}
def daysRequiredLastMonth = weekSequence.indexOf(week[thisMonth.head().day])
def lastMonth = (0 ..< daysRequiredLastMonth).collect{ thisMonth.head() - (it+1) }.reverse()
// 既に一ヶ月のカレンダーとしてフルの場合
if((lastMonth + thisMonth).size() % 7 == 0) {
lastMonth + thisMonth
} else {
def daysRequiredNextMonth = 7 - ((lastMonth + thisMonth).size() % 7)
def nextMonth = (0 ..< daysRequiredNextMonth).collect{ thisMonth.last() + (it+1) }
lastMonth + thisMonth + nextMonth
}
}
}
// インスタンスの生成
def calendar = new OneMonthCalendar(year:2013, month:2, beginningOfWeek:"Sun")
// カレンダーを生成&取得!
def result = calendar.getCalendar()
/**********************************************************
* 以降は表示する際にどうするかなので、ケースバイケースでそれなりに。
*********************************************************/
// Listの中身はDateオブジェクトなので適当にほしい値に変換
perfectOne = result.collect{"${(it.date).toString().padLeft(2,'0')}"}
// とりあえず週の情報を表示してみる
println "${calendar.year}/${calendar.month}".center(35)
calendar.weekSequence.each{print it.center(5, " ")}
println ""
// list(1か月分のDateオブジェクト(カレンダー))を1週間ごとに分けるクロージャ
// 本当は末尾再帰を最適化するようにtrampolineを使って方が良いけど、
// 今回は5回だけの再帰と分かりきっているのでとりあえず無視
def spliter = { List list ->
!list ? [] : [list.take(7)] + call(list.drop(7))
}
// 用意したクロージャで一週間ごとに分けられたlistを表示。
spliter(perfectOne).each{ weeks ->
weeks.each{ week ->
print week.center(5, " ")
}
println ""
}