# 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.

Cheers,
Simon

------------------------------------------------------------------------
----
-- * ClockTime

-- | A representation of absolute time
data ClockTime
=3D ClockTime { ctSeconds :: Integer,
ctPicoseconds :: Integer }

-- | returns the current absolute time
getClockTime :: IO ClockTime

-- | Difference between two 'ClockTime's
data TimeDiff
=3D TimeDiff { tdSeconds :: Integer,
tdPicoseconds :: Integer }

-- | 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 `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
}

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