roshask-0.2: src/Ros/Internal/RosTime.hs
-- |Utilities for working with ROS time values.
module Ros.Internal.RosTime (ROSTime, ROSDuration, toROSTime, fromROSTime,
diffROSTime, getROSTime, diffSeconds) where
import Data.Time.Clock (UTCTime, NominalDiffTime)
import Data.Time.Clock.POSIX
import Data.Word (Word32)
import Ros.Internal.RosTypes
toROSTime :: UTCTime -> ROSTime
toROSTime = aux . properFraction . utcTimeToPOSIXSeconds
where aux (s,f) = (s, truncate $ f * 1000000)
-- |Class of types that may be derived from a 'ROSTime'.
class FromROSTime a where
fromROSTime :: ROSTime -> a
instance FromROSTime UTCTime where
fromROSTime = posixSecondsToUTCTime . aux . fromROSTime
where aux = realToFrac :: Double -> NominalDiffTime
-- |Convert a 'ROSTime' to the POSIX number of seconds since epoch.
instance FromROSTime Double where
fromROSTime (s,ns) = s' + ns'
where s' = fromIntegral s :: Double
ns' = fromIntegral ns / 1000000 :: Double
-- |@timeDiff t1 t2@ computes the difference @t1 - t2@.
diffROSTime :: ROSTime -> ROSTime -> ROSDuration
diffROSTime (s1,ns1) (s2,ns2)
| dns >= 0 = (fi ds, fi dns)
| otherwise = (fi $ ds - 1, fi $ 1000000 + dns)
where dns = fw ns1 - fw ns2
ds = fw s1 - fw s2
fw :: Word32 -> Int
fw = fromIntegral
fi :: Int -> Word32
fi = fromIntegral
-- |Get the current POSIX time.
getROSTime :: IO ROSTime
getROSTime = fmap (aux . properFraction) getPOSIXTime
where aux (s,f) = (s, truncate $ f * 1000000)
-- |Compute the difference in seconds between two 'ROSTime'
-- values. The application @diffSeconds tStop tStart@ computes the
-- time interval @tStop - tStart@.
diffSeconds :: ROSTime -> ROSTime -> Double
diffSeconds t1 t2 = fromROSTime $ diffROSTime t1 t2