Monadoro-0.4.0.0: src/ParseTime.lhs
#!/usr/bin/env stack
> --stack --install-ghc runghc
> module ParseTime (
> count_down_time,
> subtract_second,
> asTimePeriod
> )
> where
>
> data TimePeriod = TimePeriod Integer Integer deriving (Read)
>
> split :: (Char -> Bool) -> String -> [String]
> split p s = case dropWhile p s of
> "" -> []
> s' -> w : split p s''
> where (w, s'') = break p s'
> -- | Given a string denoting a time interval, function "split" returns the
> -- corresponding time in ["MM","SS"].
> --
> -- >>> split (==':') "10:20"
> -- ["10","20"]
> split_by_colon :: String -> [String]
> split_by_colon timeString = split (==':') timeString
>
> {-| split_by_colon: Returns time in `["MM","SS"]`, corresponding to the time
> interval given in a string.
>
> >>> split_by_colon "10:20"
> ["10","20"]
> -}
>
> many_to_int :: [String] -> [Integer]
> many_to_int [] = []
> many_to_int (x:xs) = (read $ x :: Integer):(many_to_int xs)
>
> {-| many_to_int
>
> >>> many_to_int ["10","20"]
> [10,20]
> -}
>
> list_to_time_periods :: [Integer] -> [TimePeriod]
> list_to_time_periods [m,s] = [TimePeriod m s]
> list_to_time_periods _ = []
>
> {-| list_to_time_periods
>
> >>> list_to_time_periods [10,20]
> [10:20]
> -}
>
> subtract_second :: TimePeriod -> TimePeriod
> subtract_second (TimePeriod 0 0) = TimePeriod 0 0
> subtract_second (TimePeriod 0 s) = TimePeriod 0 (s-1)
> subtract_second (TimePeriod m 0) = TimePeriod (m-1) 59
> subtract_second (TimePeriod m s) = TimePeriod m (s-1)
>
> {-| subtract_second: Given a TimePeriod, returns a TimePeriod that is one
> second shorter.
>
> >>> subtract_second $ TimePeriod 00 00
> 00:00
>
> >>> subtract_second $ TimePeriod 00 01
> 00:00
>
> >>> subtract_second $ TimePeriod 01 00
> 00:59
>
> >>> subtract_second $ TimePeriod 02 00
> 01:59
> -}
>
> asTimePeriod :: String -> TimePeriod
> asTimePeriod s = head $ list_to_time_periods $ many_to_int $ split_by_colon s
>
> {-| asTimePeriod: Reads a string as a TimePeriod.
>
> >>> asTimePeriod "00:00"
> 00:00
>
> >>> asTimePeriod "99:99"
> 99:99
> -}
>
> {-| count_down_time: Subtracts a second from time given as a string.
>
> >>> count_down_time "00:00"
> "00:00"
>
> >>> count_down_time "00:01"
> "00:00"
>
> >>> count_down_time "00:02"
> "00:01"
>
> >>> count_down_time "01:00"
> "00:59"
>
> What happens when an invalid period is given?
>
> >>> count_down_time "foo"
> "*** Exception: Prelude.head: empty list
>
> Turns out Vim highlighting doesn't handle this lack
> of double quotes well, but tests complete OK.
> -}
>
> count_down_time :: String -> String
> count_down_time = show . subtract_second . asTimePeriod
>
> {-| show_two_digits
>
> >>> show_two_digits 0
> "00"
> -}
>
> show_two_digits :: Integer -> String
> show_two_digits x
> | x < 10 = "0" ++ show x
> | otherwise = show x
>
> {-| show TimePeriod
>
> >>> show (TimePeriod 0 0)
> "00:00"
>
> >>> a = TimePeriod 0 0
> >>> show a
> "00:00"
> -}
>
> instance Show TimePeriod where
> show (TimePeriod m s) = show_two_digits m ++ ":" ++ show_two_digits s
Related materials:
1. Generic time processing example: https://stackoverflow.com/a/14006938