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)
loadTZFile :: FilePath
-> Q Exp
loadTZFile zf =
mkTZS =<< (runIO $ getTimeZoneSeriesFromOlsonFile zf)
mkTZS :: TimeZoneSeries
-> 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) |]