(.module: [library [lux #* ["_" test (#+ Test)] [abstract [monad (#+ do)] [\\specification ["$." equivalence]]] [control ["." try ("#\." functor)] ["." exception] [parser ["<.>" text]]] [math ["." random (#+ Random)] [number ["n" nat] ["i" int]]] [time ["." date ("#\." equivalence)] ["." year]]]] [\\program ["." /]]) (def: .public random (Random /.Date) (random.one (function (_ raw) (try.maybe (do try.monad [year (|> raw date.year year.value i.abs (i.% +9,000) (i.+ +1,000) year.year) raw (date.date year (date.month raw) (date.day_of_month raw))] (/.date raw)))) random.date)) (def: .public test Test (<| (_.covering /._) (_.for [/.Date]) (do random.monad [expected ..random candidate random.date] ($_ _.and (_.for [/.equivalence] ($equivalence.spec /.equivalence ..random)) (_.cover [/.format /.parser] (|> expected /.format (.result /.parser) (try\map (\ /.equivalence = expected)) (try.else false))) (_.cover [/.value /.date] (|> expected /.value /.date (try\map (\ /.equivalence = expected)) (try.else false))) (_.cover [/.year_is_out_of_range] (case (/.date candidate) (#try.Success date) (same? candidate (/.value date)) (#try.Failure error) (exception.match? /.year_is_out_of_range error))) (_.cover [/.epoch] (date\= date.epoch (/.value /.epoch))) ))))