{-# LANGUAGE Safe #-}
{-# OPTIONS -fno-warn-orphans #-}

module Data.Time.LocalTime.Internal.ZonedTime
    ( ZonedTime(..)
    , utcToZonedTime
    , zonedTimeToUTC
    , getZonedTime
    , utcToLocalZonedTime
    ) where

import Control.DeepSeq
import Data.Data
import Data.Time.Clock.Internal.UTCTime
import Data.Time.Clock.POSIX
import Data.Time.LocalTime.Internal.LocalTime
import Data.Time.LocalTime.Internal.TimeZone

-- | A local time together with a time zone.
--
-- There is no 'Eq' instance for @ZonedTime@.
-- If you want to compare local times, use 'zonedTimeToLocalTime'.
-- If you want to compare absolute times, use 'zonedTimeToUTC'.
data ZonedTime = ZonedTime
    { ZonedTime -> LocalTime
zonedTimeToLocalTime :: LocalTime
    , ZonedTime -> TimeZone
zonedTimeZone :: TimeZone
    } deriving (Typeable ZonedTime
ZonedTime -> DataType
ZonedTime -> Constr
(forall b. Data b => b -> b) -> ZonedTime -> ZonedTime
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> ZonedTime -> u
forall u. (forall d. Data d => d -> u) -> ZonedTime -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ZonedTime
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ZonedTime -> c ZonedTime
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ZonedTime)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ZonedTime -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ZonedTime -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> ZonedTime -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ZonedTime -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
gmapT :: (forall b. Data b => b -> b) -> ZonedTime -> ZonedTime
$cgmapT :: (forall b. Data b => b -> b) -> ZonedTime -> ZonedTime
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ZonedTime)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ZonedTime)
dataTypeOf :: ZonedTime -> DataType
$cdataTypeOf :: ZonedTime -> DataType
toConstr :: ZonedTime -> Constr
$ctoConstr :: ZonedTime -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ZonedTime
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ZonedTime
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ZonedTime -> c ZonedTime
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ZonedTime -> c ZonedTime
Data, Typeable)

instance NFData ZonedTime where
    rnf :: ZonedTime -> ()
rnf (ZonedTime LocalTime
lt TimeZone
z) = forall a. NFData a => a -> ()
rnf LocalTime
lt seq :: forall a b. a -> b -> b
`seq` forall a. NFData a => a -> ()
rnf TimeZone
z seq :: forall a b. a -> b -> b
`seq` ()

utcToZonedTime :: TimeZone -> UTCTime -> ZonedTime
utcToZonedTime :: TimeZone -> UTCTime -> ZonedTime
utcToZonedTime TimeZone
zone UTCTime
time = LocalTime -> TimeZone -> ZonedTime
ZonedTime (TimeZone -> UTCTime -> LocalTime
utcToLocalTime TimeZone
zone UTCTime
time) TimeZone
zone

zonedTimeToUTC :: ZonedTime -> UTCTime
zonedTimeToUTC :: ZonedTime -> UTCTime
zonedTimeToUTC (ZonedTime LocalTime
t TimeZone
zone) = TimeZone -> LocalTime -> UTCTime
localTimeToUTC TimeZone
zone LocalTime
t

instance Show ZonedTime where
    show :: ZonedTime -> String
show (ZonedTime LocalTime
t TimeZone
zone) = forall a. Show a => a -> String
show LocalTime
t forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show TimeZone
zone

-- orphan instance
instance Show UTCTime where
    show :: UTCTime -> String
show UTCTime
t = forall a. Show a => a -> String
show (TimeZone -> UTCTime -> ZonedTime
utcToZonedTime TimeZone
utc UTCTime
t)

getZonedTime :: IO ZonedTime
getZonedTime :: IO ZonedTime
getZonedTime = do
    UTCTime
t <- IO UTCTime
getCurrentTime
    TimeZone
zone <- UTCTime -> IO TimeZone
getTimeZone UTCTime
t
    forall (m :: * -> *) a. Monad m => a -> m a
return (TimeZone -> UTCTime -> ZonedTime
utcToZonedTime TimeZone
zone UTCTime
t)

-- |
utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime UTCTime
t = do
    TimeZone
zone <- UTCTime -> IO TimeZone
getTimeZone UTCTime
t
    forall (m :: * -> *) a. Monad m => a -> m a
return (TimeZone -> UTCTime -> ZonedTime
utcToZonedTime TimeZone
zone UTCTime
t)