time since the epoch

Simon Marlow simonmar@microsoft.com
Mon, 10 Feb 2003 11:13:24 -0000

>     SM> TimeDiff has a perfectly well-defined meaning for Eq=20
> and Ord: one
>     SM> TimeDiff is equal to another iff all the fields are=20
> respectively equal.
> Yes, sure, Eq and Ord are defined by=20
>   deriving (Eq, Ord, ...)
> but this does not make much sense if the representation for a
> particular duration is not unique. All I'm asking for is a unique
> representation for a duration and I do not see how you can do this
> using not uniquely defined terms like "month" and "year".

TimeDiff isn't a "duration", it's a way of specifying time offsets whose
duration depends on the base to which the offset is being added.  If we
only had constant-duration offsets, then there would be no way to say
"give me a ClockTime for this time next Wednesday".

The problem is really that all the different kinds of offset are lumped
into one type: there ought to be a TimeDiffSeconds, TimeDiffMonths, and
so on.  TimeDiffSeconds is a constant-duration offset, but
TimeDiffMonths isn't.  The problem with lumping them into one type is
that if multiple components are non-zero, you don't know in which order
to add them.

The TimeExts library gives you separate differences like these, BTW.

>     SM> This isn't a problem with the spec, I think.  A=20
> TimeDiff of "1 month" is
>     SM> precisely a difference, which, when added to a given=20
> ClockTime, produces
>     SM> a ClockTime which is one month later (with respect to=20
> some timezone,
>     SM> presumably UTC since it isn't specified otherwise). =20
> That is, January
>     SM> 12th 12:00 UTC becomes February 12th 12:00 UTC, and=20
> so on.  Adding one
>     SM> month to certain ClockTimes is meaningless: eg.=20
> adding one month to
>     SM> January 31st doesn't work.
> Unfortunately, with UTC, this goes on to make adding *anything* except
> seconds to certain ClockTimes (namely the instants of leap seconds,
> eg, what happens if you add 1 minute to 23:59:60 ? This is a perfectly
> legal UTC time on a day with a leap second) meaningless.

That's right, and here I'm not sure whether the right behaviour is to
raise an exception or to "roll over" to the next nearest date/time.  I
believe TimeExts does some kind of rolling over, but I'm not sure of the
exact semantics (George?).

> My take would
> be to look at an established standard for expressing time durations
> (eg, ISO8601) and just adhere to that (but not the POSIX standard,
> please!). Personally, I think that it is unacceptable to make
> something like addToClockTime a partial function.

Ok, ISO8601 seems to specify only constant-duration time intervals, but
allows them to be given in terms of years, months, days etc., where a
month is specified to be 30 days, it seems, and similar approximations
are made for the other units.  This seems very odd to me, but if that's
what you want...  (it's possible I'm misreading the standard, or maybe I
got hold of an old version though).

>     SM> At least, that's how I believe it is supposed to work.  GHC's
>     SM> implementation *is* completely wrong (which is=20
> perhaps where some of the
>     SM> confusion comes from), but the TimeExts library can=20
> be used instead of
>     SM> TimeDiffs.
> Well, so you agree that the behavior of the Time module is
> unspecified! Of course, I'm not blaming GHC's implementation which
> cannot be right under these circumstances.

Yes, it's unspecified, but I also think many people misinterpret it to
be more broken than it actually is.

>     SM> This is a perfectly reasonable definition of absolute=20
> time, we don't
>     SM> need to talk about TAI at all, except to define what=20
> the epoch means.
> Agreed! So what is epoch? Is it
> "Seconds since 00:00:00 on 1 Jan 1970 [TAI]"?

I guess so... GHC's implementation will be whatever the C library uses,
which I assume is the one you specified above (at least on a decent