Gaucheプログラミング(立読み版) > 第2部: 実用 > スケジュールCGIを書こう > 時間型と日付型 > ある日付を与えてその月のカレンダーを生成する


[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

ある日付を与えてその月のカレンダーを生成する 応援する 

srfi-19ライブラリの<date>型の値を与えて、「“要素数7のリスト”のリスト」でその月のカレンダーを表現するにはどうしたら良いでしょうか?

例:

((#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 29 30 31 #f #f #f))

この例ではこの月の最初の日は月曜日なので、最初の週を表現するリストの先頭要素、つまり日曜日の位置に#fを置いてカレンダーを表現しています。

月の最初の日までの曜日を埋める

月の最初の日までの曜日を#fで埋めるにはどうしたらよいでしょうか?

「ある日付を与えてその日の曜日を曜日を得る」で見たように、ある日付の曜日の値を得るにはsrfi-19ライブラリのdate-week-day手続きが使えます。

例:

 gosh> (use srfi-19)
 
 gosh> (date-week-day
        (make-date 0 0 0 0 1 1 2007 (date-zone-offset  (current-date))))
 1        ;; 月曜日

曜日の値は日曜日なら0、月曜日なら1、...土曜日なら6なのですから、曜日の値の数ぶんの要素数を持つリストをmake-list手続きで生成してやれば良いのです。

例:

 gosh> (make-list
        (date-week-day
         (make-date 0 0 0 0 1 1 2007 (date-zone-offset (current-date))))
        #f)
 (#f)

先頭を埋めた日付のリストを作る

「ある日付を与えてその月の最初の日を求める」で見たように、その月の最初の日を求めるfirst-day-of-month手続きは次の通りに書けました。

(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)))

また、「その月の日数を求める」で見たように、月の日数を求めるdays-of-month手続きは次の通りに書けました。

(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 (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手続きが使えました。その月の日数分の連続した数からなるリストを得るには、days-of-month手続きで得た日数ぶんのリストをiota手続きで生成してやれば良いことになります。

例:

 gosh> (iota (days-of-month (current-date)) 1)
 (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 29 30 31)

月の最初の日までの曜日を#fで埋めたリストと日数分のリストを連結してやれば、その月のカレンダーの元になるリストが得られそうです。

例:

 gosh> (append
        (make-list
         (date-week-day
          (first-day-of-month (current-date))))
        (iota (days-of-month (current-date)) 1))
 (#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 29 30 31)

util.listライブラリのslices手続きを使って、このリストを要素7のリストに分割すればリストのリストでカレンダーを表現することができます。

例:

 gosh> (slices
        (append
        (make-list
         (date-week-day
          (first-day-of-month (current-date))))
        (iota (days-of-month (current-date))))
        7 #t #f)
 ((#f 0 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 29 30 #f #f #f))

カレンダーを生成するdate-slices-of-month手続きを書く

上記から、任意の日付dateを与えて「“要素数7のリスト”のリスト」でカレンダーを生成するdate-slices-of-month手続きは次の通りに書けます。

 (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))

[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

このサイトについて|ヘルプ|Q&A|個人情報保護|プライバシーポリシー|利用規約|コメント・トラックバック規約|削除規程|広告掲載
Copyright (c) 2005-2007 Time Intermedia Corporation