{-# OPTIONS_HADDOCK hide #-}
module Data.Time.LocalTime.TimeZone.Olson.Render
(
renderTimeZoneSeriesToOlsonFile,
timeZoneSeriesToOlson,
renderOlsonToFile,
verifyOlsonLimits,
putOlson,
extractOlsonV1
)
where
import Data.Time.LocalTime.TimeZone.Olson.Types
import Data.Time.LocalTime.TimeZone.Series (TimeZoneSeries(TimeZoneSeries))
import Data.Time (TimeZone(TimeZone, timeZoneSummerOnly, timeZoneName))
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
import Data.Binary.Put (Put, runPut, putByteString, putWord8, flush,
putWord32be, putWord64be)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Data.List (partition, sortBy, sort, group)
import Data.Ord (comparing)
import Data.Word (Word8)
import Data.Maybe (listToMaybe, maybeToList, isNothing, fromMaybe, catMaybes)
import Data.Monoid (mempty)
import Control.Monad (guard, replicateM_, unless)
renderTimeZoneSeriesToOlsonFile :: FilePath -> TimeZoneSeries -> IO ()
renderTimeZoneSeriesToOlsonFile :: String -> TimeZoneSeries -> IO ()
renderTimeZoneSeriesToOlsonFile String
fp = String -> OlsonData -> IO ()
renderOlsonToFile String
fp (OlsonData -> IO ())
-> (TimeZoneSeries -> OlsonData) -> TimeZoneSeries -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
OlsonData -> Maybe OlsonData -> OlsonData
forall a. a -> Maybe a -> a
fromMaybe (String -> OlsonData
forall a. HasCallStack => String -> a
error String
"Cannot render TimeZoneSeries: default is summer time") (Maybe OlsonData -> OlsonData)
-> (TimeZoneSeries -> Maybe OlsonData)
-> TimeZoneSeries
-> OlsonData
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
TimeZoneSeries -> Maybe OlsonData
timeZoneSeriesToOlson
timeZoneSeriesToOlson :: TimeZoneSeries -> Maybe OlsonData
timeZoneSeriesToOlson :: TimeZoneSeries -> Maybe OlsonData
timeZoneSeriesToOlson (TimeZoneSeries TimeZone
dflt [(UTCTime, TimeZone)]
pairs)
| TimeZone -> Bool
timeZoneSummerOnly TimeZone
dflt Bool -> Bool -> Bool
&& Bool -> Bool
not ((TimeZone -> Bool) -> [TimeZone] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all TimeZone -> Bool
timeZoneSummerOnly ([TimeZone] -> Bool) -> [TimeZone] -> Bool
forall a b. (a -> b) -> a -> b
$ ((UTCTime, TimeZone) -> TimeZone)
-> [(UTCTime, TimeZone)] -> [TimeZone]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime, TimeZone) -> TimeZone
forall a b. (a, b) -> b
snd [(UTCTime, TimeZone)]
pairs)
= Maybe OlsonData
forall a. Maybe a
Nothing
| Bool
otherwise = OlsonData -> Maybe OlsonData
forall a. a -> Maybe a
Just (OlsonData -> Maybe OlsonData) -> OlsonData -> Maybe OlsonData
forall a b. (a -> b) -> a -> b
$
[Transition]
-> [TtInfo String] -> [LeapInfo] -> Maybe String -> OlsonData
OlsonData
[Integer -> Int -> Transition
Transition Integer
secs Int
ttinfo |
(UTCTime
t, TimeZone
tz) <- [(UTCTime, TimeZone)] -> [(UTCTime, TimeZone)]
forall a. [a] -> [a]
reverse [(UTCTime, TimeZone)]
pairs,
let secs :: Integer
secs = POSIXTime -> Integer
forall b. Integral b => POSIXTime -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (POSIXTime -> Integer) -> POSIXTime -> Integer
forall a b. (a -> b) -> a -> b
$ UTCTime -> POSIXTime
utcTimeToPOSIXSeconds UTCTime
t,
Int
ttinfo <- Maybe Int -> [Int]
forall a. Maybe a -> [a]
maybeToList (Maybe Int -> [Int]) -> Maybe Int -> [Int]
forall a b. (a -> b) -> a -> b
$ TtInfo String -> [(TtInfo String, Int)] -> Maybe Int
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (TimeZone -> TtInfo String
mkTT TimeZone
tz) [(TtInfo String, Int)]
ttAssocs]
[TtInfo String]
ttinfos
[]
Maybe String
forall a. Maybe a
Nothing
where
mkTT :: TimeZone -> TtInfo String
mkTT (TimeZone Int
offset Bool
isdst String
abbr) =
Int -> Bool -> TransitionType -> String -> TtInfo String
forall abbr. Int -> Bool -> TransitionType -> abbr -> TtInfo abbr
TtInfo (Int
offsetInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
60) Bool
isdst TransitionType
Wall String
abbr
dfltTT :: TtInfo String
dfltTT = TimeZone -> TtInfo String
mkTT TimeZone
dflt
ttAssocs :: [(TtInfo String, Int)]
ttAssocs = (TtInfo String
dfltTT, Int
0) (TtInfo String, Int)
-> [(TtInfo String, Int)] -> [(TtInfo String, Int)]
forall a. a -> [a] -> [a]
:
[TtInfo String] -> [Int] -> [(TtInfo String, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([TtInfo String] -> [TtInfo String]
forall a. Eq a => [a] -> [a]
uniq ([TtInfo String] -> [TtInfo String])
-> ([TtInfo String] -> [TtInfo String])
-> [TtInfo String]
-> [TtInfo String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TtInfo String] -> [TtInfo String]
forall a. Ord a => [a] -> [a]
sort ([TtInfo String] -> [TtInfo String])
-> ([TtInfo String] -> [TtInfo String])
-> [TtInfo String]
-> [TtInfo String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TtInfo String -> Bool) -> [TtInfo String] -> [TtInfo String]
forall a. (a -> Bool) -> [a] -> [a]
filter (TtInfo String -> TtInfo String -> Bool
forall a. Eq a => a -> a -> Bool
/= TtInfo String
dfltTT) ([TtInfo String] -> [TtInfo String])
-> [TtInfo String] -> [TtInfo String]
forall a b. (a -> b) -> a -> b
$ ((UTCTime, TimeZone) -> TtInfo String)
-> [(UTCTime, TimeZone)] -> [TtInfo String]
forall a b. (a -> b) -> [a] -> [b]
map (TimeZone -> TtInfo String
mkTT (TimeZone -> TtInfo String)
-> ((UTCTime, TimeZone) -> TimeZone)
-> (UTCTime, TimeZone)
-> TtInfo String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UTCTime, TimeZone) -> TimeZone
forall a b. (a, b) -> b
snd) [(UTCTime, TimeZone)]
pairs) [Int
1..]
ttinfos :: [TtInfo String]
ttinfos = ((TtInfo String, Int) -> TtInfo String)
-> [(TtInfo String, Int)] -> [TtInfo String]
forall a b. (a -> b) -> [a] -> [b]
map (TtInfo String, Int) -> TtInfo String
forall a b. (a, b) -> a
fst [(TtInfo String, Int)]
ttAssocs
verifyOlsonLimits :: SizeLimits -> OlsonData -> Bool
verifyOlsonLimits :: SizeLimits -> OlsonData -> Bool
verifyOlsonLimits SizeLimits
limits (OlsonData [Transition]
transs [TtInfo String]
ttinfos [LeapInfo]
leaps Maybe String
_) =
(SizeLimits -> Maybe Int) -> [Transition] -> Bool
forall {a}. (SizeLimits -> Maybe Int) -> [a] -> Bool
withinLimit SizeLimits -> Maybe Int
maxTimes [Transition]
transs Bool -> Bool -> Bool
&&
(SizeLimits -> Maybe Int) -> [TtInfo String] -> Bool
forall {a}. (SizeLimits -> Maybe Int) -> [a] -> Bool
withinLimit SizeLimits -> Maybe Int
maxTypes [TtInfo String]
ttinfos Bool -> Bool -> Bool
&&
(SizeLimits -> Maybe Int) -> [LeapInfo] -> Bool
forall {a}. (SizeLimits -> Maybe Int) -> [a] -> Bool
withinLimit SizeLimits -> Maybe Int
maxLeaps [LeapInfo]
leaps Bool -> Bool -> Bool
&&
(SizeLimits -> Maybe Int) -> String -> Bool
forall {a}. (SizeLimits -> Maybe Int) -> [a] -> Bool
withinLimit SizeLimits -> Maybe Int
maxAbbrChars String
abbrChars
where
withinLimit :: (SizeLimits -> Maybe Int) -> [a] -> Bool
withinLimit SizeLimits -> Maybe Int
limit [a]
items = Bool -> (Int -> Bool) -> Maybe Int -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True ([a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([a] -> Bool) -> (Int -> [a]) -> Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> [a] -> [a]) -> [a] -> Int -> [a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop [a]
items) (Maybe Int -> Bool) -> Maybe Int -> Bool
forall a b. (a -> b) -> a -> b
$
SizeLimits -> Maybe Int
limit SizeLimits
limits
abbrChars :: String
abbrChars = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
abbrStrs String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String -> Char) -> [String] -> String
forall a b. (a -> b) -> [a] -> [b]
map (Char -> String -> Char
forall a b. a -> b -> a
const Char
'\NUL') [String]
abbrStrs
abbrStrs :: [String]
abbrStrs = (TtInfo String -> String) -> [TtInfo String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map TtInfo String -> String
forall abbr. TtInfo abbr -> abbr
tt_abbr [TtInfo String]
ttinfos
renderOlsonToFile :: FilePath -> OlsonData -> IO ()
renderOlsonToFile :: String -> OlsonData -> IO ()
renderOlsonToFile String
fp OlsonData
olson = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (SizeLimits -> OlsonData -> Bool
verifyOlsonLimits SizeLimits
defaultLimits OlsonData
olson) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
forall a. HasCallStack => String -> a
error String
"Olson timezone data exceeds size limits"
String -> ByteString -> IO ()
L.writeFile String
fp (ByteString -> IO ())
-> (OlsonData -> ByteString) -> OlsonData -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPut (Put -> ByteString)
-> (OlsonData -> Put) -> OlsonData -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OlsonData -> Put
putOlson (OlsonData -> IO ()) -> OlsonData -> IO ()
forall a b. (a -> b) -> a -> b
$ OlsonData
olson
putOlson :: OlsonData -> Put
putOlson olson :: OlsonData
olson@(OlsonData [Transition]
_ [TtInfo String]
_ [LeapInfo]
_ Maybe String
posix)
| Bool
fitsInVersion1 = Word8 -> (Integer -> Put) -> OlsonData -> Put
putOlsonPart Word8
0 Integer -> Put
forall a. Integral a => a -> Put
put32bitIntegral OlsonData
olson
| Bool
otherwise = do Word8 -> (Integer -> Put) -> OlsonData -> Put
putOlsonPart Word8
50 Integer -> Put
forall a. Integral a => a -> Put
put32bitIntegral OlsonData
olson1
Word8 -> (Integer -> Put) -> OlsonData -> Put
putOlsonPart Word8
50 Integer -> Put
forall a. Integral a => a -> Put
put64bitIntegral OlsonData
olson
Maybe String -> Put
putPosixTZ Maybe String
posix
where
olson1 :: OlsonData
olson1 = OlsonData -> OlsonData
extractOlsonV1 OlsonData
olson
fitsInVersion1 :: Bool
fitsInVersion1 = (String -> Bool) -> Maybe String -> Maybe Bool
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Maybe String
posix Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False Bool -> Bool -> Bool
&&
OlsonData
olson1 OlsonData -> OlsonData -> Bool
forall a. Eq a => a -> a -> Bool
== OlsonData
olson {olsonPosixTZ :: Maybe String
olsonPosixTZ = Maybe String
forall a. Maybe a
Nothing}
extractOlsonV1 :: OlsonData -> OlsonData
(OlsonData [Transition]
transs [TtInfo String]
ttinfos [LeapInfo]
leaps Maybe String
_)
| Bool
allV1 = [Transition]
-> [TtInfo String] -> [LeapInfo] -> Maybe String -> OlsonData
OlsonData [Transition]
transs [TtInfo String]
ttinfos [LeapInfo]
leaps Maybe String
forall a. Maybe a
Nothing
| Bool
otherwise = [Transition]
-> [TtInfo String] -> [LeapInfo] -> Maybe String -> OlsonData
OlsonData [Transition]
transs1 [TtInfo String]
ttinfos1 [LeapInfo]
leaps1 Maybe String
forall a. Maybe a
Nothing
where
cutoff :: Integer
cutoff = Integer
0x80000000
fitsIn32bits :: Integer -> Bool
fitsIn32bits Integer
x = Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
cutoff Bool -> Bool -> Bool
&& Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer -> Integer
forall a. Num a => a -> a
negate Integer
cutoff
leaps1 :: [LeapInfo]
leaps1 = (LeapInfo -> Bool) -> [LeapInfo] -> [LeapInfo]
forall a. (a -> Bool) -> [a] -> [a]
filter (Integer -> Bool
fitsIn32bits (Integer -> Bool) -> (LeapInfo -> Integer) -> LeapInfo -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LeapInfo -> Integer
leapTime) [LeapInfo]
leaps
transs1' :: [Transition]
transs1' = (Transition -> Bool) -> [Transition] -> [Transition]
forall a. (a -> Bool) -> [a] -> [a]
filter (Integer -> Bool
fitsIn32bits (Integer -> Bool) -> (Transition -> Integer) -> Transition -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transition -> Integer
transTime) [Transition]
transs
allV1 :: Bool
allV1 = [LeapInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [LeapInfo]
leaps1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [LeapInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [LeapInfo]
leaps Bool -> Bool -> Bool
&& [Transition] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Transition]
transs1' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [Transition] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Transition]
transs
assoc1 :: [(Int, Int)]
assoc1 = [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip
((Int -> Int -> Ordering) -> [Int] -> [Int]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((Int -> Maybe TransitionType) -> Int -> Int -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing ((Int -> Maybe TransitionType) -> Int -> Int -> Ordering)
-> (Int -> Maybe TransitionType) -> Int -> Int -> Ordering
forall a b. (a -> b) -> a -> b
$ (TtInfo String -> TransitionType)
-> Maybe (TtInfo String) -> Maybe TransitionType
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TtInfo String -> TransitionType
forall abbr. TtInfo abbr -> TransitionType
tt_ttype (Maybe (TtInfo String) -> Maybe TransitionType)
-> (Int -> Maybe (TtInfo String)) -> Int -> Maybe TransitionType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TtInfo String] -> Maybe (TtInfo String)
forall a. [a] -> Maybe a
listToMaybe ([TtInfo String] -> Maybe (TtInfo String))
-> (Int -> [TtInfo String]) -> Int -> Maybe (TtInfo String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> [TtInfo String] -> [TtInfo String])
-> [TtInfo String] -> Int -> [TtInfo String]
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [TtInfo String] -> [TtInfo String]
forall a. Int -> [a] -> [a]
drop [TtInfo String]
ttinfos) ([Int] -> [Int]) -> ([Int] -> [Int]) -> [Int] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
[Int] -> [Int]
forall a. Eq a => [a] -> [a]
uniq ([Int] -> [Int]) -> ([Int] -> [Int]) -> [Int] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort ([Int] -> [Int]) -> ([Int] -> [Int]) -> [Int] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
0 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
:) ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Transition -> Int) -> [Transition] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Transition -> Int
transIndex [Transition]
transs1')
[Int
0..]
transs1 :: [Transition]
transs1 = [Transition
t {transIndex :: Int
transIndex = Int
i} |
Transition
t <- [Transition]
transs1', Int
i <- Maybe Int -> [Int]
forall a. Maybe a -> [a]
maybeToList (Maybe Int -> [Int]) -> Maybe Int -> [Int]
forall a b. (a -> b) -> a -> b
$ Int -> [(Int, Int)] -> Maybe Int
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (Transition -> Int
transIndex Transition
t) [(Int, Int)]
assoc1]
ttinfos1 :: [TtInfo String]
ttinfos1 = ((Maybe Int, TtInfo String) -> TtInfo String)
-> [(Maybe Int, TtInfo String)] -> [TtInfo String]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe Int, TtInfo String) -> TtInfo String
forall a b. (a, b) -> b
snd ([(Maybe Int, TtInfo String)] -> [TtInfo String])
-> ([(Maybe Int, TtInfo String)] -> [(Maybe Int, TtInfo String)])
-> [(Maybe Int, TtInfo String)]
-> [TtInfo String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Maybe Int, TtInfo String) -> Bool)
-> [(Maybe Int, TtInfo String)] -> [(Maybe Int, TtInfo String)]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Maybe Int -> Bool
forall a. Maybe a -> Bool
isNothing (Maybe Int -> Bool)
-> ((Maybe Int, TtInfo String) -> Maybe Int)
-> (Maybe Int, TtInfo String)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Int, TtInfo String) -> Maybe Int
forall a b. (a, b) -> a
fst) ([(Maybe Int, TtInfo String)] -> [(Maybe Int, TtInfo String)])
-> ([(Maybe Int, TtInfo String)] -> [(Maybe Int, TtInfo String)])
-> [(Maybe Int, TtInfo String)]
-> [(Maybe Int, TtInfo String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
((Maybe Int, TtInfo String)
-> (Maybe Int, TtInfo String) -> Ordering)
-> [(Maybe Int, TtInfo String)] -> [(Maybe Int, TtInfo String)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (((Maybe Int, TtInfo String) -> Maybe Int)
-> (Maybe Int, TtInfo String)
-> (Maybe Int, TtInfo String)
-> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (Maybe Int, TtInfo String) -> Maybe Int
forall a b. (a, b) -> a
fst) ([(Maybe Int, TtInfo String)] -> [TtInfo String])
-> [(Maybe Int, TtInfo String)] -> [TtInfo String]
forall a b. (a -> b) -> a -> b
$ [Maybe Int] -> [TtInfo String] -> [(Maybe Int, TtInfo String)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Int -> Maybe Int) -> [Int] -> [Maybe Int]
forall a b. (a -> b) -> [a] -> [b]
map ((Int -> [(Int, Int)] -> Maybe Int)
-> [(Int, Int)] -> Int -> Maybe Int
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [(Int, Int)] -> Maybe Int
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [(Int, Int)]
assoc1) [Int
0..]) [TtInfo String]
ttinfos
putOlsonPart :: Word8 -> (Integer -> Put) -> OlsonData -> Put
putOlsonPart :: Word8 -> (Integer -> Put) -> OlsonData -> Put
putOlsonPart Word8
version Integer -> Put
putTime (OlsonData [Transition]
transs [TtInfo String]
ttinfos [LeapInfo]
leaps Maybe String
_) = do
String -> String -> Put
putASCII String
"magic number" String
"TZif"
Word8 -> Put
putWord8 Word8
version
ByteString -> Put
putByteString (ByteString -> Put) -> ([Word8] -> ByteString) -> [Word8] -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
B.pack ([Word8] -> Put) -> [Word8] -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> [Word8]
forall a. Int -> a -> [a]
replicate Int
15 Word8
0
Int -> Put -> Put
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
2 (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ [TtInfo Int] -> Put
forall {a}. [a] -> Put
putCount [TtInfo Int]
ttinfosWithTtype
[LeapInfo] -> Put
forall {a}. [a] -> Put
putCount [LeapInfo]
leaps
[Transition] -> Put
forall {a}. [a] -> Put
putCount [Transition]
transs
[TtInfo String] -> Put
forall {a}. [a] -> Put
putCount [TtInfo String]
ttinfos
Int -> Put
forall a. Integral a => a -> Put
put32bitIntegral Int
abbrChars
(Transition -> Put) -> [Transition] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Integer -> Put
putTime (Integer -> Put) -> (Transition -> Integer) -> Transition -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transition -> Integer
transTime ) [Transition]
transs
(Transition -> Put) -> [Transition] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Int -> Put
forall a. Integral a => a -> Put
put8bitIntegral (Int -> Put) -> (Transition -> Int) -> Transition -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transition -> Int
transIndex) [Transition]
transs
(TtInfo Int -> Put) -> [TtInfo Int] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ TtInfo Int -> Put
putTtInfo [TtInfo Int]
ttinfosIndexed
(String -> Put) -> [String] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ String -> Put
putAbbr [String]
abbrStrings
(LeapInfo -> Put) -> [LeapInfo] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((Integer -> Put) -> LeapInfo -> Put
forall a. Integral a => (a -> Put) -> LeapInfo -> Put
putLeapInfo Integer -> Put
putTime) [LeapInfo]
leaps
(TtInfo Int -> Put) -> [TtInfo Int] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Bool -> Put
putBool (Bool -> Put) -> (TtInfo Int -> Bool) -> TtInfo Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TransitionType -> TransitionType -> Bool
forall a. Eq a => a -> a -> Bool
== TransitionType
Std) (TransitionType -> Bool)
-> (TtInfo Int -> TransitionType) -> TtInfo Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TtInfo Int -> TransitionType
forall abbr. TtInfo abbr -> TransitionType
tt_ttype) [TtInfo Int]
ttinfosWithTtype
(TtInfo Int -> Put) -> [TtInfo Int] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Bool -> Put
putBool (Bool -> Put) -> (TtInfo Int -> Bool) -> TtInfo Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TransitionType -> TransitionType -> Bool
forall a. Eq a => a -> a -> Bool
== TransitionType
UTC) (TransitionType -> Bool)
-> (TtInfo Int -> TransitionType) -> TtInfo Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TtInfo Int -> TransitionType
forall abbr. TtInfo abbr -> TransitionType
tt_ttype) [TtInfo Int]
ttinfosWithTtype
where
putCount :: [a] -> Put
putCount = Int -> Put
forall a. Integral a => a -> Put
put32bitIntegral (Int -> Put) -> ([a] -> Int) -> [a] -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length
ttinfosWithTtype :: [TtInfo Int]
ttinfosWithTtype = (TtInfo Int -> Bool) -> [TtInfo Int] -> [TtInfo Int]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile ((TransitionType -> TransitionType -> Bool
forall a. Ord a => a -> a -> Bool
<= TransitionType
UTC) (TransitionType -> Bool)
-> (TtInfo Int -> TransitionType) -> TtInfo Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TtInfo Int -> TransitionType
forall abbr. TtInfo abbr -> TransitionType
tt_ttype) [TtInfo Int]
ttinfosIndexed
abbrStrings :: [String]
abbrStrings = [String] -> [String]
forall a. Eq a => [a] -> [a]
uniq ([String] -> [String])
-> ([String] -> [String]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
forall a. Ord a => [a] -> [a]
sort ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (TtInfo String -> String) -> [TtInfo String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map TtInfo String -> String
forall abbr. TtInfo abbr -> abbr
tt_abbr [TtInfo String]
ttinfos
abbrChars :: Int
abbrChars = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((String -> Int) -> [String] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
abbrStrings) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
abbrStrings
putAbbr :: String -> Put
putAbbr String
abbr = String -> String -> Put
putASCII String
"time zone abbreviation" String
abbr Put -> Put -> Put
forall a b. PutM a -> PutM b -> PutM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8 Word8
0
abbrAssocs :: [(String, Int)]
abbrAssocs = [String] -> [Int] -> [(String, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [String]
abbrStrings ([Int] -> [(String, Int)])
-> ([Int] -> [Int]) -> [Int] -> [(String, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> Int -> [Int] -> [Int]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) Int
0 ([Int] -> [(String, Int)]) -> [Int] -> [(String, Int)]
forall a b. (a -> b) -> a -> b
$
(String -> Int) -> [String] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ((Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int -> Int) -> (String -> Int) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) [String]
abbrStrings
ttinfosIndexed :: [TtInfo Int]
ttinfosIndexed = [Int -> Bool -> TransitionType -> Int -> TtInfo Int
forall abbr. Int -> Bool -> TransitionType -> abbr -> TtInfo abbr
TtInfo Int
utoff Bool
isdst TransitionType
ttype Int
i |
TtInfo Int
utoff Bool
isdst TransitionType
ttype String
abbr <- [TtInfo String]
ttinfos,
Int
i <- Maybe Int -> [Int]
forall a. Maybe a -> [a]
maybeToList (Maybe Int -> [Int]) -> Maybe Int -> [Int]
forall a b. (a -> b) -> a -> b
$ String -> [(String, Int)] -> Maybe Int
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
abbr [(String, Int)]
abbrAssocs]
putPosixTZ :: Maybe String -> Put
putPosixTZ :: Maybe String -> Put
putPosixTZ Maybe String
posix = do
Word8 -> Put
putWord8 Word8
10
String -> String -> Put
putASCII String
"POSIX TZ string"(String -> Put) -> String -> Put
forall a b. (a -> b) -> a -> b
$ String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"" Maybe String
posix
Word8 -> Put
putWord8 Word8
10
putTtInfo :: TtInfo Int -> Put
putTtInfo :: TtInfo Int -> Put
putTtInfo TtInfo Int
tt = do
Int -> Put
forall a. Integral a => a -> Put
put32bitIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ TtInfo Int -> Int
forall abbr. TtInfo abbr -> Int
tt_utoff TtInfo Int
tt
Bool -> Put
putBool (Bool -> Put) -> Bool -> Put
forall a b. (a -> b) -> a -> b
$ TtInfo Int -> Bool
forall abbr. TtInfo abbr -> Bool
tt_isdst TtInfo Int
tt
Int -> Put
forall a. Integral a => a -> Put
put8bitIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ TtInfo Int -> Int
forall abbr. TtInfo abbr -> abbr
tt_abbr TtInfo Int
tt
putLeapInfo :: Integral a => (a -> Put) -> LeapInfo -> Put
putLeapInfo :: forall a. Integral a => (a -> Put) -> LeapInfo -> Put
putLeapInfo a -> Put
putTime LeapInfo
leap = do
a -> Put
putTime (a -> Put) -> (Integer -> a) -> Integer -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Put) -> Integer -> Put
forall a b. (a -> b) -> a -> b
$ LeapInfo -> Integer
leapTime LeapInfo
leap
Int -> Put
forall a. Integral a => a -> Put
put32bitIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ LeapInfo -> Int
leapOffset LeapInfo
leap
put8bitIntegral :: Integral a => a -> Put
put8bitIntegral :: forall a. Integral a => a -> Put
put8bitIntegral = Word8 -> Put
putWord8 (Word8 -> Put) -> (a -> Word8) -> a -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral
put32bitIntegral :: Integral a => a -> Put
put32bitIntegral :: forall a. Integral a => a -> Put
put32bitIntegral = Word32 -> Put
putWord32be (Word32 -> Put) -> (a -> Word32) -> a -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
put64bitIntegral :: Integral a => a -> Put
put64bitIntegral :: forall a. Integral a => a -> Put
put64bitIntegral = Word64 -> Put
putWord64be (Word64 -> Put) -> (a -> Word64) -> a -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
putBool :: Bool -> Put
putBool :: Bool -> Put
putBool Bool
False = Word8 -> Put
putWord8 Word8
0
putBool Bool
True = Word8 -> Put
putWord8 Word8
1
uniq :: Eq a => [a] -> [a]
uniq :: forall a. Eq a => [a] -> [a]
uniq = ([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> a
forall a. HasCallStack => [a] -> a
head ([[a]] -> [a]) -> ([a] -> [[a]]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [[a]]
forall a. Eq a => [a] -> [[a]]
group
putASCII :: String -> String -> Put
putASCII :: String -> String -> Put
putASCII String
what =
ByteString -> Put
putByteString (ByteString -> Put) -> (String -> ByteString) -> String -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
B.pack ([Word8] -> ByteString)
-> (String -> [Word8]) -> String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Word8) -> String -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int
forall {a}. (Ord a, Num a) => a -> a
verify (Int -> Int) -> (Char -> Int) -> Char -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
forall a. Enum a => a -> Int
fromEnum)
where
verify :: a -> a
verify a
c
| a
c a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
32 Bool -> Bool -> Bool
&& a
c a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
126 = a
c
| Bool
otherwise = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Cannot render TimeZoneSeries: " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" contains non-ASCII characters"