{-# 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
Typeable ZonedTime =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> ZonedTime -> c ZonedTime)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c ZonedTime)
-> (ZonedTime -> Constr)
-> (ZonedTime -> DataType)
-> (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))
-> ((forall b. Data b => b -> b) -> ZonedTime -> ZonedTime)
-> (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 u. (forall d. Data d => d -> u) -> ZonedTime -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> ZonedTime -> u)
-> (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 (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime)
-> Data ZonedTime
ZonedTime -> Constr
ZonedTime -> DataType
(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)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ZonedTime -> c ZonedTime
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ZonedTime -> c ZonedTime
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ZonedTime
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ZonedTime
$ctoConstr :: ZonedTime -> Constr
toConstr :: ZonedTime -> Constr
$cdataTypeOf :: ZonedTime -> DataType
dataTypeOf :: ZonedTime -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ZonedTime)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ZonedTime)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime)
$cgmapT :: (forall b. Data b => b -> b) -> ZonedTime -> ZonedTime
gmapT :: (forall b. Data b => b -> b) -> ZonedTime -> ZonedTime
$cgmapQl :: 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
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ZonedTime -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ZonedTime -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> ZonedTime -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ZonedTime -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ZonedTime -> u
$cgmapM :: forall (m :: * -> *).
Monad 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
$cgmapMp :: 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
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime
Data, Typeable)

instance NFData ZonedTime where
    rnf :: ZonedTime -> ()
rnf (ZonedTime LocalTime
lt TimeZone
z) = LocalTime -> ()
forall a. NFData a => a -> ()
rnf LocalTime
lt () -> () -> ()
forall a b. a -> b -> b
`seq` TimeZone -> ()
forall a. NFData a => a -> ()
rnf TimeZone
z () -> () -> ()
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

-- | For the time zone, this only shows the name, or offset if the name is empty.
instance Show ZonedTime where
    show :: ZonedTime -> String
show (ZonedTime LocalTime
t TimeZone
zone) = LocalTime -> String
forall a. Show a => a -> String
show LocalTime
t String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ TimeZone -> String
forall a. Show a => a -> String
show TimeZone
zone

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

getZonedTime :: IO ZonedTime
getZonedTime :: IO ZonedTime
getZonedTime = do
    t <- IO UTCTime
getCurrentTime
    zone <- getTimeZone t
    return (utcToZonedTime zone t)

utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime UTCTime
t = do
    zone <- UTCTime -> IO TimeZone
getTimeZone UTCTime
t
    return (utcToZonedTime zone t)