-- |
-- Module      : Test.LeanCheck.Instances.Time
-- Copyright   : (c) 2019-2022 Rudy Matela
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : Rudy Matela <rudy@matela.com.br>
--
-- Declares 'Listable' time datatype instances.
--
-- Admitedly, these 'Listable' enumerations are defined somewhat arbitrarily...
module Test.LeanCheck.Instances.Time () where

import Data.Time
import Test.LeanCheck
import Test.LeanCheck.Tiers

-- | This listable enumeration starts with January 2019 then switches back and
--   forth between past and future.
--
-- > list :: [Day] =
-- >   [ 2019-01-01
-- >   , 2099-01-24
-- >   , 1938-12-09
-- >   , 2139-02-05
-- >   , 1978-12-20
-- >   , 2059-01-12
-- >   , 1898-11-27
-- >   , 2159-02-11
-- >   , 1998-12-26
-- >   , 2079-01-18
-- >   , ...
-- >   ]
instance Listable Day where
  tiers :: [[Day]]
tiers  =  forall a b. (a -> Maybe b) -> [[a]] -> [[b]]
mapMaybeT (\(Year
y,(MonthOfYear
m,MonthOfYear
d)) -> Year -> MonthOfYear -> MonthOfYear -> Maybe Day
fromGregorianValid Year
y MonthOfYear
m MonthOfYear
d) ([[Year]]
yearss forall a b. [[a]] -> [[b]] -> [[(a, b)]]
>< ([[MonthOfYear]]
monthss forall a b. [[a]] -> [[b]] -> [[(a, b)]]
>< [[MonthOfYear]]
dayss))
    where
    thisYear :: Year
thisYear = Year
2019 -- year of release
    yearss :: [[Year]]
yearss   = forall a. [a] -> [[a]]
toTiers forall a b. (a -> b) -> a -> b
$ [Year
thisYear,(Year
thisYearforall a. Num a => a -> a -> a
-Year
1)..] forall a. [a] -> [a] -> [a]
+| [(Year
thisYearforall a. Num a => a -> a -> a
+Year
1)..]
    monthss :: [[MonthOfYear]]
monthss  = forall a. [a] -> [[a]]
toTiers forall a b. (a -> b) -> a -> b
$ [MonthOfYear
1..MonthOfYear
12]
    dayss :: [[MonthOfYear]]
dayss    = forall a. [a] -> [[a]]
toTiers forall a b. (a -> b) -> a -> b
$ [MonthOfYear
1..MonthOfYear
31]

instance Listable DiffTime where
  tiers :: [[DiffTime]]
tiers  =  forall a b. (a -> b) -> [[a]] -> [[b]]
mapT (\(Year
x,Year
y) -> forall a. Num a => Year -> a
fromInteger Year
x forall a. Fractional a => a -> a -> a
/ forall a. Num a => Year -> a
fromInteger Year
y) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [[a]] -> [[a]]
reset
         forall a b. (a -> b) -> a -> b
$  forall a. Listable a => [[a]]
tiers forall a. [[a]] -> (a -> Bool) -> [[a]]
`suchThat` \(Year
n,Year
d) -> Year
n forall a. Ord a => a -> a -> Bool
> Year
0 Bool -> Bool -> Bool
&& Year
d forall a. Ord a => a -> a -> Bool
> Year
0 Bool -> Bool -> Bool
&& Year
n forall a. Integral a => a -> a -> a
`gcd` Year
d forall a. Eq a => a -> a -> Bool
== Year
1


instance Listable UTCTime where
  tiers :: [[UTCTime]]
tiers  =  forall a b c. (Listable a, Listable b) => (a -> b -> c) -> [[c]]
cons2 Day -> DiffTime -> UTCTime
UTCTime