スケジュールを表示したり入力したりする際に、月ごとのカレンダーが表示できると便利です。
ここでは「“要素数7のリスト”のリスト」でカレンダーを表現することにしましょう。
((#f #f #f #f 1 2 3)
(4 5 6 7 8 9 10)
(11 12 13 14 15 16 17)
(18 19 20 21 22 23 24)
(25 26 27 28 #f #f #f))
各週を表すリストは日曜日から始まることにします。
今月のカレンダーを計算するためには次の項目が必要です。
- 現在の日付を得る
- ある日付を与えてその月の最初の日を求める
- 次の月、前の月を求める
- ある月の日数を求める
- その月の1日から末日までの日にちを要素としたリストを得る
- リストを複数のリストに分割する
「現在の日付を得る」で見たように、現在日付はsrfi-19ライブラリのcurrent-date手続きで得られます。
「<date>型の値を生成する」で見たように、ある日付を与えてその月の最初の日を求めるにはsrfi-19ライブラリのmake-date手続きが使えます。
(use srfi-19)
(define (make-month m y)
(make-date 0 0 0 0 1 m y (date-zone-offset (current-date))))
(define (first-day-of-month date)
(make-month (date-month date) (date-year date)))
「次の月、前の月を求める」で見たように、make-date手続きに与える月と年の値を増減することで、次の月、前の月の1日(朔日)を求めることができます。
(define (next-month date)
(if (= (date-month date) 12)
(make-month 1 (+ (date-year date) 1))
(make-month (+ (date-month date) 1) (date-year date))))
(define (prev-month date)
(if (= (date-month date) 1)
(make-month 12 (- (date-year date) 1))
(make-month (- (date-month date) 1) (date-year date))))
「日数(=日付の差)を計算する」「その月の日数を求める」で見たように次の月の1日(朔日)と、その月の1日(朔日)との差を求めればその月の日数が計算できます。
(define (days-of-month date)
(inexact->exact
(round
(- (date->modified-julian-day (next-month date))
(date->modified-julian-day (first-day-of-month date))))))
「連続した数を要素とするリストを生成する」で見たように、ある月の日にちを要素とするリストを得るにはsrfi-1ライブラリのiota手続きが使えます。
また、「リストを複数のリストに分割する」で見たように、ある月の日にちを要素とするリストを「“要素数7のリスト”のリスト」に分割するにはutil.listライブラリのslices手続きが使えます。
(define (date-slices-of-month date)
(slices (append (make-list (date-week-day (first-day-of-month date)) #f)
(iota (days-of-month date) 1))
7 #t #f))
date-slices-of-month手続きをためしに実行してみましょう。
gosh> (date-slices-of-month (current-date))
((#f #f #f #f 1 2 3) (4 5 6 7 8 9 10) (11 12 13 14 15 16 17) (18 19 20 21 22 23 24) (25 26 27 28 #f #f #f))
カレンダーが「“要素数7のリスト”のリスト」で表現できました。
これでカレンダーの基本手続きは完成しました。次にこれをHTMLとして表示してみましょう。
by えんどうやすゆき
Trackback URL: http://karetta.jp/trackback/book/012619/012751 Trackbacks: |