They said it couldn't be done. They said it SHOULDN'T be done! But I have here a working 64 bit localtime_r() on a machine with just 32 bits of time_t. Time zones, daylight savings time... it all works.
$ ./miniperl -wle 'print scalar localtime(2**35)'
Mon Oct 25 20:46:08 3058
Perl will be Y2038 safe. And yes, I'm going to get it backported to 5.10.
The underlying C functions are solid, but I just sort of rammed them down perl's throat because it's 5am. Here's
the patch for the intrepid.
The underlying
C implementation is a heavily modified version of the code from
2038bug.com written by Paul Sheer. He came up with the same basic algorithm I did:
1) Write a 64 bit clean gmtime(), that's a SMOP and Paul did that.
2) Run your time through this new gmtime_64().
3) Change the year to a year between 2012 and 2037.
4) Run it through the 32 bit system localtime() to get time zone stuff.
5) Move the year back to the original.
The trick is using a 32 bit safe year that has the same properties as the real year. This means same leap year status and same calendar layout. Had to do some tricky Gregorian calendar math aided by Graham, Nick and Abigail who realized there's a 28 year cycle within the larger 400 year Gregorian cycle and Mark Mielke who provided a big table of 64 bit localtime() results to test against. There's also some edge cases around New Year's, but they're all taken care of.
This approach will break when daylight savings time changes, but I'd rather be off by an hour than 137 years. The full Perl patch will always prefer the system's 64 bit localtime() if one is available. As more machines upgrade time_t this hack will be used less.
The nice part is this code isn't specific to Perl and can be used to fix up any other C-based Unix program.
Another free 64 bit time library
charlieb on 2008-02-08T15:26:26
> The underlying C implementation is a heavily
> modified version of the code from 2038bug.com
> written by Paul Sheer.
Did you perchance look at Dan Bernstein's libtai?
http://cr.yp.to/libtai.htmlI notice that 2038bug.com's code comes with license which appears to include an advertising clause. OTOH djb's code is public domain, and therefore unambiguously compatible with the GPL. Its use is also recommended by Paul Sheer:
http://2038bug.com/developers.html
Re:Another free 64 bit time library
schwern on 2008-02-09T00:02:36
I glanced at libtai but on its TODO list is "support time zones" which puts it right out for localtime(). Supporting time zones and DST is a non-trivial task and I wish very much for Perl to have to ship time zone tables. Also libtai lacks a gmtime() and localtime() implementation and, as I'm not a very good C programmer, would probably require quite a bit more adaptation than I can handle.
The 2038bug.com implementation attracted me because it is a 64 bit drop in replacement for 32 bit gmtime() and localtime() which is exactly what I need and requires the least adaptation. The licensing issue is a worry. Since he's obviously interested in educating people and fixing the problem, I hope that the author will be amenable to dropping the advertising clause and smoothing out any licensing issues. However, I have not heard back and it's possible the mail isn't getting through. Hmm, maybe I'll just call him.
I came up with the algorithm before seeing Paul's implementation, and significantly improved on it. In the worst case I will just have to reimplement the code myself. Either way, it'll get done.