1-- | A clone in Haskell of the zdump(8) command, including most of
2-- the bugs, that takes paths to Olson files instead of timezone
3-- names. This is useful for testing the Haskell implementation
4-- of the Olson timezone parser and renderer against the reference
5-- implementation in C. But less useful than it might seem at first,
6-- because Haskell rounds historical solar mean timezones to the
7-- nearest minute, whereas the C implementation rounds to the nearest
11import Data.Time.LocalTime.TimeZone.Series
12import Data.Time.LocalTime.TimeZone.Olson
14import Data.Maybe (listToMaybe)
15import System.Environment (getArgs)
16import System.Exit (exitWith, exitSuccess, ExitCode(ExitFailure))
17import System.Locale (defaultTimeLocale)
18import Control.Monad (guard)
22 putStrLn "hzdump version 0.1, clone of zdump 1.7 -c option fixed,"
23 putStrLn "takes zone file paths instead of zone specifications"
28 putStrLn "usage: hzdump [--version] [-v] [-c cutoff] zone-file-path ..."
29 putStrLn " where cutoff is lo-year,hi-year or hi-year"
30 exitWith $ ExitFailure 1
32illegalOpt :: Char -> IO a -- sic
34 putStrLn $ "hzdump: illegal option -- " ++ [opt]
37data Option = Version | Illegal Char |
38 Verbose (Maybe Integer, Maybe Integer) | Now
39 deriving (Eq, Ord, Show)
42 (opts, zones) <- fmap parseArgs getArgs
43 (getTimes, displayTime) <- case opts of
45 Illegal opt -> illegalOpt opt
46 Verbose rng -> return (transitionTimes rng, displayVerbose)
47 _ -> do now <- getCurrentTime
48 return (const [now], displayConcise)
49 tzss <- mapM getZone zones
50 putStr . unlines . concat $
51 zipWith (displayZone getTimes displayTime) zones tzss
53 getZone "-" = return utcTZ -- sic
54 getZone z = getTimeZoneSeriesFromOlsonFile z
56 displayZone getTimes displayTime zone tzs =
57 map ((zone ++) . (" " ++) . displayTime tzs) $ getTimes tzs
59parseArgs :: [String] -> (Option, [FilePath])
60parseArgs args | "--version" `elem` args = (Version, [])
61parseArgs args = getOpts False (Nothing, Nothing) args
63 getOpts _ cutoff ("-v":args) = getOpts True cutoff args
64 getOpts v _ ("-c":c:args) = maybe (Illegal 'c', [])
65 (\y -> getOpts v y args) $
67 getOpts v cutoff ("--":zones ) = (opts v cutoff, zones)
68 getOpts _ _ (('-':x:_):_) = (Illegal x, [])
69 getOpts v cutoff zones = (opts v cutoff, zones)
71 opts v cutoff = if v then Verbose cutoff else Now
73 parseCutoff c = let p0 = listToMaybe $ reads c
75 his = do str <- fmap snd p0
76 let (comma, str1) = splitAt 1 str
79 in los >> Just (maybe (Nothing, los) ((,) los . Just) his)
81displayConcise :: TimeZoneSeries -> UTCTime -> String
82displayConcise tzs t = formatTime defaultTimeLocale format $
85 format = "%a %b %e %T %Y %Z"
87displayVerbose :: TimeZoneSeries -> UTCTime -> String
88displayVerbose tzs t = concat [displayConcise utcTZ t, " = ",
89 displayConcise tzs t, " isdst=", if isdst then "1" else "0"]
91 isdst = timeZoneSummerOnly $ timeZoneFromSeries tzs t
93transitionTimes :: (Maybe Integer, Maybe Integer) -> TimeZoneSeries ->
95transitionTimes (lo, hi) =
96 maybe id (takeWhile . (>)) (fmap happyNewYear hi) .
97 maybe id (dropWhile . (>)) (fmap happyNewYear lo) .
98 addBugs . addPrevSecond . actualTransitions
100 happyNewYear y = UTCTime (fromGregorian y 1 1) 0
101 actualTransitions (TimeZoneSeries d cs) =
103 in map snd . filter fst $
104 zipWith (\(t, tz) prevTz -> (tz /= prevTz, t))
107 addPrevSecond = concatMap (\t -> [(-1) `addUTCTime` t, t])
108 addBugs = (bug0 ++) . (++ bug1) -- sic
109 bug0 = [UTCTime (fromGregorian 1901 12 13) (20*3600+45*60+52),
110 UTCTime (fromGregorian 1901 12 14) (20*3600+45*60+52)]
111 bug1 = [UTCTime (fromGregorian 2038 1 18) ( 3*3600+14*60+ 7),
112 UTCTime (fromGregorian 2038 1 19) ( 3*3600+14*60+ 7)]
114utcTZ :: TimeZoneSeries
115utcTZ = TimeZoneSeries utc []
117maybeRead :: Read a => String -> Maybe a
118maybeRead = fmap fst . listToMaybe . filter (null . snd) . reads
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list