fuzzy-time-0.2.0.0: src/Data/FuzzyTime/Types.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.FuzzyTime.Types
( module Data.FuzzyTime.Types,
DayOfWeek (..),
)
where
import Control.DeepSeq
import Data.Fixed
import Data.Int
import Data.Time
import Data.Validity
import Data.Validity.Time ()
import GHC.Generics (Generic)
data FuzzyZonedTime
= ZonedNow
deriving (Show, Eq, Generic)
instance Validity FuzzyZonedTime
instance NFData FuzzyZonedTime
data AmbiguousLocalTime
= OnlyDaySpecified Day
| BothTimeAndDay LocalTime
deriving (Show, Eq, Generic)
instance Validity AmbiguousLocalTime
instance NFData AmbiguousLocalTime
newtype FuzzyLocalTime = FuzzyLocalTime
{ unFuzzyLocalTime :: Some FuzzyDay FuzzyTimeOfDay
}
deriving (Show, Eq, Generic)
instance Validity FuzzyLocalTime
instance NFData FuzzyLocalTime
data Some a b
= One a
| Other b
| Both a b
deriving (Show, Eq, Generic)
instance (Validity a, Validity b) => Validity (Some a b)
instance (NFData a, NFData b) => NFData (Some a b)
data FuzzyTimeOfDay
= SameTime
| Noon
| Midnight
| Morning
| Evening
| AtHour Int
| AtMinute Int Int
| AtExact TimeOfDay
| HoursDiff Int -- Max 24
| MinutesDiff Int -- Max 24 * 60
| SecondsDiff Pico -- Max 24 * 60 * 60
deriving (Show, Eq, Generic)
instance Validity FuzzyTimeOfDay where
validate ftod =
mconcat
[ genericValidate ftod,
case ftod of
AtHour h ->
mconcat
[ declare "The hour is positive" $ h >= 0,
declare "The hours are fewer than 24" $ h < 24
]
AtMinute h m ->
mconcat
[ declare "The hour is positive" $ h >= 0,
declare "The hours are fewer than 24" $ h < 24,
declare "The minute is positive" $ m >= 0,
declare "The minutes are fewer than 60" $ m < 60
]
HoursDiff hs ->
mconcat
[declare "The hours difference is no less than 24h" $ abs hs < 24]
MinutesDiff ms ->
mconcat
[ declare "The minutes difference is no less than 1440m" $
abs ms < 24 * 60
]
SecondsDiff ms ->
mconcat
[ declare "The seconds difference is no less than 86400s" $
abs ms < 24 * 60 * 60
]
_ -> valid
]
instance NFData FuzzyTimeOfDay
data FuzzyDay
= Yesterday
| Now
| Today
| Tomorrow
| OnlyDay Int
| DayInMonth Int Int
| DiffDays Int16
| DiffWeeks Int16
| DiffMonths Int16
| NextDayOfTheWeek DayOfWeek
| ExactDay Day
deriving (Show, Eq, Generic)
instance Validity FuzzyDay where
validate fd =
mconcat
[ genericValidate fd,
case fd of
OnlyDay di ->
decorate "OnlyDay" $
mconcat
[ declare "The day is strictly positive" $ di >= 1,
declare "The day is less than or equal to 31" $ di <= 31
]
DayInMonth mi di ->
decorate "DayInMonth" $
mconcat
[ declare "The day is strictly positive" $ di >= 1,
declare "The day is less than or equal to 31" $ di <= 31,
declare "The month is strictly positive" $ mi >= 1,
declare "The month is less than or equal to 12" $ mi <= 12,
declare "The number of days makes sense for the month" $
maybe False (>= di) $ lookup (numMonth mi) (daysInMonth 2004)
]
_ -> valid
]
instance NFData FuzzyDay
deriving instance Generic DayOfWeek
instance NFData DayOfWeek
dayOfTheWeekNum :: DayOfWeek -> Int
dayOfTheWeekNum = fromEnum
numDayOfTheWeek :: Int -> DayOfWeek
numDayOfTheWeek = toEnum
data Month
= January
| February
| March
| April
| May
| June
| July
| August
| September
| October
| November
| December
deriving (Show, Eq, Generic, Enum, Bounded)
instance Validity Month
instance NFData Month
daysInMonth :: Integer -> [(Month, Int)]
daysInMonth y =
[ (January, 31),
( February,
if isLeapYear y
then 29
else 28
),
(March, 31),
(April, 30),
(May, 31),
(June, 30),
(July, 31),
(August, 31),
(September, 30),
(October, 31),
(November, 30),
(December, 31)
]
monthNum :: Month -> Int
monthNum = (+ 1) . fromEnum
numMonth :: Int -> Month
numMonth = toEnum . (\x -> x - 1)