hodatime-1.0.0.0: src/Data/HodaTime/OffsetDateTime.hs
-----------------------------------------------------------------------------
-- |
-- Module : Data.HodaTime.OffsetDateTime
-- Copyright : (C) 2016 Jason Johnson
-- License : BSD-style (see the file LICENSE)
-- Maintainer : Jason Johnson <jason.johnson.081@gmail.com>
-- Stability : experimental
-- Portability : POSIX, Windows
--
-- An 'OffsetDateTime' is a date and time combined with an offset from UTC time. 'OffsetDateTime' is the form that HTTP uses to deal with dates and times.
----------------------------------------------------------------------------
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.HodaTime.OffsetDateTime
(
-- * Types
OffsetDateTime
-- * Constructors
,fromInstantWithOffset
,fromCalendarDateTimeWithOffset
-- * Math
-- * Conversion
,toCalendarDateTime
,offset
)
where
import Data.HodaTime.Offset.Internal
import Data.HodaTime.Instant.Internal (Instant)
import Data.HodaTime.CalendarDateTime.Internal (CalendarDateTime, IsCalendarDateTime(..), Date)
import Data.HodaTime.ZonedDateTime.Internal (ZonedDateTime(..))
import Data.HodaTime.TimeZone.Internal (TimeZone(..), TZIdentifier(..), TransitionInfo, tiUtcOffset, fixedOffsetZone)
import Data.Hashable (Hashable(..))
-- | A 'CalendarDateTime' with a UTC offset. This is the format used by e.g. HTTP. This type has a fixed 'TimeZone' with the name "UTC(+/-)offset". If the offset is
-- empty, the name of the 'TimeZone' will be UTC
newtype OffsetDateTime cal = OffsetDateTime (ZonedDateTime cal)
deriving instance Eq (Date cal) => Eq (OffsetDateTime cal)
deriving instance (IsCalendarDateTime cal, Eq (Date cal)) => Ord (OffsetDateTime cal)
-- | Renders an 'OffsetDateTime' as the 'fromInstantWithOffset' call that reconstructs it.
instance IsCalendarDateTime cal => Show (OffsetDateTime cal) where
showsPrec p (OffsetDateTime (ZonedDateTime cdt _ ti)) = showParen (p > 10) $
showString "fromInstantWithOffset " . showsPrec 11 inst . showChar ' ' . showsPrec 11 off
where
off = tiUtcOffset ti
inst = adjustInstant (negateOffset off) (toUnadjustedInstant cdt)
negateOffset (Offset s) = Offset (negate s)
-- NOTE: no 'NFData' instance is provided because 'OffsetDateTime' embeds a 'TimeZone', whose fingertree-based
-- transition maps cannot be forced (see 'Data.HodaTime.TimeZone.Internal').
instance Hashable (Date cal) => Hashable (OffsetDateTime cal) where
hashWithSalt s (OffsetDateTime z) = hashWithSalt s z
-- | Create an 'OffsetDateTime' from an 'Instant' and an 'Offset'.
fromInstantWithOffset :: IsCalendarDateTime cal => Instant -> Offset -> OffsetDateTime cal
fromInstantWithOffset inst offset' = OffsetDateTime $ ZonedDateTime cdt tz tInfo
where
(tz, tInfo) = makeFixedTimeZone offset'
cdt = fromAdjustedInstant . adjustInstant offset' $ inst
-- | Create an 'OffsetDateTime' from a 'CalendarDateTime' and an 'Offset'.
fromCalendarDateTimeWithOffset :: CalendarDateTime cal -> Offset -> OffsetDateTime cal
fromCalendarDateTimeWithOffset cdt offset' = OffsetDateTime $ ZonedDateTime cdt tz tInfo
where
(tz, tInfo) = makeFixedTimeZone offset'
-- | The local (wall-clock) 'CalendarDateTime' of the 'OffsetDateTime', before the offset is applied.
toCalendarDateTime :: OffsetDateTime cal -> CalendarDateTime cal
toCalendarDateTime (OffsetDateTime zdt) = zdtCalendarDateTime zdt
-- | The UTC 'Offset' of the 'OffsetDateTime'.
offset :: OffsetDateTime cal -> Offset
offset (OffsetDateTime zdt) = tiUtcOffset . zdtActiveTransition $ zdt
-- helper functions
makeFixedTimeZone :: Offset -> (TimeZone, TransitionInfo)
makeFixedTimeZone offset' = (TimeZone (Zone tzName) utcM calDateM, tInfo)
where
tzName = toStringRep offset'
(utcM, calDateM, tInfo) = fixedOffsetZone tzName offset'