
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.
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.
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 = 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 = 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. Invariants: t1 `addToClockTime` (t2 `diffClockTimes` t1) == t2 t1 `addToClockTime` noTimeDiff == t1 t1 `diffClockTimes` t1 == 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 = 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: - 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? -}