(module iso-8601 mzscheme
(require (lib "pregexp.ss"))
(define px:ccyy-mm-dd #px"^(\\d{4})-(\\d{2})-(\\d{2})$") (define px:ccyymmdd #px"^(\\d{4})(\\d{2})(\\d{2})$") (define px:ccyy-mm #px"^(\\d{4})-(\\d{2})$") (define px:ccyy #px"^(\\d{4})$") (define px:cc #px"^(\\d{2})$")
(define px:yy-mm-dd #px"^(\\d{2})-(\\d{2})-(\\d{2})$") (define px:yymmdd #px"^(\\d{2})(\\d{2})(\\d{2})$")
(define px:ccyy-ddd #px"^(\\d{4})-(\\d{3})$") (define px:ccyyddd #px"^(\\d{4})(\\d{3})$")
(define px:yy-ddd #px"^(\\d{2})-(\\d{3})$") (define px:yyddd #px"^(\\d{2})(\\d{3})$")
(define px:ccyy-www-d #px"^(\\d{4})-W(\\d{2})-(\\d)$") (define px:ccyywwwd #px"^(\\d{4})W(\\d{2})(\\d)$") (define px:ccyy-www #px"^(\\d{4})-W(\\d{2})$") (define px:ccyywww #px"^(\\d{4})W(\\d{2})$")
(define px:yy-www-d #px"^(\\d{2})-W(\\d{2})-(\\d)$") (define px:yywwwd #px"^(\\d{2})W(\\d{2})(\\d)$") (define px:yy-www #px"^(\\d{2})-W(\\d{2})$") (define px:yywww #px"^(\\d{2})W(\\d{2})$")
(define px:hh:mm:ss #px"^(\\d{2}):(\\d{2}):(\\d{2})$") (define px:hhmmss #px"^(\\d{2})(\\d{2})(\\d{2})$") (define px:hh:mm #px"^(\\d{2}):(\\d{2})$") (define px:hhmm #px"^(\\d{2})(\\d{2})$") (define px:hh #px"^(\\d{2})$")
(define (read-digit str pos)
(let ([chr (string-ref str pos)])
(if (char-numeric? chr)
(char->integer chr)
#f)))
(define (read-number str start end)
(let loop ([accum 0] [pos start])
(if (< pos end)
(let ([digit (read-digit str pos)])
(loop (+ (* 10 accum) digit) (add1 pos)))
accum)))
(define (read-fraction input start end normalize-to)
(let loop ([accum 0] [pos start])
(if (< pos end)
(let ([digit (read-digit input pos)])
(loop (+ (* 10 accum) digit) (add1 pos)))
(let loop ([accum accum] [pos (- pos start)])
(if (< pos normalize-to)
(loop (* 10 accum) (add1 pos))
accum)))))
(define (parse-normal-date str format)
(match format
[(list 4 2 2)
]
[(list 8)
]
[(list 4 2)
]
[(list 4)
]
[(list 2)
]
[(list 2 2 2)
]
[(list 6)
]
[(list 4 3)
]
[(list 7)
]))
(define parse-date
(case-lambda
[(str) (parse-date str (date-format str))]
[(str format)
(case (car format)
[(#\D) (parse-normal-date str (cdr format))]
[(#\W) (parse-week-date str (cdr format))])]))
)