#!/usr/bin/env stack
> --stack --install-ghc runghc

> module ParseTime (
>   count_down_time,
>   subtract_second,
>   asTimePeriod
> )
> where
>
> data TimePeriod = TimePeriod Integer Integer deriving (ReadPrec [TimePeriod]
ReadPrec TimePeriod
Int -> ReadS TimePeriod
ReadS [TimePeriod]
(Int -> ReadS TimePeriod)
-> ReadS [TimePeriod]
-> ReadPrec TimePeriod
-> ReadPrec [TimePeriod]
-> Read TimePeriod
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TimePeriod]
$creadListPrec :: ReadPrec [TimePeriod]
readPrec :: ReadPrec TimePeriod
$creadPrec :: ReadPrec TimePeriod
readList :: ReadS [TimePeriod]
$creadList :: ReadS [TimePeriod]
readsPrec :: Int -> ReadS TimePeriod
$creadsPrec :: Int -> ReadS TimePeriod
Read)
> 
> split :: (Char -> Bool) -> String -> [String]
> split :: (Char -> Bool) -> String -> [String]
split Char -> Bool
p String
s =  case (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
p String
s of
>     String
"" -> []
>     String
s' -> String
w String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (Char -> Bool) -> String -> [String]
split Char -> Bool
p String
s''
>         where (String
w, String
s'') = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
p String
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 :: String -> [String]
split_by_colon String
timeString = (Char -> Bool) -> String -> [String]
split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
':') String
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 :: [String] -> [Integer]
many_to_int [] = []
> many_to_int (String
x:[String]
xs) = (String -> Integer
forall a. Read a => String -> a
read (String -> Integer) -> String -> Integer
forall a b. (a -> b) -> a -> b
$ String
x :: Integer)Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
:([String] -> [Integer]
many_to_int [String]
xs)
> 
> {-| many_to_int
> 
> >>> many_to_int ["10","20"]
> [10,20]
> -}
> 
> list_to_time_periods :: [Integer] -> [TimePeriod]
> list_to_time_periods :: [Integer] -> [TimePeriod]
list_to_time_periods [Integer
m,Integer
s] = [Integer -> Integer -> TimePeriod
TimePeriod Integer
m Integer
s]
> list_to_time_periods [Integer]
_ = []
> 
> {-| list_to_time_periods
> 
> >>> list_to_time_periods [10,20]
> [10:20]
> -}
> 
> subtract_second :: TimePeriod -> TimePeriod
> subtract_second :: TimePeriod -> TimePeriod
subtract_second (TimePeriod Integer
0 Integer
0) = Integer -> Integer -> TimePeriod
TimePeriod Integer
0 Integer
0
> subtract_second (TimePeriod Integer
0 Integer
s) = Integer -> Integer -> TimePeriod
TimePeriod Integer
0 (Integer
sInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1)
> subtract_second (TimePeriod Integer
m Integer
0) = Integer -> Integer -> TimePeriod
TimePeriod (Integer
mInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1) Integer
59
> subtract_second (TimePeriod Integer
m Integer
s) = Integer -> Integer -> TimePeriod
TimePeriod Integer
m (Integer
sInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
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 :: String -> TimePeriod
asTimePeriod String
s = [TimePeriod] -> TimePeriod
forall a. [a] -> a
head ([TimePeriod] -> TimePeriod) -> [TimePeriod] -> TimePeriod
forall a b. (a -> b) -> a -> b
$ [Integer] -> [TimePeriod]
list_to_time_periods ([Integer] -> [TimePeriod]) -> [Integer] -> [TimePeriod]
forall a b. (a -> b) -> a -> b
$ [String] -> [Integer]
many_to_int ([String] -> [Integer]) -> [String] -> [Integer]
forall a b. (a -> b) -> a -> b
$ String -> [String]
split_by_colon String
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"
> -}
> 
> count_down_time :: String -> String
> count_down_time :: String -> String
count_down_time = TimePeriod -> String
forall a. Show a => a -> String
show (TimePeriod -> String)
-> (String -> TimePeriod) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimePeriod -> TimePeriod
subtract_second (TimePeriod -> TimePeriod)
-> (String -> TimePeriod) -> String -> TimePeriod
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> TimePeriod
asTimePeriod
>
> {-| show_two_digits
>
> >>> show_two_digits 0
> "00"
> -}
>
> show_two_digits :: Integer -> String
> show_two_digits :: Integer -> String
show_two_digits Integer
x
>   | Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
10 = String
"0" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
x
>   | Bool
otherwise = Integer -> String
forall a. Show a => a -> String
show Integer
x
>
> {-| show TimePeriod
>
> >>> show (TimePeriod 0 0)
> "00:00"
>
> >>> a = TimePeriod 0 0
> >>> show a
> "00:00"
> -}
>
> instance Show TimePeriod where
>   show :: TimePeriod -> String
show (TimePeriod Integer
m Integer
s) = Integer -> String
show_two_digits Integer
m String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
show_two_digits Integer
s

Related materials:

1. Generic time processing example: https://stackoverflow.com/a/14006938