aboutsummaryrefslogtreecommitdiff
path: root/src/Cron/Schedule.hs
diff options
context:
space:
mode:
authorevuez <julien@mulga.net>2024-04-01 15:16:52 +0200
committerevuez <julien@mulga.net>2024-04-03 22:45:16 +0200
commitff174d9536db26945189593bf8194f18fbd5ce3f (patch)
tree327cf783e3c24a0b4b035f548b0ea7206ea9b0f9 /src/Cron/Schedule.hs
downloaduncron-ff174d9536db26945189593bf8194f18fbd5ce3f.tar.gz
Initial commit
Diffstat (limited to 'src/Cron/Schedule.hs')
-rw-r--r--src/Cron/Schedule.hs72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/Cron/Schedule.hs b/src/Cron/Schedule.hs
new file mode 100644
index 0000000..2ea56ab
--- /dev/null
+++ b/src/Cron/Schedule.hs
@@ -0,0 +1,72 @@
+module Cron.Schedule (Schedule (..), fromParts) where
+
+import Common ((?))
+import qualified Cron.Expr as E
+import qualified Cron.Parser as P
+import Intro
+
+data Schedule = Schedule
+ { minute :: E.Expr
+ , hour :: E.Expr
+ , dayOfMonth :: E.Expr
+ , month :: E.Expr
+ , dayOfWeek :: E.Expr
+ }
+ deriving (Show)
+
+fromParts :: String -> String -> String -> String -> String -> Either String Schedule
+fromParts mn h d m wd =
+ Schedule
+ <$> parseMinute mn
+ <*> parseHour h
+ <*> parseDayOfMonth d
+ <*> parseMonth m
+ <*> parseDayOfWeek wd
+
+parseMinute :: String -> Either String E.Expr
+parseMinute s = P.parse s >>= validateMinute
+
+parseHour :: String -> Either String E.Expr
+parseHour s = P.parse s >>= validateHour
+
+parseDayOfMonth :: String -> Either String E.Expr
+parseDayOfMonth s = P.parse s >>= validateDayOfMonth
+
+parseMonth :: String -> Either String E.Expr
+parseMonth s = P.parse s >>= validateMonth
+
+parseDayOfWeek :: String -> Either String E.Expr
+parseDayOfWeek s = P.parse s >>= validateDayOfWeek
+
+validateMinute :: E.Expr -> Either String E.Expr
+validateMinute expr = validateExpr expr >>= flip validateInRange [0 .. 59]
+
+validateHour :: E.Expr -> Either String E.Expr
+validateHour expr = validateExpr expr >>= flip validateInRange [0 .. 23]
+
+validateDayOfMonth :: E.Expr -> Either String E.Expr
+validateDayOfMonth expr = validateExpr expr >>= flip validateInRange [1 .. 31]
+
+validateMonth :: E.Expr -> Either String E.Expr
+validateMonth expr = validateExpr expr >>= flip validateInRange [1 .. 12]
+
+validateDayOfWeek :: E.Expr -> Either String E.Expr
+validateDayOfWeek expr = validateExpr expr >>= flip validateInRange [0 .. 6]
+
+validateExpr :: E.Expr -> Either String E.Expr
+validateExpr expr = validate expr $ \case
+ E.Range n m -> n < m
+ _ -> True
+
+validateInRange :: E.Expr -> [Int] -> Either String E.Expr
+validateInRange expr range = validate expr $ \case
+ E.Multi ns -> all inRange ns
+ E.Range n m -> inRange n && inRange m
+ E.Step _ _ -> True
+ E.Every -> True
+ where
+ inRange :: Int -> Bool
+ inRange = flip elem range
+
+validate :: E.Expr -> (E.Expr -> Bool) -> Either String E.Expr
+validate expr p = p expr ? Right expr $ Left ("Invalid cron expression " ++ E.showExpr expr)