The y2038 TPF grant has shipped all its deliverables and I now consider it
to be complete. While the original estimate of August 18th was blown
through, writing portable C code is a bitch, I'm happy the 2038
problem has been fixed with time to spare. All that remains now is
for the patches to be integrated. (Rafael is not integrating any
bleadperl branches until after 5.8.9 is released.)
Perl now has a portable means to calculate time in a range of +/- 142
million years. It also has another C programmer to help hack the perl
Why 142 million years and not 292 billion as is the true range of 64
bit time? Well, it turns out that Perl has access to a portable 64
bit integer, it has no accompanying portable 64 bit integer scalar
type. Because all arguments passed into a Perl function are scalars,
I had to make due with double precision floating point numbers. These
are accurate out to about 2**52 after which accuracy degrades. 2**52
is about 142 million years.
Since the code is a drop-in replacement for the time.h
fucntions, and not specific to Perl, any project written in C can take
advantage. For example, in order to allow users access to the code
without patching Perl, Time::Local::Extended
has been patched to include this code. The author should release a
new version soon. The patch is available.
print scalar gmtime(2**52);
Sat Dec 6 03:48:16 142715360
I gave a presentation at PPW covering the problem, the usual proposed solutions which aren't, and the solution which y2038 takes.
This does not mean the end of the y2038 project. Ideally the entirety
of time.h will be reimplemented. timegm() has already been done (not
in the standard, but too useful to ignore), mktime() (ie. timelocal())
is next on the list and the wildly complicated strftime()
has been started. 2038 bugs have been identified in Ruby and
Python, they are the project's next targets.
Help is greatly appreciated.
Here is a breakdown of the project's deliverables and their conclusions.
64 bit localtime/gmtime
* Write C versions of localtime() and gmtime() which work with
times beyond 2038 regardless of the limits of the system C
Done. The y2038 project solves this problem.
* Test for negative times.
* If it can be made to work, make it work.
* If not, provide a proper error message.
Done and it works. It also provides a proper errno and error message on overflow or failure.
* Fix any performance issues so the process is O(1) (currently
parts of the code are O(n)).
Using a little clever math, it is now O(1). The process for
calculating a date does not get slower as the time increases. This
sped up the time to calculate distant dates by about 10000x.
* Make gmtime64_r() properly report an EOVERFLOW error when the
year is too large to be held by tm.tm_year.
Done. Also provided an option to use an alternative (but
incompatible) tm struct with a bigger tm_year to punch through the
y2billion bug, which Perl uses.
* Fix any portability issues.
The code is written in ANSI C89 and conforms to the POSIX spec.
Tested on most Unixen and Windows. A configuration header allows tweaking.
Provide a patch for Perl which...
* Adapts these libraries for perl and change pp_gmtime() and
pp_localtime() to use them.
Done as a bleadperl branch.
* Add additional tests to localtime(), gmtime() and related core
modules (Time::Local) for beyond 2038.
Done. Time::Local, Time::gmtime and Time::localtime were fixed and tested.
* Ensure cross-platform compatibility including any necessary Configure probing.
Done. No additional probing was necessary.
* Use the existing system libraries should they be 64 bit clean.
Done with Merijn's help to add probes to Configure.
* Works with bleadperl.
Done. Rafael is holding off integrating the branch until after 5.8.9
* Works with 5.10.
Done, no additional work is necessary. It can be included as part of
the normal maint-perl process and hopefully included in 5.10.1.
* BONUS Backport to 5.8.
Done, no backporting is needed, but it is unlikely (and inadvisable)
to be included in 5.8.9 this late in the process. 5.8 users can use