Re: Algorithm to exploit 32 bit time functions to do time zone calculations
Michael G Schwern <[email protected]> Tue, 16 Sep 2008 18:34:34 -0700
| Newsgroups | gmane.os.miros.general,gmane.comp.lib.libtai |
|---|---|
| Message-ID | <[email protected]> |
Thorsten Glaser wrote:
> Michael G Schwern dixit:
>=20
>> You: "Your shit is boring."
>=20
> More like "has been done already". Sorry.
Apology accepted. Sorry things got off to a bad start.
>> If I understand correctly, that's an entire operating system.
>=20
> Yes, but the gist is, that there is code which uses a certain 64-bit ty=
pe,
> called time_t, but you could of course just use int64_t instead, which =
does
> the job quite fine. (Not even a binary change in the time zone data for=
mat.)
Is this approach portable outside BSD?
My main targets are Perl, Python and Ruby which have to be absurdly porta=
ble.
As I understand it, almost nothing about the time zone database is porta=
ble.
For example, I could not expect tzload() to work on all operating system=
s. I
would have to ship my own, which I do not want to do, or write time zone =
code
for each operating system, which I also do not want to do.
I could be wrong, I'm really a Perl programmer who plays a C programmer o=
n TV.
That said, I do recognize that a lot of my work will boil down to just do=
ing a
search and replace for "time_t" with "Time64_T" and "int" with "Int64_T".=
For
example, asctime(). It's really the trick to get localtime() working tha=
t's
important. I intend to loot BSD code for everything I can, right now I'm
mostly using it mostly as a reference. In fact, I'm considering changing=
from
MIT to BSD license to make that even easier.
Speaking of asctime(), I think this is a y2**31 bug in asctime3:
char year[INT_STRLEN_MAXIMUM(int) + 2];
Since 64 bit time can go well above the year 2 billion, years must be sto=
red
as 64 bit ints. If int is 32 bits, the code above is only allocating eno=
ugh
room for 2**31 years.
I've been testing a lot of 64 bit system's time handling lately and that'=
s a
common mistake, 32 bit years. Though not as bad as HP/UX's Y10k bug.
Oh, don't forget to make tm.tm_year 64 bit!
>> Also you might want to have a look at the tests in y2038.
>=20
> This is actually a good idea. Compiling (I think it was) CVS with the
> changes was a good test too, as the configure script =E2=80=9Cchecks wh=
ether
> mktime() works=E2=80=9D. To get that right (over all of the 64 bit) was=
hard.
> You have to think about very many border cases=E2=80=A6 in the end, I j=
ust
> ensured the round-trip via tai64_t was right, not neccessarily the
> tai64_t representation itself.
To test timegm() I just round tripped it through gmtime() at various
interesting times.
time =3D 60*60*16;
gmtime64_r(&time, &date);
is_Int64( timegm64(&date), time, "timegm64(60*60*16)" );
An mktime() test should work the same way, round trip through localtime()=
, no?
You can see the test here (and I really should put all that repeated code=
into
its own test function).
http://code.google.com/p/y2038/source/browse/trunk/t/timegm.c
Anyhow, if you're interested in the Test Anything Protocol, a really simp=
le
implementation is here:
http://code.google.com/p/y2038/source/browse/trunk/tap.c
And the code to run them is here in the "tap_tests" target.
http://code.google.com/p/y2038/source/browse/trunk/Makefile
More info about TAP can be found here:
http://testanything.org/wiki/index.php/Main_Page
The MyTAP library used by MySQL might be relevant (and cleaner than mine)
http://www.kindahl.net/mytap/doc/
And MySQL's documentation on that.
http://dev.mysql.com/doc/mysqltest/en/unit-test.html
--=20
The mind is a terrible thing,
and it must be stopped.