module Lambdabot.Compat.AltTime
( ClockTime
, getClockTime
, diffClockTimes
, addToClockTime
, timeDiffPretty
, TimeDiff(..)
, noTimeDiff
) where
import Control.Arrow (first)
import Data.Binary
import Data.List
import Data.Time
import Text.Read hiding (get, lexP, readPrec)
import Text.Read.Lex
newtype ClockTime = ClockTime UTCTime
deriving Eq
newtype TimeDiff = TimeDiff NominalDiffTime
deriving (Eq, Ord)
noTimeDiff :: TimeDiff
noTimeDiff = TimeDiff 0
epoch :: UTCTime
epoch = UTCTime (fromGregorian 1970 1 1) 0
toOldTime :: ClockTime -> (Integer, Integer)
toOldTime (ClockTime t) = round (diffUTCTime t epoch * 1e12) `divMod` 1000000000000
fromOldTime :: Integer -> Integer -> ClockTime
fromOldTime x y = ClockTime (addUTCTime (fromIntegral x + fromIntegral y * 1e-12) epoch)
instance Show ClockTime where
showsPrec p = showsPrec p . toOldTime
instance Read ClockTime where
readsPrec p = map (first (uncurry fromOldTime)) . readsPrec p
instance Show TimeDiff where
showsPrec p td = showParen (p > 10) $
( showString "TimeDiff {tdYear = "
. showsPrec 11 ye
. showString ", tdMonth = "
. showsPrec 11 mo
. showString ", tdDay = "
. showsPrec 11 da
. showString ", tdHour = "
. showsPrec 11 ho
. showString ", tdMin = "
. showsPrec 11 mi
. showString ", tdSec = "
. showsPrec 11 se
. showString ", tdPicosec = "
. showsPrec 11 ps
. showString "}")
where (ye, mo, da, ho, mi, se, ps) = toOldTimeDiff td
instance Read TimeDiff where
readsPrec = readPrec_to_S $ parens
(prec 11 (do
let lexP = lift Text.Read.Lex.lex
readPrec :: Read a => ReadPrec a
readPrec = readS_to_Prec readsPrec
Ident "TimeDiff" <- lexP
Punc "{" <- lexP
Ident "tdYear" <- lexP
Punc "=" <- lexP
ye <- reset readPrec
Punc "," <- lexP
Ident "tdMonth" <- lexP
Punc "=" <- lexP
mo <- reset readPrec
Punc "," <- lexP
Ident "tdDay" <- lexP
Punc "=" <- lexP
da <- reset readPrec
Punc "," <- lexP
Ident "tdHour" <- lexP
Punc "=" <- lexP
ho <- reset readPrec
Punc "," <- lexP
Ident "tdMin" <- lexP
Punc "=" <- lexP
mi <- reset readPrec
Punc "," <- lexP
Ident "tdSec" <- lexP
Punc "=" <- lexP
se <- reset readPrec
Punc "," <- lexP
Ident "tdPicosec" <- lexP
Punc "=" <- lexP
ps <- reset readPrec
Punc "}" <- lexP
return (fromOldTimeDiff ye mo da ho mi se ps)))
readList = readListDefault
readListPrec = readListPrecDefault
getClockTime :: IO ClockTime
getClockTime = ClockTime `fmap` getCurrentTime
diffClockTimes :: ClockTime -> ClockTime -> TimeDiff
diffClockTimes (ClockTime ct1) (ClockTime ct2) = TimeDiff (diffUTCTime ct1 ct2)
addToClockTime :: TimeDiff -> ClockTime -> ClockTime
addToClockTime (TimeDiff td) (ClockTime ct) = ClockTime (addUTCTime td ct)
timeDiffPretty :: TimeDiff -> String
timeDiffPretty td = concat . intersperse " " $ filter (not . null)
[ prettyP ye "y"
, prettyP mo "m"
, prettyP da "d"
, prettyP ho "h"
, prettyP mi "m"
, prettyP se "s"
]
where
prettyP 0 _ = []
prettyP i s = show i ++ s
(ye, mo, da, ho, mi, se, _) = toOldTimeDiff td
toOldTimeDiff :: TimeDiff -> (Int, Int, Int, Int, Int, Int, Integer)
toOldTimeDiff (TimeDiff td) = (fromInteger ye, fromInteger mo, fromInteger da, fromInteger ho, fromInteger mi, fromInteger se, ps)
where
(a, ps) = round (td * 1e12) `divMod` 1000000000000
(b, se) = a `divMod` 60
(c, mi) = b `divMod` 60
(d, ho) = c `divMod` 24
(e, da) = d `divMod` 28
(ye, mo) = e `divMod` 12
fromOldTimeDiff :: Int -> Int -> Int -> Int -> Int -> Int -> Integer -> TimeDiff
fromOldTimeDiff ye mo da ho mi se ps =
TimeDiff
(1e-12 * fromIntegral (ps
+ 1000000000000 * (toInteger se
+ 60 * (toInteger mi
+ 60 * (toInteger ho
+ 24 * (toInteger da
+ 28 * (toInteger mo
+ 12 * toInteger ye)))))))
instance Binary ClockTime where
put t = put i >> put j
where (i, j) = toOldTime t
get = do
i <- get
j <- get
return (fromOldTime i j)
instance Binary TimeDiff where
put td = do
put ye; put mo; put da; put ho; put mi; put se; put ps
where (ye, mo, da, ho, mi, se, ps) = toOldTimeDiff td
get = do
ye <- get
mo <- get
da <- get
ho <- get
mi <- get
se <- get
ps <- get
return (fromOldTimeDiff ye mo da ho mi se ps)