; Appendix C
; Recursive computation of the difference between dates
; Return the number of days spanned by earlier-date
; and later-date.
; Earlier-date and later-date both represent dates in 2002,
; with earlier-date being the earlier of the two.
(define (day-span earlier-date later-date)
(cond
((same-month? earlier-date later-date)
(same-month-span earlier-date later-date) )
((consecutive-months? earlier-date later-date)
(consec-months-span earlier-date later-date) )
(else
(general-day-span earlier-date later-date) ) ) )
; Access functions for the components of a date.
(define (month-name date) (first date))
(define (date-in-month date) (first (butfirst date)))
; Return true if date1 and date2 are dates in the same month, and
; false otherwise. Date1 and date2 both represent dates in 2002.
(define (same-month? date1 date2)
(equal? (month-name date1) (month-name date2)))
; Return the number of the month with the given name.
(define (month-number month-name)
(cond
((equal? month-name 'january) 1)
((equal? month-name 'february) 2)
((equal? month-name 'march) 3)
((equal? month-name 'april) 4)
((equal? month-name 'may) 5)
((equal? month-name 'june) 6)
((equal? month-name 'july) 7)
((equal? month-name 'august) 8)
((equal? month-name 'september) 9)
((equal? month-name 'october) 10)
((equal? month-name 'november) 11)
((equal? month-name 'december) 12) ) )
; Return true if date1 is in the month that immediately precedes the
; month date2 is in, and false otherwise.
; Date1 and date2 both represent dates in 2002.
(define (consecutive-months? date1 date2)
(=
(month-number (month-name date2))
(+ 1 (month-number (month-name date1))) ) )
; Return the difference in days between earlier-date and later-date,
; which both represent dates in the same month of 2002.
(define (same-month-span earlier-date later-date)
(+ 1
(- (date-in-month later-date) (date-in-month earlier-date)) ) )
; Return the number of days in the month named month-name.
(define (days-in-month month-name)
(cond
((equal? month-name 'january) 31)
((equal? month-name 'february) 28)
((equal? month-name 'march) 31)
((equal? month-name 'april) 30)
((equal? month-name 'may) 31)
((equal? month-name 'june) 30)
((equal? month-name 'july) 31)
((equal? month-name 'august) 31)
((equal? month-name 'september) 30)
((equal? month-name 'october) 31)
((equal? month-name 'november) 30)
((equal? month-name 'december) 31) ) )
; Return the number of days remaining in the month of the given date,
; including the current day. Date represents a date in 2002.
(define (days-remaining date)
(+ 1 (- (days-in-month (month-name date)) (date-in-month date))) )
; Return the difference in days between earlier-date and later-date,
; which represent dates in consecutive months of 2002.
(define (consec-months-span earlier-date later-date)
(+ (days-remaining earlier-date) (date-in-month later-date)) )
; Return the name of the month with the given number.
; 1 means January, 2 means February, and so on.
(define (name-of month-number)
(item
month-number
'(january february march april may june
july august september october november december) ) )
; Return the sum of days in the months represented by the range
; first-month through last-month.
; First-month and last-month are integers; 1 represents January,
; 2 February, and so on.
; This procedure uses recursion.
(define (day-sum first-month last-month)
(if (> first-month last-month) 0
(+
(days-in-month (name-of first-month))
(day-sum (+ first-month 1) last-month)) ) )
; Return the number of the month that immediately precedes the month
; of the given date. 1 represents January, 2 February, and so on.
(define (prev-month-number date)
(- (month-number (month-name date)) 1) )
; Return the number of the month that immediately follows the month
; of the given date. 1 represents January, 2 February, and so on.
(define (next-month-number date)
(+ (month-number (month-name date)) 1) )
; Return the difference in days between earlier-date and later-date,
; which represent dates neither in the same month nor in consecutive months.
(define (general-day-span earlier-date later-date)
(+
(days-remaining earlier-date)
(day-sum
(next-month-number earlier-date)
(prev-month-number later-date) )
(date-in-month later-date) ) )