module Data.Time.Ebeats
( Ebeats(..)
, EbeatsTime(..)
, getEbeatsTime
, getEbeats
, toEbeatsTime
, toEbeats
, ebeatsToSeconds
, secondsToEbeats
, diffEbeatsTime
, addEbeatsTime
)
where
import Data.Fixed (Fixed, E2, divMod')
import Data.Time (UTCTime(..), getCurrentTime)
import Data.Time.LocalTime (TimeOfDay(..), timeToTimeOfDay)
import Data.Time.Calendar (toGregorian, Day(ModifiedJulianDay), toModifiedJulianDay)
newtype Ebeats = Ebeats { ebeatsTimeValue :: Fixed E2 }
deriving (Eq, Ord)
data EbeatsTime = EbeatsTime { days :: Integer
, ebeats :: Ebeats }
deriving (Eq, Ord)
instance Show Ebeats where
show = ('@':) . show . ebeatsTimeValue
instance Show EbeatsTime where
show ebeatsTime = show y ++ "-" ++ show m ++ "m-" ++ show d ++ "d " ++ show (ebeats ebeatsTime) where
(y,m,d) = toGregorian $ ModifiedJulianDay $ days ebeatsTime
getEbeats :: IO Ebeats
getEbeats = toEbeats `fmap` getCurrentTime
getEbeatsTime :: IO EbeatsTime
getEbeatsTime = do ebs <- getEbeats
now <- getCurrentTime
let day = toModifiedJulianDay $ utctDay now
return $ EbeatsTime day ebs
toEbeats :: UTCTime -> Ebeats
toEbeats utct =
let TimeOfDay h m s = timeToTimeOfDay $ utctDayTime utct
!ebs = realToFrac $ s * 5/432 + realToFrac m * 25/36 + realToFrac h * 125/3
in Ebeats ebs
toEbeatsTime :: UTCTime -> EbeatsTime
toEbeatsTime utct =
let TimeOfDay h m s = timeToTimeOfDay $ utctDayTime utct
!ebs = realToFrac $ s * 5/432 + realToFrac m * 25/36 + realToFrac h * 125/3
day = toModifiedJulianDay $ utctDay utct
in EbeatsTime day (Ebeats ebs)
diffEbeatsTime :: EbeatsTime
-> EbeatsTime
-> Ebeats
diffEbeatsTime (EbeatsTime day0 (Ebeats ebeats0)) (EbeatsTime day1 (Ebeats ebeats1))
= let total0 = (fromIntegral $ day0 * 1000 :: Fixed E2) + ebeats0
total1 = (fromIntegral $ day1 * 1000 :: Fixed E2) + ebeats1
in Ebeats (total0 total1)
addEbeatsTime :: Ebeats
-> EbeatsTime
-> EbeatsTime
addEbeatsTime (Ebeats a) (EbeatsTime d (Ebeats e)) = let (newDays, newEbeats) = divMod' (a + e) 1000
in EbeatsTime (d + newDays) (Ebeats newEbeats)
instance Num Ebeats where
(Ebeats a) + (Ebeats b) = Ebeats (a + b)
(Ebeats a) (Ebeats b) = Ebeats (a b)
(Ebeats a) * (Ebeats b) = Ebeats (a * b)
negate (Ebeats a) = Ebeats (negate a)
abs (Ebeats a) = Ebeats (abs a)
signum (Ebeats a) = Ebeats (signum a)
fromInteger an_int = Ebeats (fromInteger an_int)
ebeatsToSeconds :: Ebeats
-> Fixed E2
ebeatsToSeconds (Ebeats a) = a * (86400 / 1000)
secondsToEbeats :: Fixed E2
-> Ebeats
secondsToEbeats secs = Ebeats $ secs * (1000 / 86400)