Welcome to the CHICKEN Scheme pasting service
my date module added by C-Keen on Thu Jul 7 16:12:56 2016
(module date (seconds->date-list today date-list->seconds date<? day-of-week days-in-month valid-date? valid-partial-date?) (import chicken scheme) (use srfi-1 posix) (define (seconds->date-list secs) (let ((t (seconds->utc-time secs))) (list (+ 1900 (vector-ref t 5)) (add1 (vector-ref t 4)) (vector-ref t 3)))) (define (today) (seconds->date-list (current-seconds))) (define (date-list->seconds d) (let ((t (make-vector 10 0))) (set! (vector-ref t 5) (- (first d) 1900)) (set! (vector-ref t 4) (sub1 (second d))) (set! (vector-ref t 3) (third d)) (utc-time->seconds t))) (define (date<? a b) (if (= (first a) (first b)) (if (= (second a) (second b)) (< (third a) (third b)) (< (second a) (second b))) (< (first a) (first b)))) (define (leap-year? y) (cond ((not (zero? (modulo y 4))) #f) ((zero? (modulo y 400)) #t) ((zero? (modulo y 100)) #f) (else #t))) (define days-in-month-list '(#f 31 28 31 30 31 30 31 31 30 31 30 31)) ;; This is probably not correct for *all* julian calendars and their ;; reforms over the centuries but at least it has been stable for the ;; last 115 years now. (define (days-in-month date) (let ((m (second date))) (if (and (= m 2) (leap-year? (car date))) 29 (list-ref days-in-month-list m)))) (define (valid-date? d) (and-let* ((_ (every number? d)) (_ (= (length d) 3)) (y (first d)) (m (second d)) (d (third d)) (_ (<= 1900 y)) (_ (<= 1 m 12)) (max-days (days-in-month m))) (<= 1 d max-days))) (define (valid-partial-date? date) (or (null? date) (and-let* ((_ (<= 1 (length date) 3)) (filled-partial (append date (make-list (- 3 (length date)) 1)))) (valid-date? filled-partial)))) ;; Calculates the weekday of a given date using Gauss's method ;; https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week ;; Weekday of the first day of a year A: ;; ;; R(1 + 5R(A-1,4) + 4R(A-1,100) + 6R(A-1,400),7) where R(y,m) = (modulo y m) (define (day-of-week date) (let* ((A (first date)) (m (second date)) (d (third date)) (first-day (modulo (+ 1 (* 5 (modulo (sub1 A) 4)) (* 4 (modulo (sub1 A) 100)) (* 6 (modulo (sub1 A) 400))) 7)) (month-days (cond ((and (= m 1) (= d 1)) -1) ((> m 1) (+ (if (and (> m 2) (leap-year? A)) 1 0) (sub1 (apply + (take (cdr days-in-month-list) (sub1 m)))))) (else -1)))) ;; The gauss method reorders the weekdays, starting at sunday (0) ;; We however want the week to start on monday, hence the renumbering (let ((dow (modulo (+ first-day d month-days) 7))) (if (< (sub1 dow) 0) 6 (sub1 dow))))) ;; Ben Daglish's simple method, see http://www.ben-daglish.net/moon.shtml ;; Returns the phase day (0 to 29, where 0=new moon, 15=full etc.) for ;; the selected date. #;(define (moon-phase date) (let ((lunar-phase 2551443) (new-moon 588900000) (date (time->milliseconds (date->time (date-subtract-duration (make-date 0 0 0 0 day month year) (make-duration #:months 1)))))) (inexact->exact (add1 (floor (/ (modulo (/ (- date new-moon) 1000) lunar-phase) (* 24 3600))))))) ) ;; Module