. use library function to parse memory string
[minix3.git] / lib / ansi / mktime.c
blobfd95870440d80f67c6443693ee3cf54e2da7c3dc
1 /*
2 * mktime - convert local time into calendar time
3 */
4 /* $Header$ */
6 /* Michael A. Temari <temari@ix.netcom.com> 03/01/96 */
7 /* - fixed bug is structure fixup code */
9 #include <time.h>
10 #include <limits.h>
11 #include "loc_time.h"
13 /* The code assumes that unsigned long can be converted to time_t.
14 * A time_t should not be wider than unsigned long, since this would mean
15 * that the check for overflow at the end could fail.
17 time_t
18 mktime(register struct tm *timep)
20 register long day, year;
21 register int tm_year;
22 int yday, month;
23 register unsigned long seconds;
24 int overflow;
25 unsigned dst;
27 timep->tm_min += timep->tm_sec / 60;
28 timep->tm_sec %= 60;
29 if (timep->tm_sec < 0) {
30 timep->tm_sec += 60;
31 timep->tm_min--;
33 timep->tm_hour += timep->tm_min / 60;
34 timep->tm_min = timep->tm_min % 60;
35 if (timep->tm_min < 0) {
36 timep->tm_min += 60;
37 timep->tm_hour--;
39 day = timep->tm_hour / 24;
40 timep->tm_hour= timep->tm_hour % 24;
41 if (timep->tm_hour < 0) {
42 timep->tm_hour += 24;
43 day--;
45 timep->tm_year += timep->tm_mon / 12;
46 timep->tm_mon %= 12;
47 if (timep->tm_mon < 0) {
48 timep->tm_mon += 12;
49 timep->tm_year--;
51 day += (timep->tm_mday - 1);
52 while (day < 0) {
53 if(--timep->tm_mon < 0) {
54 timep->tm_year--;
55 timep->tm_mon = 11;
57 day += _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
59 while (day >= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]) {
60 day -= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
61 if (++(timep->tm_mon) == 12) {
62 timep->tm_mon = 0;
63 timep->tm_year++;
66 timep->tm_mday = day + 1;
67 _tzset(); /* set timezone and dst info */
68 year = EPOCH_YR;
69 if (timep->tm_year < year - YEAR0) return (time_t)-1;
70 seconds = 0;
71 day = 0; /* means days since day 0 now */
72 overflow = 0;
74 /* Assume that when day becomes negative, there will certainly
75 * be overflow on seconds.
76 * The check for overflow needs not to be done for leapyears
77 * divisible by 400.
78 * The code only works when year (1970) is not a leapyear.
80 #if EPOCH_YR != 1970
81 #error EPOCH_YR != 1970
82 #endif
83 tm_year = timep->tm_year + YEAR0;
85 if (LONG_MAX / 365 < tm_year - year) overflow++;
86 day = (tm_year - year) * 365;
87 if (LONG_MAX - day < (tm_year - year) / 4 + 1) overflow++;
88 day += (tm_year - year) / 4
89 + ((tm_year % 4) && tm_year % 4 < year % 4);
90 day -= (tm_year - year) / 100
91 + ((tm_year % 100) && tm_year % 100 < year % 100);
92 day += (tm_year - year) / 400
93 + ((tm_year % 400) && tm_year % 400 < year % 400);
95 yday = month = 0;
96 while (month < timep->tm_mon) {
97 yday += _ytab[LEAPYEAR(tm_year)][month];
98 month++;
100 yday += (timep->tm_mday - 1);
101 if (day + yday < 0) overflow++;
102 day += yday;
104 timep->tm_yday = yday;
105 timep->tm_wday = (day + 4) % 7; /* day 0 was thursday (4) */
107 seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec;
109 if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
110 seconds += day * SECS_DAY;
112 /* Now adjust according to timezone and daylight saving time */
114 if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
115 || ((_timezone < 0) && (seconds < -_timezone)))
116 overflow++;
117 seconds += _timezone;
119 if (timep->tm_isdst < 0)
120 dst = _dstget(timep);
121 else if (timep->tm_isdst)
122 dst = _dst_off;
123 else dst = 0;
125 if (dst > seconds) overflow++; /* dst is always non-negative */
126 seconds -= dst;
128 if (overflow) return (time_t)-1;
130 if ((time_t)seconds != seconds) return (time_t)-1;
131 return (time_t)seconds;