packages feed

scheduling-0.1.0.0: src/Control/Scheduling/TimeSpan.hs

module Control.Scheduling.TimeSpan (expand, TimeSpan(..), start, end, stringsToSlots, timesFromStrings) where

import Data.Time
import Control.Lens ((^.), (.~), (<&>), set, view, makeLenses, makeFields)
import Data.List (unfoldr)

data TimeSpan = TimeSpan { _start :: UTCTime
                         , _end :: UTCTime
                         } deriving (Show, Eq, Ord)

makeLenses ''TimeSpan

stringsToSlots :: String -> String -> String -> String -> Integer -> Maybe [TimeSpan]
stringsToSlots sd ed st et sl = Just slots
  where
    days = daysFromStrings sd ed
    (st', et') = timesFromStrings st et
    ranges = [TimeSpan (UTCTime d st') (UTCTime d et') | d <- days]
    increment' = secondsToDiffTime $ 60 * sl :: DiffTime
    slots = concat $ map (expand increment') ranges

expand :: DiffTime -> TimeSpan -> [TimeSpan]
expand slotLength block = if s' > e then [n] else n:(expand slotLength block')
  where
    s = block ^. start
    e = block ^. end
    s' = s { utctDayTime=utctDayTime s + slotLength }
    n = TimeSpan s s'
    block' = TimeSpan s' e
  
daysFromStrings :: String -> String -> [Day]
daysFromStrings s e = ds
  where
    s' = parseTimeOrError True defaultTimeLocale "%Y-%-m-%-d" s :: Day
    e' = parseTimeOrError True defaultTimeLocale "%Y-%-m-%-d" e :: Day
    ds = unfoldr (\d -> if d > e' then Nothing else Just (d, (addDays 1 d))) s'

timesFromStrings :: String -> String -> (DiffTime, DiffTime)
timesFromStrings s e = (timeOfDayToTime s', timeOfDayToTime e')
  where
    s' = parseTimeOrError True defaultTimeLocale "%R" s :: TimeOfDay
    e' = parseTimeOrError True defaultTimeLocale "%R" e :: TimeOfDay