System.Time.Clock Implementation - Clock.hs (1/1)
Ashley Yakeley
ashley at semantic.org
Wed Feb 23 21:42:29 EST 2005
OK, I have my own darcs repository for code, but I seem to have trouble
pushing it to the empty repository I set up on a server:
<http://www.abridgegame.org/pipermail/darcs-users/2005-February/005828.ht
ml>
In the mean time, attached is a first attempt at an implementation of
System.Time.Clock. It should compile OK. Some notes:
* I use FFI to call gettimeofday to get the current day.
* DiffTime and UTCDiffTime are instances of Num, Integral etc., and as
such it represent picoseconds. This isn't ideal with regards to physical
dimension, but that's the way the numeric classes are.
* Arithmetic on UTC times works by "squeezing" leap seconds, i.e.
converting them to POSIX times:
1998-12-31 23:59:60.5 UTC + 0 UTC = 1999-01-01 00:00:00.0 UTC
I'm not sure what the best solution is here.
* More haddock comments will be forthcoming...
--
Ashley Yakeley, Seattle WA
{-# OPTIONS -ffi -fglasgow-exts #-}
module System.Time.Clock
(
-- Modified Julian days and dates (for UT1)
ModJulianDay,ModJulianDate,
-- absolute time intervals
DiffTime,timeToSISeconds,siSecondsToTime,
-- UTC arithmetic
UTCTime(..),UTCDiffTime,utcTimeToUTCSeconds,utcSecondsToUTCTime,
addUTCTime,diffUTCTime,
-- getting the current UTC time
getCurrentTime
) where
import Foreign
import Foreign.C
-- | standard Julian count of Earth days
type ModJulianDay = Integer
-- | standard Julian dates for UT1, 1 = 1 day
type ModJulianDate = Rational
secondPicoseconds :: (Num a) => a
secondPicoseconds = 1000000000000
newtype DiffTime = MkDiffTime Integer deriving (Eq,Ord,Num,Enum,Real,Integral)
instance Show DiffTime where
show (MkDiffTime t) = (show t) ++ "ps"
timeToSISeconds :: (Fractional a) => DiffTime -> a
timeToSISeconds t = fromRational ((toRational t) / (toRational secondPicoseconds));
siSecondsToTime :: (Real a) => a -> DiffTime
siSecondsToTime t = fromInteger (round ((toRational t) * secondPicoseconds))
data UTCTime = UTCTime {
utctDay :: ModJulianDay,
utctDayTime :: DiffTime
}
newtype UTCDiffTime = MkUTCDiffTime Integer deriving (Eq,Ord,Num,Enum,Real,Integral)
instance Show UTCDiffTime where
show (MkUTCDiffTime t) = (show t) ++ "ps"
utcTimeToUTCSeconds :: (Fractional a) => UTCDiffTime -> a
utcTimeToUTCSeconds t = fromRational ((toRational t) / (toRational secondPicoseconds))
utcSecondsToUTCTime :: (Real a) => a -> UTCDiffTime
utcSecondsToUTCTime t = fromInteger (round ((toRational t) * secondPicoseconds))
posixDaySeconds :: (Num a) => a
posixDaySeconds = 86400
posixDayPicoseconds :: Integer
posixDayPicoseconds = posixDaySeconds * secondPicoseconds
unixEpochMJD :: ModJulianDay
unixEpochMJD = 40587
posixPicosecondsToUTCTime :: Integer -> UTCTime
posixPicosecondsToUTCTime i = let
(d,t) = divMod i posixDayPicoseconds
in UTCTime (d + unixEpochMJD) (fromInteger t)
utcTimeToPOSIXPicoseconds :: UTCTime -> Integer
utcTimeToPOSIXPicoseconds (UTCTime d t) =
((d - unixEpochMJD) * posixDayPicoseconds) + min posixDayPicoseconds (toInteger t)
addUTCTime :: UTCDiffTime -> UTCTime -> UTCTime
addUTCTime x t = posixPicosecondsToUTCTime ((toInteger x) + (utcTimeToPOSIXPicoseconds t))
diffUTCTime :: UTCTime -> UTCTime -> UTCDiffTime
diffUTCTime a b = fromInteger ((utcTimeToPOSIXPicoseconds a) - (utcTimeToPOSIXPicoseconds b))
-- Get current time
data CTimeval = MkCTimeval CLong CLong
ctimevalToPosixPicoseconds :: CTimeval -> Integer
ctimevalToPosixPicoseconds (MkCTimeval s mus) = ((fromIntegral s) * 1000000 + (fromIntegral mus)) * 1000000
instance Storable CTimeval where
sizeOf _ = (sizeOf (undefined :: CLong)) * 2
alignment _ = alignment (undefined :: CLong)
peek p = do
s <- peekElemOff (castPtr p) 0
mus <- peekElemOff (castPtr p) 1
return (MkCTimeval s mus)
poke p (MkCTimeval s mus) = do
pokeElemOff (castPtr p) 0 s
pokeElemOff (castPtr p) 1 mus
foreign import ccall unsafe "sys/time.h gettimeofday" gettimeofday :: Ptr CTimeval -> Ptr () -> IO CInt
getCurrentTime :: IO UTCTime
getCurrentTime = with (MkCTimeval 0 0) (\ptval -> do
result <- gettimeofday ptval nullPtr
if (result == 0)
then do
tval <- peek ptval
return (posixPicosecondsToUTCTime (ctimevalToPosixPicoseconds tval))
else fail ("error in gettimeofday: " ++ (show result))
)
More information about the Libraries
mailing list