Concerning Time.TimeDiff
Simon Marlow
simonmar@microsoft.com
Tue, 17 Jun 2003 13:53:48 +0100
=20
> On Mon, Jun 16, 2003 at 04:42:53PM +0100, Graham Klyne wrote:
> > ... I think it's quite usual for people and applications to deal
> > with a day as a consistent time interval without concern for
> > possible leap seconds, so dealing with days as intervals of 24*60*60
> > seconds is useful for a majority of applications that deal with such
> > intervals.
>=20
> What about the fact that days are not actually intervals of 24*60*60
> seconds (as I'm sure you know)? Most applications don't care, but
> it's crucial to give correct and unsurprising results.
>=20
> I'm worried that the complexity to deal with leap seconds will end up
> being just as complicated as the complexity to deal with more general
> TimeDiff's as in the current library, in which case it may be
> necessary to bite the bullet and specify the behaviour of TimeDiffs
> completely and accurately.
Agreed, this discussion tends to get rather vague at times, so I'd like
to put it on a more concrete footing if I may. I've put together rough
suggestion for a starting point for a replacement System.Time, appended
below.
Please comment!
Cheers,
Simon
------------------------------------------------------------------------
----
-- * ClockTime
-- | A representation of absolute time
data ClockTime
=3D ClockTime { ctSeconds :: Integer,
ctPicoseconds :: Integer }
deriving (Eq, Ord, Show, Read)
-- | returns the current absolute time
getClockTime :: IO ClockTime
-- | Difference between two 'ClockTime's
data TimeDiff
=3D TimeDiff { tdSeconds :: Integer,
tdPicoseconds :: Integer }
deriving (Eq, Ord, Show, Read)
-- | An empty 'TimeDiff'
noTimeDiff :: TimeDiff
-- | Returns the difference between two 'ClockTime's
diffClockTimes :: ClockTime -> ClockTime -> TimeDiff
-- | Adds a 'TimeDiff' to a 'ClockTime'
addToClockTime :: ClockTime -> TimeDiff -> ClockTime
{-
Rationale:
- TimeDiff is now an absolute measure of time period.
=20
Invariants:
t1 `addToClockTime` (t2 `diffClockTimes` t1) =3D=3D t2
t1 `addToClockTime` noTimeDiff =3D=3D t1
t1 `diffClockTimes` t1 =3D=3D noTimeDiff
TODO:
- This representation of TimeDiff is maybe not the best.
Two other possibilities: use just picoseconds, or
have the type be abstract with a way to extract
picoseconds.
- If we keep the seconds/picoseconds representation,
should we specify that the TimeDiff returned by
diffClockTimes is normalised? Should we provide
a way to normalise a TimeDiff?
-}
------------------------------------------------------------------------
----
-- * CalendarTime
data CalendarTime=20
=3D CalendarTime {
ctYear :: Int,
ctMonth :: Month,
ctDay :: Int,
ctHour :: Int,
ctMin :: Int,
ctSec :: Int,
ctPicosec :: Integer,
ctTZ :: Timezone
}
deriving (Eq, Ord, Read, Show)
data Timezone -- abstract
-- | Make a 'Timezone'
-- TODO: do we need to specify daylight savings time too?
timezoneFromOffset :: Int -> Timezone
timezoneFromName :: String -> Timezone
timezoneOffset :: Timezone -> Int
timezoneName :: Timezone -> String
-- | Convert a 'ClockTime' to a 'CalendarTime' in the current timezone
clockTimeToCalendarTime :: ClockTime -> IO CalendarTime
-- | Convert a 'ClockTime' to a 'CalendarTime' in UTC
clockTimeToUTCTime :: ClockTime -> CalendarTime
-- | Convert a 'CalendarTime' to a 'ClockTime'
-- TODO: can this raise an exception if the CalendarTime does not
-- represent a valid time? Or should it return Maybe ClockTime?
calendarTimeToClockTime :: CalendarTime -> ClockTime
-- OPTIONAL: these are hard to implement, and require
-- careful specification (see rationale below):
addPicoseconds :: CalendarTime -> Integer -> CalendarTime
addSeconds :: CalendarTime -> Integer -> CalendarTime
addMinutes :: CalendarTime -> Integer -> CalendarTime
addDays :: CalendarTime -> Integer -> CalendarTime
addWeeks :: CalendarTime -> Integer -> CalendarTime
addMonths :: CalendarTime -> Integer -> CalendarTime
addYears :: CalendarTime -> Integer -> CalendarTime
{-
Rationale:=20
=20
- Adding "irregular" time differences should be done on
CalendarTimes, because these operations depend on the timezone.
- Need to define the meaning when the offset doesn't exist.
eg. adding a day at the end of the month clearly rolls over
into the next month. But what about adding a month to
January 31st?
-}