batchd-0.1.1.0: src/Batchd/Common/Schedule.hs
{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving, RecordWildCards, DeriveGeneric #-}
-- | This module contains definitions for working with schedules
module Batchd.Common.Schedule where
import GHC.Generics
import Data.Time.Clock
import Data.Time.LocalTime
import Data.Dates
import Data.Dates.Formats
import Data.Aeson
import Text.Parsec
import Text.Parsec.String
import Batchd.Common.Types (jsonOptions)
import Batchd.Common.Data
-- | Time period within day.
data Period =
Period {
periodBegin :: TimeOfDay,
periodEnd :: TimeOfDay
}
deriving (Eq, Generic)
instance Show Period where
show (Period begin end) = show begin ++ " -- " ++ show end
toPeriod :: ScheduleTime -> Period
toPeriod (ScheduleTime {..}) = Period scheduleTimeBegin scheduleTimeEnd
instance ToJSON Period where
toJSON = genericToJSON (jsonOptions "period")
instance FromJSON Period where
parseJSON = genericParseJSON (jsonOptions "period")
data ScheduleInfo =
ScheduleInfo {
sName :: String
, sWeekdays :: Maybe [WeekDay]
, sTime :: Maybe [Period]
}
deriving (Eq, Show, Generic)
instance ToJSON ScheduleInfo where
toJSON = genericToJSON (jsonOptions "s")
instance FromJSON ScheduleInfo where
parseJSON = genericParseJSON (jsonOptions "s")
anytime :: ScheduleInfo
anytime = ScheduleInfo "anytime" Nothing Nothing
getTime :: DateTime -> TimeOfDay
getTime (DateTime {..}) = TimeOfDay hour minute (fromIntegral second)
parsePeriod :: String -> Either ParseError Period
parsePeriod str = parse parser "(period description)" str
where
format :: Format
format = [HOUR True 2,Fixed True ":",MINUTE True 2,Fixed True ":",SECOND True 2]
parser :: Parser Period
parser = do
begin <- formatParser format
spaces
end <- formatParser format
return $ Period (getTime begin) (getTime end)
allows :: ScheduleInfo -> DateTime -> Bool
allows (ScheduleInfo {..}) dt = weekdayOk && timeOk
where
weekdayOk = case sWeekdays of
Nothing -> True
Just weekdays -> dateWeekDay dt `elem` weekdays
timeOk = case sTime of
Nothing -> True
Just lst -> any goodTime lst
goodTime (Period {..}) =
getTime dt > periodBegin && getTime dt <= periodEnd
allowsU :: ScheduleInfo -> UTCTime -> Bool
allowsU (ScheduleInfo {..}) dt = weekdayOk && timeOk
where
date = dayToDateTime (utctDay dt)
time = timeToTimeOfDay (utctDayTime dt)
weekdayOk = case sWeekdays of
Nothing -> True
Just weekdays -> dateWeekDay date `elem` weekdays
timeOk = case sTime of
Nothing -> True
Just lst -> any goodTime lst
goodTime (Period {..}) =
time > periodBegin && time <= periodEnd