module Data.Time.TZInfo
( TZInfo(..)
, TZIdentifier
, utc
, loadFromSystem
, loadFromFile
, getCurrentTZInfo
, fromIdentifier
, fromLabel
, TZ.TZLabel(..)
) where
import Control.DeepSeq (NFData)
import Data.Data (Data)
import Data.String (fromString)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Encoding qualified as T
import Data.Time.Zones (TZ)
import Data.Time.Zones qualified as TZ
import Data.Time.Zones.All (TZLabel)
import Data.Time.Zones.All qualified as TZ
import GHC.Generics (Generic)
import System.Directory (getSymbolicLinkTarget)
import System.Environment (lookupEnv)
import System.FilePath (makeRelative)
data TZInfo = TZInfo
{ TZInfo -> TZIdentifier
tziIdentifier :: TZIdentifier
, TZInfo -> TZ
tziRules :: TZ
}
deriving stock (TZInfo -> TZInfo -> Bool
(TZInfo -> TZInfo -> Bool)
-> (TZInfo -> TZInfo -> Bool) -> Eq TZInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TZInfo -> TZInfo -> Bool
== :: TZInfo -> TZInfo -> Bool
$c/= :: TZInfo -> TZInfo -> Bool
/= :: TZInfo -> TZInfo -> Bool
Eq, Int -> TZInfo -> ShowS
[TZInfo] -> ShowS
TZInfo -> String
(Int -> TZInfo -> ShowS)
-> (TZInfo -> String) -> ([TZInfo] -> ShowS) -> Show TZInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TZInfo -> ShowS
showsPrec :: Int -> TZInfo -> ShowS
$cshow :: TZInfo -> String
show :: TZInfo -> String
$cshowList :: [TZInfo] -> ShowS
showList :: [TZInfo] -> ShowS
Show, Typeable TZInfo
Typeable TZInfo
-> (forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TZInfo -> c TZInfo)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TZInfo)
-> (TZInfo -> Constr)
-> (TZInfo -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TZInfo))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c TZInfo))
-> ((forall b. Data b => b -> b) -> TZInfo -> TZInfo)
-> (forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TZInfo -> r)
-> (forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TZInfo -> r)
-> (forall u. (forall d. Data d => d -> u) -> TZInfo -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> TZInfo -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo)
-> Data TZInfo
TZInfo -> Constr
TZInfo -> DataType
(forall b. Data b => b -> b) -> TZInfo -> TZInfo
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) -> TZInfo -> u
forall u. (forall d. Data d => d -> u) -> TZInfo -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> TZInfo -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> TZInfo -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TZInfo
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TZInfo -> c TZInfo
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TZInfo)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c TZInfo)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TZInfo -> c TZInfo
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TZInfo -> c TZInfo
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TZInfo
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TZInfo
$ctoConstr :: TZInfo -> Constr
toConstr :: TZInfo -> Constr
$cdataTypeOf :: TZInfo -> DataType
dataTypeOf :: TZInfo -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TZInfo)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TZInfo)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c TZInfo)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c TZInfo)
$cgmapT :: (forall b. Data b => b -> b) -> TZInfo -> TZInfo
gmapT :: (forall b. Data b => b -> b) -> TZInfo -> TZInfo
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> TZInfo -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> TZInfo -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> TZInfo -> r
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> TZInfo -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> TZInfo -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> TZInfo -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> TZInfo -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> TZInfo -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TZInfo -> m TZInfo
Data, (forall x. TZInfo -> Rep TZInfo x)
-> (forall x. Rep TZInfo x -> TZInfo) -> Generic TZInfo
forall x. Rep TZInfo x -> TZInfo
forall x. TZInfo -> Rep TZInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TZInfo -> Rep TZInfo x
from :: forall x. TZInfo -> Rep TZInfo x
$cto :: forall x. Rep TZInfo x -> TZInfo
to :: forall x. Rep TZInfo x -> TZInfo
Generic)
deriving anyclass TZInfo -> ()
(TZInfo -> ()) -> NFData TZInfo
forall a. (a -> ()) -> NFData a
$crnf :: TZInfo -> ()
rnf :: TZInfo -> ()
NFData
type TZIdentifier = Text
utc :: TZInfo
utc :: TZInfo
utc = TZIdentifier -> TZ -> TZInfo
TZInfo TZIdentifier
"UTC" TZ
TZ.utcTZ
loadFromSystem :: TZIdentifier -> IO TZInfo
loadFromSystem :: TZIdentifier -> IO TZInfo
loadFromSystem TZIdentifier
ident =
TZIdentifier -> TZ -> TZInfo
TZInfo TZIdentifier
ident (TZ -> TZInfo) -> IO TZ -> IO TZInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO TZ
TZ.loadSystemTZ (TZIdentifier -> String
T.unpack TZIdentifier
ident)
loadFromFile :: TZIdentifier -> FilePath -> IO TZInfo
loadFromFile :: TZIdentifier -> String -> IO TZInfo
loadFromFile TZIdentifier
ident String
filepath =
TZIdentifier -> TZ -> TZInfo
TZInfo TZIdentifier
ident (TZ -> TZInfo) -> IO TZ -> IO TZInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO TZ
TZ.loadTZFromFile String
filepath
getCurrentTZInfo :: IO TZInfo
getCurrentTZInfo :: IO TZInfo
getCurrentTZInfo =
String -> IO (Maybe String)
lookupEnv String
"TZ" IO (Maybe String) -> (Maybe String -> IO TZInfo) -> IO TZInfo
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe String
Nothing -> do
String
filePath <- String -> IO String
getSymbolicLinkTarget String
"/etc/localtime"
let ident :: TZIdentifier
ident = forall a. IsString a => String -> a
fromString @TZIdentifier (String -> TZIdentifier) -> String -> TZIdentifier
forall a b. (a -> b) -> a -> b
$ String -> ShowS
makeRelative String
"/usr/share/zoneinfo" String
filePath
TZ
tz <- String -> IO TZ
TZ.loadTZFromFile String
filePath
pure $ TZIdentifier -> TZ -> TZInfo
TZInfo TZIdentifier
ident TZ
tz
Just String
"" -> TZInfo -> IO TZInfo
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure TZInfo
utc
Just String
ident -> TZIdentifier -> TZ -> TZInfo
TZInfo (String -> TZIdentifier
forall a. IsString a => String -> a
fromString String
ident) (TZ -> TZInfo) -> IO TZ -> IO TZInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO TZ
TZ.loadSystemTZ String
ident
fromIdentifier :: TZIdentifier -> Maybe TZInfo
fromIdentifier :: TZIdentifier -> Maybe TZInfo
fromIdentifier TZIdentifier
ident =
TZIdentifier -> TZ -> TZInfo
TZInfo TZIdentifier
ident (TZ -> TZInfo) -> Maybe TZ -> Maybe TZInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> Maybe TZ
TZ.tzByName (TZIdentifier -> ByteString
T.encodeUtf8 TZIdentifier
ident)
fromLabel :: TZLabel -> TZInfo
fromLabel :: TZLabel -> TZInfo
fromLabel TZLabel
label =
TZIdentifier -> TZ -> TZInfo
TZInfo
(ByteString -> TZIdentifier
T.decodeUtf8 (ByteString -> TZIdentifier) -> ByteString -> TZIdentifier
forall a b. (a -> b) -> a -> b
$ TZLabel -> ByteString
TZ.toTZName TZLabel
label)
(TZLabel -> TZ
TZ.tzByLabel TZLabel
label)