utc-0.2.0.0: Data/UTC/Class/IsTime.hs
{-# LANGUAGE Safe #-}
module Data.UTC.Class.IsTime
( IsTime (..)
) where
import Control.Monad.Catch
import Data.Ratio
import Data.UTC.Internal
-- | This class captures the concept of a 24-hour clock time
-- during a day.
class IsTime t where
-- | Returns values in the range 0 to 23.
hour :: t -> Integer
-- | Returns values in the range 0 to 59.
minute :: t -> Integer
-- | Returns values in the range 0 to 59.
second :: t -> Integer
-- | Returns values in the range 0.0 <= x < 1.0.
secondFraction :: t -> Rational
-- | Accepts values in the range 0 to 23.
--
-- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
setHour :: (MonadThrow m) => Integer -> t -> m t
-- | Accepts values in the range 0 to 59.
--
-- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
setMinute :: (MonadThrow m) => Integer -> t -> m t
-- | Accepts values in the range 0 to 59.
--
-- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
setSecond :: (MonadThrow m) => Integer -> t -> m t
-- | Accepts values in the range 0.0 <= x < 1.0.
--
-- The function fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
setSecondFraction :: (MonadThrow m) => Rational -> t -> m t
-- | Adds an arbitrary count of hours (positive or negative).
--
-- * Full days flow over to 'Data.UTC.addDays' if the type is also an instance of 'Data.UTC.Class.IsDate' (this is the case for 'Data.UTC.DateTime').
-- * Types not implementing the 'Data.UTC.Class.IsDate' class should just ignore the days part on overflow (like 'Data.UTC.Time' does).
-- * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
addHours :: (MonadThrow m) => Integer -> t -> m t
addHours h t
= setHour hors t
where
h' = h + (hour t)
hors = h' `mod` hoursPerDay
-- | Adds an arbitrary count of minutes (positive or negative).
--
-- * Full hours flow over to 'addHours'.
-- * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
addMinutes :: (MonadThrow m) => Integer -> t -> m t
addMinutes m t
= setMinute mins t >>= addHours hors
where
m' = m + (minute t)
mins = m' `mod` minsPerHour
hors = m' `div` minsPerHour
-- | Adds an arbitrary count of seconds (positive or negative).
--
-- * Full minutes flow over to 'addMinutes'.
-- * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
addSeconds :: (MonadThrow m) => Integer -> t -> m t
addSeconds s t
= setSecond secs t >>= addMinutes mins
where
s' = s + (second t)
secs = s' `mod` secsPerMinute
mins = s' `div` secsPerMinute
-- | Adds an arbitrary second fraction (positive or negative).
--
-- * Full seconds flow over to 'addSeconds'.
-- * Instances of this class are not required to preserve full precision (although 'Data.UTC.Time' and 'Data.UTC.DateTime' do so).
-- * Fails if the result cannot be represented by the type (cannot happen for 'Data.UTC.Time' and 'Data.UTC.DateTime').
addSecondFractions :: (MonadThrow m) => Rational -> t -> m t
addSecondFractions f t
| f == 0 = return t
| f >= 0 = setSecondFraction frcs t >>= addSeconds secs
| otherwise = setSecondFraction (frcs + 1.0) t >>= addSeconds (secs - 1)
where
f' = f + (secondFraction t)
frcs = f' - (truncate f' % 1)
secs = truncate f'