2 * mktime - convert local time into calendar time
4 /* $Id: mktime.c,v 1.6 1994/06/24 11:58:20 ceriel Exp $ */
10 /* The code assumes that unsigned long can be converted to time_t.
11 * A time_t should not be wider than unsigned long, since this would mean
12 * that the check for overflow at the end could fail.
15 mktime(register struct tm *timep)
17 register long day, year;
20 register unsigned long seconds;
24 timep->tm_min += timep->tm_sec / 60;
26 if (timep->tm_sec < 0) {
30 timep->tm_hour += timep->tm_min / 60;
31 timep->tm_min = timep->tm_min % 60;
32 if (timep->tm_min < 0) {
36 day = timep->tm_hour / 24;
37 timep->tm_hour= timep->tm_hour % 24;
38 if (timep->tm_hour < 0) {
42 timep->tm_year += timep->tm_mon / 12;
44 if (timep->tm_mon < 0) {
48 day += (timep->tm_mday - 1);
50 day += YEARSIZE(YEAR0 + timep->tm_year - 1);
53 while (day >= YEARSIZE(YEAR0 + timep->tm_year)) {
54 day -= YEARSIZE(YEAR0 + timep->tm_year);
57 while (day >= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]) {
58 day -= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
59 if (++(timep->tm_mon) == 12) {
64 timep->tm_mday = day + 1;
65 _tzset(); /* set timezone and dst info */
67 if (timep->tm_year < year - YEAR0) return (time_t)-1;
69 day = 0; /* means days since day 0 now */
72 /* Assume that when day becomes negative, there will certainly
73 * be overflow on seconds.
74 * The check for overflow needs not to be done for leapyears
76 * The code only works when year (1970) is not a leapyear.
79 #error EPOCH_YR != 1970
81 tm_year = timep->tm_year + YEAR0;
83 if (LONG_MAX / 365 < tm_year - year) overflow++;
84 day = (tm_year - year) * 365;
85 if (LONG_MAX - day < (tm_year - year) / 4 + 1) overflow++;
86 day += (tm_year - year) / 4
87 + ((tm_year % 4) && tm_year % 4 < year % 4);
88 day -= (tm_year - year) / 100
89 + ((tm_year % 100) && tm_year % 100 < year % 100);
90 day += (tm_year - year) / 400
91 + ((tm_year % 400) && tm_year % 400 < year % 400);
94 while (month < timep->tm_mon) {
95 yday += _ytab[LEAPYEAR(tm_year)][month];
98 yday += (timep->tm_mday - 1);
99 if (day + yday < 0) overflow++;
102 timep->tm_yday = yday;
103 timep->tm_wday = (day + 4) % 7; /* day 0 was thursday (4) */
105 seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec;
107 if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
108 seconds += day * SECS_DAY;
110 /* Now adjust according to timezone and daylight saving time */
112 if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
113 || ((_timezone < 0) && (seconds < -_timezone)))
115 seconds += _timezone;
117 if (timep->tm_isdst < 0)
118 dst = _dstget(timep);
119 else if (timep->tm_isdst)
123 if (dst > seconds) overflow++; /* dst is always non-negative */
126 if (overflow) return (time_t)-1;
128 if ((time_t)seconds != seconds) return (time_t)-1;
129 return (time_t)seconds;