xref: /openbsd-src/gnu/usr.bin/perl/Porting/timecheck2.c (revision 256a93a44f36679bee503f12e49566c2183f6181)
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