23 lines
922 B
Haskell
23 lines
922 B
Haskell
module Yore.Schedule (schedule) where
|
|
|
|
import Control.Concurrent (forkIO, threadDelay)
|
|
import Control.Monad (when)
|
|
import Data.Functor (($>))
|
|
import Data.Time (ZonedTime, getZonedTime, nominalDiffTimeToSeconds, secondsToNominalDiffTime)
|
|
import Data.Time.Clock.POSIX (getPOSIXTime)
|
|
|
|
schedule :: (ZonedTime -> Bool) -> IO a -> IO ()
|
|
schedule shouldRunAt f = everyMinute $ \now -> when (shouldRunAt now) (f $> ())
|
|
|
|
everyMinute :: (ZonedTime -> IO ()) -> IO ()
|
|
everyMinute f = do
|
|
-- Use POSIX time to avoid having to handle leap seconds
|
|
now <- getPOSIXTime
|
|
let posixSeconds :: Int
|
|
posixSeconds = floor $ nominalDiffTimeToSeconds now
|
|
lastFullMinute = secondsToNominalDiffTime $ fromIntegral $ posixSeconds - posixSeconds `mod` 60
|
|
secondsSinceLastFullMinute = now - lastFullMinute
|
|
threadDelay $ ceiling $ (60 - secondsSinceLastFullMinute) * 1_000_000
|
|
_ <- forkIO $ f =<< getZonedTime
|
|
everyMinute f
|