Commit | Line | Data |
1b289682 |
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 | mappping 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 |