timezone-olson-th-0.1.0.0: src/Data/Time/LocalTime/TimeZone/Olson/TH.hs
{-# LANGUAGE TemplateHaskell #-}
-- |
-- Load TimeZoneSeries from an Olson file at compile time.
--
-- For example:
--
-- > myTimeZoneSeries :: TimeZoneSeries
-- > myTimeZoneSeries = $(loadTZFile "/usr/share/zoneinfo/Europe/Stockholm")
module Data.Time.LocalTime.TimeZone.Olson.TH
(
loadTZFile
) where
import Data.Ratio (numerator,
denominator)
import Data.Time.LocalTime.TimeZone.Olson (getTimeZoneSeriesFromOlsonFile)
import Data.Time.LocalTime.TimeZone.Series (TimeZoneSeries(..))
import Data.Time.LocalTime (TimeZone(..))
import Data.Time (UTCTime(..),
Day(..),
DiffTime,
secondsToDiffTime)
import Language.Haskell.TH (Q,
runIO,
Exp(..),
mkName,
Lit(..),
litE,
integerL)
-- | Make a splice of a TimeZoneSeries from an Olson file.
loadTZFile :: FilePath -- ^ Path to the Olson file.
-> Q Exp
loadTZFile zf =
mkTZS =<< (runIO $ getTimeZoneSeriesFromOlsonFile zf)
-- | Make a splice of a TimeZoneSeries.
mkTZS :: TimeZoneSeries -- ^ The TimeZoneSeries to be spliced
-> Q Exp
mkTZS (TimeZoneSeries def tlist) = [| TimeZoneSeries $(litTimeZone def) $(mkList tlist) |]
mkList :: [(UTCTime,TimeZone)]
-> Q Exp
mkList l = [| $(fmap ListE $ mapM mkPair l) |]
mkPair :: (UTCTime,TimeZone)
-> Q Exp
mkPair (t,tz) = [| ($(litUTCTime t),$(litTimeZone tz)) |]
litUTCTime :: UTCTime
-> Q Exp
litUTCTime (UTCTime (ModifiedJulianDay d) s) =
[| UTCTime (ModifiedJulianDay $(litInteger d))
(secondsToDiffTime $(litInteger $ diffTimeToInteger s)) |]
litInteger :: Integer
-> Q Exp
litInteger = litE . integerL
diffTimeToInteger :: DiffTime
-> Integer
diffTimeToInteger s =
let r = toRational s
n = numerator r
d = denominator r in
(n `div` d)
litTimeZone :: TimeZone
-> Q Exp
litTimeZone (TimeZone m s n) =
[| TimeZone $(litInteger $ toInteger m)
$(return $ ConE $ mkName $ show s)
$(litE $ StringL n) |]