-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A pragmatic time and date library.
--
-- This library aims to supply you with common types and operations for
-- working with time and date.
--
--
-- - Parsing and rendering common formats like ISO8601 and
-- RFC3339.
-- - Modifying dates and times in a way that is easy to understand and
-- not overengineered (srsly, who needs something else than the Gregorian
-- Calendar?)
-- - A set of classes that provide interfaces for your own application
-- specific or maybe more efficient time and date types. Implement the
-- interfaces and get all the parsing and rendering functions for
-- free!
--
--
-- Bug reports or (even better) tests are welcome.
@package utc
@version 0.2.0.0
module Data.UTC
-- | This class captures the behaviour of the Proleptic Gregorian
-- Calendar.
--
-- Without any exception the following holds:
--
--
-- - A regular year has 365 days and the corresponding February has 28
-- days.
-- - A leap year has 366 days and the corresponding February has 29
-- days.
-- - A year that is a multiple of 400 is a leap year.
-- - A year that is a multiple of 100 but not of 400 is not a leap
-- year.
-- - A year that is a multiple of 4 but not of 100 is a leap year.
--
class Epoch t => IsDate t where addYears ys t = if isValidDate (year t + ys, month t, day t) then setYear (year t + ys) t else setYear (year t + ys) =<< setDay (day t - 1) t addMonths ms t = setDay 1 t >>= setYear y >>= setMonth m >>= setDay d where ym = (year t * monthsPerYear) + (month t - 1) + ms y = ym `div` monthsPerYear m = (ym `mod` monthsPerYear) + 1 d' = day t d | isValidDate (y, m, d') = d' | isValidDate (y, m, d' - 1) = d' - 1 | isValidDate (y, m, d' - 2) = d' - 2 | otherwise = d' - 3 addDays ds t = setDay 1 t >>= setYear y >>= setMonth m >>= setDay d where ds' = yearMonthDayToDays (year t, month t, day t) (y, m, d) = daysToYearMonthDay (ds' + ds)
-- |
-- year "2014-12-24" == 2014
--
--
-- For negative years the function assumes astronomical year numbering
-- (year 1 ~ 1 AD, year 0 ~ 1 BC, year -1 ~ 2 BC etc). Note that 1 BC and
-- 5 BC are therefore leap years.
year :: IsDate t => t -> Integer
-- |
-- month "2014-12-24" == 12
--
--
-- The function only returns values ranging from 1 to 12.
month :: IsDate t => t -> Integer
-- |
-- day "2014-12-24" == 24
--
--
-- The function only returns values ranging from 1 to 31.
day :: IsDate t => t -> Integer
-- | Sets the year and fails if the result would be invalid.
--
--
-- setYear 2005 "2004-02-28" :: Maybe Date
-- > Just 2005-02-28
-- setYear 2005 "2004-02-29" :: Maybe Date
-- > Nothing
--
setYear :: (IsDate t, MonadThrow m) => Integer -> t -> m t
-- | Sets the month of year and fails if the result would be invalid.
--
-- The function only accepts input ranging from 1 to 12.
setMonth :: (IsDate t, MonadThrow m) => Integer -> t -> m t
-- | Sets the day of month and fails if the result would be invalid.
--
-- The function only accepts input ranging from 1 to 31 (or less
-- depending on month and year).
setDay :: (IsDate t, MonadThrow m) => Integer -> t -> m t
-- | A year is a relative amount of time. The function's semantic is
-- a follows:
--
--
-- - The years (positive or negative) are added.
-- - If the target date is invalid then days are subtracted until the
-- date gets valid.
-- - If the resulting date is out of the instance type's range, the
-- function fails (cannot happen for Date and DateTime as
-- they use multiprecision integers).
--
--
--
-- addYears 4 "2000-02-29" :: Maybe Date
-- > Just 2004-02-29
-- addYears 1 "2000-02-29" :: Maybe Date
-- > Just 2001-02-28
--
addYears :: (IsDate t, MonadThrow m) => Integer -> t -> m t
-- | A month is a relative amount of time. The function's semantic
-- is equivalent to that of addYears.
--
-- The function fails if the resulting date is out of the instance type's
-- range (cannot happen for Date and DateTime as they use
-- multiprecision integers).
--
--
-- addMonths (-13) "1970-01-01" :: Maybe Date
-- > Just 1968-12-01
--
addMonths :: (IsDate t, MonadThrow m) => Integer -> t -> m t
-- | A day is an absolute amount of time. There is no surprise to
-- expect.
--
-- The function fails if the resulting date is out of the instance type's
-- range (cannot happen for Date and DateTime as they use
-- multiprecision integers).
--
--
-- addDays 365 "1970-01-01" :: Maybe Date
-- > Just 1971-01-01
-- addDays 365 "2000-01-01" :: Maybe Date
-- > Just 2000-12-31
--
addDays :: (IsDate t, MonadThrow m) => Integer -> t -> m t
-- | This class captures the concept of a 24-hour clock time during a day.
class IsTime t where addHours h t = setHour hors t where h' = h + (hour t) hors = h' `mod` hoursPerDay addMinutes m t = setMinute mins t >>= addHours hors where m' = m + (minute t) mins = m' `mod` minsPerHour hors = m' `div` minsPerHour addSeconds s t = setSecond secs t >>= addMinutes mins where s' = s + (second t) secs = s' `mod` secsPerMinute mins = s' `div` secsPerMinute 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'
-- | Returns values in the range 0 to 23.
hour :: IsTime t => t -> Integer
-- | Returns values in the range 0 to 59.
minute :: IsTime t => t -> Integer
-- | Returns values in the range 0 to 59.
second :: IsTime t => t -> Integer
-- | Returns values in the range 0.0 <= x < 1.0.
secondFraction :: IsTime t => 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 Time and DateTime).
setHour :: (IsTime t, 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 Time and DateTime).
setMinute :: (IsTime t, 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 Time and DateTime).
setSecond :: (IsTime t, 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 Time and DateTime).
setSecondFraction :: (IsTime t, MonadThrow m) => Rational -> t -> m t
-- | Adds an arbitrary count of hours (positive or negative).
--
--
-- - Full days flow over to addDays if the type is also an
-- instance of IsDate (this is the case for DateTime).
-- - Types not implementing the IsDate class should just ignore
-- the days part on overflow (like Time does).
-- - Fails if the result cannot be represented by the type (cannot
-- happen for Time and DateTime).
--
addHours :: (IsTime t, MonadThrow m) => Integer -> t -> m t
-- | 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 Time and DateTime).
--
addMinutes :: (IsTime t, MonadThrow m) => Integer -> t -> m t
-- | 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 Time and DateTime).
--
addSeconds :: (IsTime t, MonadThrow m) => Integer -> t -> m t
-- | 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 Time and DateTime do so).
-- - Fails if the result cannot be represented by the type (cannot
-- happen for Time and DateTime).
--
addSecondFractions :: (IsTime t, MonadThrow m) => Rational -> t -> m t
-- | This class is for types that have a well-defined mapping to and from
-- the Unix Time system (based on UTC).
--
-- Beware: It is a common misconception that the Unix time in
-- general counts SI seconds since 1970-01-01T00:00:00Z. There is
-- a common definition that may be called Unix time based on UTC:
-- In general, the second boundaries match with UTC, but in the event of
-- a positive (or negative) leap second the Unix second has a duration of
-- 2 (or 0) SI seconds. This library is in accordance with this
-- definition. This definition can also be understood as "ignoring leap
-- seconds" (a Unix day therefore always has 86400 Unix seconds).
--
-- The concrete behaviour of your system clock is implementation
-- dependant.
class IsUnixTime t
unixSeconds :: IsUnixTime t => t -> Rational
fromUnixSeconds :: (IsUnixTime t, MonadThrow m) => Rational -> m t
-- | The instant in time also known as the epoch:
-- 1970-01-01T00:00:00Z
class Epoch t
epoch :: Epoch t => t
-- | This class defines an interface for contexts that can be asked for a
-- timestamp.
--
-- Most users are likely to just need the IO instance, but you
-- might think of other instances:
--
--
-- - A wrapper around the system clock with internal state that ensures
-- strict monotonically increasing values.
-- - A custom monadic computation that needs time, but should not be
-- given IO access.
-- - Testing contexts where you might want to inject and test specific
-- timestamps.
--
class HasUnixTime m
-- | Get a timestamp from the surrounding context. The IO instance
-- gives access to the system clock and is what most users are
-- probably looking for.
--
-- Beware: The IO instance does not guarantee that
-- subsequent calls are monotonically increasing. The system's clock
-- might stop or even go backwards when synchronised manually or via NTP
-- or when adapting to a leap second.
--
-- Example:
--
--
-- import Data.UTC
--
-- printCurrentYear :: IO ()
-- printCurrentYear
-- = do now <- getUnixTime :: IO DateTime
-- print (year now)
--
getUnixTime :: (HasUnixTime m, Monad m, IsUnixTime a) => m a
-- | This type represents dates in the Proleptic Gregorian Calendar.
--
--
-- - It can represent any date in the past and in the future by using
-- Integer internally.
-- - The internal structure is not exposed to avoid the construction of
-- invalid values. Use epoch or a parser to construct values.
-- - The instance of Show is only meant for debugging purposes
-- and is subject to change.
--
--
--
-- > show (epoch :: Date)
-- 1970-01-01
--
data Date
-- | This type represents time instants during a day (00:00:00 -
-- 23:59:59.999..) with arbitrary precision (uses Integer
-- internally).
--
--
-- - The internal structure is not exposed to avoid the creation of
-- invalid values. Use epoch or a parser to construct values.
-- - The instance of Show is only meant for debugging purposes
-- and is subject to change.
--
--
--
-- > show (epoch :: Time)
-- 00:00:00
--
data Time
-- | A time representation based on a Date and the Time of
-- the day.
--
--
-- - The type uses multiprecision integers internally and is able to
-- represent any UTC date in the past and in the future with arbitrary
-- precision (apart from the time span within a leap second).
-- - The instance of Show is only meant for debugging purposes.
-- Don't rely on its behaviour!
--
--
--
-- > show (epoch :: DateTime)
-- 1970-01-01T00:00:00
--
data DateTime
DateTime :: Date -> Time -> DateTime
[date] :: DateTime -> Date
[time] :: DateTime -> Time
-- | This type is used to extend UTC time types by a local offset in
-- seconds (positive or negative).
--
-- Beware: A local offset is not a time zone. It is just a fix
-- period of time. In contrast to a time zone this does not take summer
-- or winter time into account.
data Local time
Local :: Maybe Rational -> time -> Local time
-- |
-- - Nothing The local offset is unknown (behaves like
-- Western European Time)
-- - Just 0 UTC+00:00 (Western European
-- Time)
-- - Just 3600 UTC+01:00 (Central European
-- Time)
--
[offset] :: Local time -> Maybe Rational
-- | The time to be interpreted as UTC+00:00 (Western
-- European Time)
[utc] :: Local time -> time
-- | All non-total functions within this library throw a
-- UtcException exception within a MonadThrow context. Use
-- MonadCatch to specifically catch this exception.
--
-- The String contains information that might be useful for
-- debugging, but its specific form is undefined and must not be relied
-- on.
data UtcException
UtcException :: String -> UtcException
class Rfc3339Parser a
parseRfc3339 :: (Rfc3339Parser a, MonadThrow m, IsDate t, IsTime t, Epoch t) => a -> m (Local t)
-- |
-- setYear 1987 (epoch :: DateTime)
-- >>= setMonth 7
-- >>= setDay 10
-- >>= setHour 12
-- >>= setMinute 4
-- >>= return . (flip Local) (Just 0)
-- >>= renderRfc3339 :: Maybe String
-- > Just "1987-07-10T12:04:00Z"
--
class Rfc3339Renderer string
renderRfc3339 :: (Rfc3339Renderer string, MonadThrow m, IsDate t, IsTime t, Epoch t) => Local t -> m string
class Iso8601Renderer string
-- | YYYYMMDD
renderIso8601CalendarDate :: (Iso8601Renderer string, MonadThrow m, IsDate t) => t -> m string
-- | YYYY-MM-DD (extended format)
renderIso8601CalendarDate' :: (Iso8601Renderer string, MonadThrow m, IsDate t) => t -> m string
-- | hhmmss
renderIso8601TimeHms :: (Iso8601Renderer string, MonadThrow m, IsTime t) => t -> m string
-- | hh:mm:ss (extended format)
renderIso8601TimeHms' :: (Iso8601Renderer string, MonadThrow m, IsTime t) => t -> m string
-- | hhmm
renderIso8601TimeHm :: (Iso8601Renderer string, MonadThrow m, IsTime t) => t -> m string
-- | hh:mm (extended format)
renderIso8601TimeHm' :: (Iso8601Renderer string, MonadThrow m, IsTime t) => t -> m string