| 1 | The y2038 implementation for perl |
| 2 | =========================================================================== |
| 3 | This is an implementation of POSIX time.h which solves the year 2038 bug on |
| 4 | systems where time_t is only 32 bits. It is implemented in bog-standard |
| 5 | ANSI C. The latest version can be found at http://y2038.googlecode.com/ |
| 6 | |
| 7 | It makes use of the system's native 32 bit functions to perform time zone |
| 8 | and daylight savings time calculations and thus does *not* need to ship its |
| 9 | own time zone table. |
| 10 | |
| 11 | time64.h currently implements three public functions, localtime64_r(), |
| 12 | gmtime64_r() and timegm64(). They are implementations of localtime_r(), |
| 13 | gmtime_r() and timegm64(). |
| 14 | |
| 15 | To install, simply copy time64.c and time64.h into your project and make |
| 16 | use of the functions. |
| 17 | |
| 18 | To test, run "make test". You must have Perl, prove (which comes with a |
| 19 | recent version of the Test::Harness Perl module) and bzdiff installed to |
| 20 | run the full test suite. It will do a number of unit tests, plus test |
| 21 | against a large table of known good values in different time zones. |
| 22 | |
| 23 | Limitations, Issues, etc... |
| 24 | --------------------------- |
| 25 | localtime64_r() gets its time zone and daylight savings time information by |
| 26 | mapping the future year back to a similar one between 2010 and 2037, safe |
| 27 | for localtime_r(). The calculations are accurate according to current time |
| 28 | zone and daylight savings information, but may become inaccurate if a |
| 29 | change is made that takes place after 2010. |
| 30 | |
| 31 | Future versions will probe for a 64 bit safe system localtime_r() and |
| 32 | gmtime_r() and use that. |
| 33 | |
| 34 | The maximum date is still limited by your tm struct. Most 32 bit systems |
| 35 | use a signed integer tm_year which means the practical upper limit is the |
| 36 | year 2147483647 which is somewhere around 2**54. You can use a 64 bit |
| 37 | clean tm struct by setting USE_TM64 in time64.h |
| 38 | |
| 39 | Portability |
| 40 | ----------- |
| 41 | I would like to add some configuration detection stuff in the future, but |
| 42 | for now all I can do is document the assumptions... |
| 43 | |
| 44 | This code assumes that long longs are 64 bit integers which is technically |
| 45 | in violation of the C standard. This can be changed in time64.h by |
| 46 | changing the Time64_T and Int64 typedefs. |
| 47 | |
| 48 | There are a number of configuration options in time64.h. |
| 49 | |
| 50 | Configure variables |
| 51 | ------------------- |
| 52 | Configure probes for the maximum and minimum values that gmtime () and |
| 53 | localtime () accept on the local system. Configure however is only used on |
| 54 | unix-like systems. For windows and VMS these values are hard-coded. You can |
| 55 | use timecheck.c in the Porting directory to check those values yourself, |
| 56 | using the same technique that is used in Configure based on bit-shifting: |
| 57 | |
| 58 | $ cd perl/Porting |
| 59 | $ cc -O -o timecheck timecheck.c |
| 60 | $ ./timecheck |
| 61 | ====================== |
| 62 | Sizeof time_t = 8 |
| 63 | gmtime () boundaries: |
| 64 | 8: 0x00f0c2ab7c54a97f: 2147485547-12-31 23:59:59 |
| 65 | 8: -0x0000000e79747c00: 0-01-01 00:00:00 |
| 66 | localtime () boundaries: |
| 67 | 8: 0x00f0c2ab7c549b6f: 2147485547-12-31 23:59:59 |
| 68 | 8: -0x0000000e79748094: 0-01-01 00:00:00 |
| 69 | Configure variables: |
| 70 | sGMTIME_max='67768036191676799' |
| 71 | sGMTIME_min='-62167219200' |
| 72 | sLOCALTIME_max='67768036191673199' |
| 73 | sLOCALTIME_min='-62167220372' |
| 74 | |
| 75 | In the rare case that your system uses a double for time_t, you can use the |
| 76 | alternate approach to test for these values: |
| 77 | |
| 78 | $ cd perl/Porting |
| 79 | $ cc -O -o timecheck2{,.c} |
| 80 | $ ./timecheck2 |
| 81 | gmtime max 67768036191676800 |
| 82 | localtime max 67768036191673200 |
| 83 | gmtime min -67768040609740800 |
| 84 | localtime min -67768040609741968 |