1*43003dfeSmillert /* A little program to test the limits of your system's time functions
2*43003dfeSmillert * See Porting/README.y2038 for details
3*43003dfeSmillert */
4*43003dfeSmillert
5*43003dfeSmillert #include <time.h>
6*43003dfeSmillert #include <stdio.h>
7*43003dfeSmillert #include <math.h>
8*43003dfeSmillert
9*43003dfeSmillert time_t Time_Zero = 0;
10*43003dfeSmillert
11*43003dfeSmillert /* Visual C++ 2008's difftime() can't do negative times */
my_difftime(time_t left,time_t right)12*43003dfeSmillert double my_difftime(time_t left, time_t right) {
13*43003dfeSmillert double diff = (double)left - (double)right;
14*43003dfeSmillert return diff;
15*43003dfeSmillert }
16*43003dfeSmillert
check_date_max(struct tm * (* date_func)(const time_t *),char * func_name)17*43003dfeSmillert void check_date_max( struct tm * (*date_func)(const time_t *), char *func_name ) {
18*43003dfeSmillert struct tm *date;
19*43003dfeSmillert time_t time = 0;
20*43003dfeSmillert time_t last_time = 0;
21*43003dfeSmillert time_t time_change;
22*43003dfeSmillert int i;
23*43003dfeSmillert
24*43003dfeSmillert for (i = 0; i <= 63; i++) {
25*43003dfeSmillert date = (*date_func)(&time);
26*43003dfeSmillert
27*43003dfeSmillert /* date_func() broke or tm_year overflowed */
28*43003dfeSmillert if(date == NULL || date->tm_year < 69)
29*43003dfeSmillert break;
30*43003dfeSmillert
31*43003dfeSmillert last_time = time;
32*43003dfeSmillert time += time + 1;
33*43003dfeSmillert
34*43003dfeSmillert /* time_t overflowed */
35*43003dfeSmillert if( time < last_time )
36*43003dfeSmillert break;
37*43003dfeSmillert }
38*43003dfeSmillert
39*43003dfeSmillert /* Binary search for the exact failure point */
40*43003dfeSmillert time = last_time;
41*43003dfeSmillert time_change = last_time / 2;
42*43003dfeSmillert
43*43003dfeSmillert do {
44*43003dfeSmillert time += time_change;
45*43003dfeSmillert
46*43003dfeSmillert date = (*date_func)(&time);
47*43003dfeSmillert
48*43003dfeSmillert /* date_func() broke or tm_year overflowed or time_t overflowed */
49*43003dfeSmillert if(date == NULL || date->tm_year < 69 || time < last_time) {
50*43003dfeSmillert time = last_time;
51*43003dfeSmillert time_change = time_change / 2;
52*43003dfeSmillert }
53*43003dfeSmillert else {
54*43003dfeSmillert last_time = time;
55*43003dfeSmillert }
56*43003dfeSmillert } while(time_change > 0);
57*43003dfeSmillert
58*43003dfeSmillert printf("%20s max %.0f\n", func_name, my_difftime(last_time, Time_Zero));
59*43003dfeSmillert }
60*43003dfeSmillert
61*43003dfeSmillert
check_date_min(struct tm * (* date_func)(const time_t *),char * func_name)62*43003dfeSmillert void check_date_min( struct tm * (*date_func)(const time_t *), char *func_name ) {
63*43003dfeSmillert struct tm *date;
64*43003dfeSmillert time_t time = -1;
65*43003dfeSmillert time_t last_time = 0;
66*43003dfeSmillert time_t time_change;
67*43003dfeSmillert int i;
68*43003dfeSmillert
69*43003dfeSmillert for (i = 1; i <= 63; i++) {
70*43003dfeSmillert date = (*date_func)(&time);
71*43003dfeSmillert
72*43003dfeSmillert /* date_func() broke or tm_year underflowed */
73*43003dfeSmillert if(date == NULL || date->tm_year > 70)
74*43003dfeSmillert break;
75*43003dfeSmillert
76*43003dfeSmillert last_time = time;
77*43003dfeSmillert time += time;
78*43003dfeSmillert
79*43003dfeSmillert /* time_t underflowed */
80*43003dfeSmillert if( time > last_time )
81*43003dfeSmillert break;
82*43003dfeSmillert }
83*43003dfeSmillert
84*43003dfeSmillert /* Binary search for the exact failure point */
85*43003dfeSmillert time = last_time;
86*43003dfeSmillert time_change = last_time / 2;
87*43003dfeSmillert
88*43003dfeSmillert do {
89*43003dfeSmillert time += time_change;
90*43003dfeSmillert
91*43003dfeSmillert date = (*date_func)(&time);
92*43003dfeSmillert
93*43003dfeSmillert /* gmtime() broke or tm_year overflowed or time_t overflowed */
94*43003dfeSmillert if(date == NULL || date->tm_year > 70 || time > last_time) {
95*43003dfeSmillert time = last_time;
96*43003dfeSmillert time_change = time_change / 2;
97*43003dfeSmillert }
98*43003dfeSmillert else {
99*43003dfeSmillert last_time = time;
100*43003dfeSmillert }
101*43003dfeSmillert } while(time_change < 0);
102*43003dfeSmillert
103*43003dfeSmillert printf("%20s min %.0f\n", func_name, my_difftime(last_time, Time_Zero));
104*43003dfeSmillert }
105*43003dfeSmillert
106*43003dfeSmillert
main(void)107*43003dfeSmillert int main(void) {
108*43003dfeSmillert check_date_max(gmtime, "gmtime");
109*43003dfeSmillert check_date_max(localtime, "localtime");
110*43003dfeSmillert check_date_min(gmtime, "gmtime");
111*43003dfeSmillert check_date_min(localtime, "localtime");
112*43003dfeSmillert
113*43003dfeSmillert return 0;
114*43003dfeSmillert }
115