(define-module (datetime util) :use-module (datetime) :use-module (srfi srfi-1) :use-module (srfi srfi-26) :use-module (srfi srfi-41) :use-module (util) ) (define-public (start-of-month date) (set (day date) 1)) (define-public (parse-freeform-date str) (let* (((year month day) (map string->number (string-split str #\-)))) (date year: year month: month day: day) )) (define-public (day-stream start-day) (stream-iterate (cut date+ <> #0-0-1) start-day)) (define-public (month-stream start-day) (stream-iterate (cut date+ <> #0-1-0) start-day)) (define-public (week-stream start-day) (stream-iterate (cut date+ <> (date day: 7)) start-day)) (define-public (time-min a b) (if (timestring date optional: (fmt "~Y-~m-~d") key: allow-unknown?) (with-output-to-string (lambda () (fold (lambda (token state) (case state ((#\~) (case token ((#\~) (display "~")) ((#\Y) (format #t "~4'0d" (year date))) ((#\m) (format #t "~2'0d" (month date))) ((#\d) (format #t "~2'0d" (day date))) ((#\1) (format #t "~4'0d-~2'0d-~2'0d" (year date) (month date) (day date))) ((#\a) (display (week-day-name (week-day date)))) (else (unless allow-unknown? (error 'date->string "Invalid format token ~a" token)))) #f) (else (unless (char=? #\~ token) (display token)) token))) #f (string->list fmt))))) (define*-public (time->string time optional: (fmt "~H:~M:~S") key: allow-unknown?) (with-output-to-string (lambda () (fold (lambda (token state) (case state ((#\~) (case token ((#\~) (display "~")) ((#\H) (format #t "~2'0d" (hour time))) ((#\M) (format #t "~2'0d" (minute time))) ((#\S) (format #t "~2'0d" (second time))) ;; ((#\z) (when (utc? time) (display "Z"))) (else (unless allow-unknown? (error 'time->string "Invalid format token ~a" token)))) #f) (else (unless (char=? #\~ token) (display token)) token))) #f (string->list fmt))))) ;; @verbatim ;; A B C D E ¬F ;; |s1| : |s2| : |s1| : |s2| : : |s1| ;; | | : | | : | ||s2| : |s1|| | : |s1||s2| : | | ;; | ||s2| : |s1|| | : | || | : | || | : | || | : ;; | | : | | : | || | : | || | : | || | : |s2| ;; | | : | | : | | : | | : : | | ;; @end verbatim ;; ;; E is covered by both case A and B. (define-public (timespan-overlaps? s1-begin s1-end s2-begin s2-end) "Return whetever or not two timespans overlap." (or ;; A (and (date/-time (24 25 26 27 28 29) ;; => (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) ;; => (1 2 3 4 5) (define-public (month-days date week-start) (let* ((month (month date)) (month-len (days-in-month date)) (prev-month-len (days-in-month (month- date))) (month-start (modulo (- (week-day date) week-start) 7))) (values (iota month-start (1+ (- prev-month-len month-start))) (iota month-len 1) (iota (modulo (- (* 7 5) month-len month-start) 7) 1))))