summaryrefslogtreecommitdiff
path: root/Porting/timecheck2.c
blob: 06d4a66cff9de018ef3271c194ad4d41fa17ab8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* A little program to test the limits of your system's time functions
 * See Porting/README.y2038 for details
 */

#include <time.h>
#include <stdio.h>
#include <math.h>

time_t Time_Zero = 0;

/* Visual C++ 2008's difftime() can't do negative times */
double my_difftime(time_t left, time_t right) {
	double diff = (double)left - (double)right;
	return diff;
}

void check_date_max( struct tm * (*date_func)(const time_t *), char *func_name ) {
    struct tm *date;
    time_t time = 0;
    time_t last_time = 0;
    time_t time_change;
    int i;

    for (i = 0; i <= 63; i++) {
        date = (*date_func)(&time);

        /* date_func() broke or tm_year overflowed */
        if(date == NULL || date->tm_year < 69)
          break;

        last_time = time;
        time += time + 1;

        /* time_t overflowed */
        if( time < last_time )
            break;
    }

    /* Binary search for the exact failure point */
    time = last_time;
    time_change = last_time / 2;

    do {
        time += time_change;

        date = (*date_func)(&time);

        /* date_func() broke or tm_year overflowed or time_t overflowed */
        if(date == NULL || date->tm_year < 69 || time < last_time) {
            time = last_time;
            time_change = time_change / 2;
        }
        else {
            last_time = time;
        }
    } while(time_change > 0);

    printf("%20s max %.0f\n", func_name, my_difftime(last_time, Time_Zero));
}


void check_date_min( struct tm * (*date_func)(const time_t *), char *func_name ) {
    struct tm *date;
    time_t time = -1;
    time_t last_time = 0;
    time_t time_change;
    int i;

    for (i = 1; i <= 63; i++) {
        date = (*date_func)(&time);

        /* date_func() broke or tm_year underflowed */
        if(date == NULL || date->tm_year > 70)
            break;

        last_time = time;
        time += time;

        /* time_t underflowed */
        if( time > last_time )
            break;
    }

    /* Binary search for the exact failure point */
    time = last_time;
    time_change = last_time / 2;

    do {
        time += time_change;

        date = (*date_func)(&time);

        /* gmtime() broke or tm_year overflowed or time_t overflowed */
        if(date == NULL || date->tm_year > 70 || time > last_time) {
            time = last_time;
            time_change = time_change / 2;
        }
        else {
            last_time = time;
        }
    } while(time_change < 0);

    printf("%20s min %.0f\n", func_name, my_difftime(last_time, Time_Zero));
}


int main(void) {
    check_date_max(gmtime, "gmtime");
    check_date_max(localtime, "localtime");
    check_date_min(gmtime, "gmtime");
    check_date_min(localtime, "localtime");

    return 0;
}