Re: Algorithm to exploit 32 bit time functions to do time zone calculations
Michael G Schwern <[email protected]> Wed, 17 Sep 2008 16:00:03 -0700
| Newsgroups | gmane.os.miros.general,gmane.comp.lib.libtai |
|---|---|
| Message-ID | <[email protected]> |
It's very nice to have someone else to bounce this all off of.
Thorsten Glaser wrote:
>> Maybe you can shed some light on this problem, what to do about year 0=
?
>=20
> I actually haven=E2=80=99t thought about year 0, since localtime/mktime=
do that,
> and mjd2tm and tm2mjd from DJB code. I think it=E2=80=99s illegal, isn=E2=
=80=99t it?
Illegal according to who?
C99 and POSIX 1003.1 define tm.tm_year as a signed int with a range of "y=
ears
since 1900" which makes a negative year perfectly "legal".
>> Right now the only limit I have on dates is the limit of what Time64_T
>> can store. Does it make sense to stop at 0?
>=20
> No, it makes sense to not stop. The thing is, mktime() and gmtime()
> *must* have full round-trip capabilities (GNU autoconf checks for that
> before it uses it), which is why, for example, my tai64_t data type doe=
s
> not exactly store what DJB calls a TAI timestamp. There is a small wrap=
-
> around at about 0x8000000000000000 (time_t) / 0xC000000000000000 (tai64=
_t)
> of 10 (I think, due to the leap seconds) seconds. So, for whatever valu=
e
> you have in whatever representation (time_t, tai64_t, struct tm), all o=
f
> these must have full round-trip capabilities (with the possible excepti=
on
> that struct tm with a 64-bit year can go beyond the 64-bit time_t value
> scale, but then, a 32-bit year does the same for a 32-bit time_t, so th=
is
> is no change).
I'm a little lost. Could you give an example?
>> localtime()... well, localtime() gets absurd real fast. Gregorian/Jul=
ian
>> calendar shifts.
>=20
> Mh. Maybe a struct tm.tm_year is always Gregorian? Have a look, while a=
t
> it, at the "%J" strftime modifier (and, especially, my implementation o=
f
> it, using the tm2mjd function). This will get you Julian days, but noth=
ing
> in Unix has them split off into a calendar time kind of structure.
C99 says "Many functions [in time.h] deal with a calendar time that repre=
sents
the current date (according to the Gregorian calendar) and time."
But then goes on to say:
"Some functions deal with local time, which is the calendar time expresse=
d for
some specific time zone, and with Daylight Saving Time, which is a tempor=
ary
change in the algorithm for determining local time. The local time zone a=
nd
Daylight Saving Time are implementation-defined."
POSIX 1003.1 does not appear to discuss the matter.
It seems clear to me that gmt is always Gregorian but not so clear what
happens with localtime().
I wonder how a Chinese locale deals with this. They switched from Julian=
to
Gregorian after 1901, so it should show up in any Chinese localtime()
implementation. Also Russia and much of Eastern Europe.
> So I think you don=E2=80=99t need to worry about THAT. That=E2=80=99s a=
pplication layer
> to do, similar to hebrew, muslim, asian etc. calendars. And at that, it
> REALLY gets absurd (cf. http://blogs.msdn.com/michkap/default.aspx), bu=
t
> that=E2=80=99s not the (our) OS=E2=80=99 job to worry about.
>=20
> However, for =E2=80=9Cabsurd=E2=80=9D years, the OS=E2=80=99 own functi=
ons might go crazy. Too
> bad we can=E2=80=99t access the OS=E2=80=99 own time zone table (I need=
to get the info
> for leap seconds out of it, for example).
I'm just glad that ctime() isn't locale sensitive. Oi, what a mess that =
would be.
PS I just found this gem in the mktime() standard:
the original values [in the tm struct] of the other components are no=
t
restricted to the ranges described in <time.h>.
which the BSD time.h man page expands out to:
The original values of the tm_wday and tm_yday components of the str=
uc-
ture are ignored, and the original values of the other components ar=
e not
restricted to their normal ranges, and will be normalized if needed.=
For
example, October 40 is changed into November 9, a tm_hour of -1 mean=
s 1
hour before midnight, tm_mday of 0 means the day preceding the curre=
nt
month, and tm_mon of -2 means 2 months before January of tm_year. (=
A
positive or zero value for tm_isdst causes mktime() to presume initi=
ally
that summer time (for example, Daylight Saving Time) is or is not in
effect for the specified time, respectively. A negative value for
tm_isdst causes the mktime() function to attempt to divine whether s=
ummer
time is in effect for the specified time. The tm_isdst and tm_gmtof=
f
members are forced to zero by timegm().)
On successful completion, the values of the tm_wday and tm_yday comp=
o-
nents of the structure are set appropriately, and the other componen=
ts
are set to represent the specified calendar time, but with their val=
ues
forced to their normal ranges; the final value of tm_mday is not set
until tm_mon and tm_year are determined. The mktime() function retu=
rns
the specified calendar time; if the calendar time cannot be represen=
ted,
it returns -1;
This is something I haven't tested for yet.
PPS How does one get the damn qsecretary program to stop making you conf=
irm
every email to this list? I'm already subscribed.
--=20
The interface should be as clean as newly fallen snow and its behavior
as explicit as Japanese eel porn.