source: trunk/minix/lib/ansi/mktime.c@ 12

Last change on this file since 12 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 3.5 KB
RevLine 
[9]1/*
2 * mktime - convert local time into calendar time
3 */
4/* $Header: /cvsup/minix/src/lib/ansi/mktime.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
5
6/* Michael A. Temari <temari@ix.netcom.com> 03/01/96 */
7/* - fixed bug is structure fixup code */
8
9#include <time.h>
10#include <limits.h>
11#include "loc_time.h"
12
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.
16 */
17time_t
18mktime(register struct tm *timep)
19{
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;
26
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--;
32 }
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--;
38 }
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--;
44 }
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--;
50 }
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;
56 }
57 day += _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
58 }
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++;
64 }
65 }
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;
73
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.
79 */
80#if EPOCH_YR != 1970
81#error EPOCH_YR != 1970
82#endif
83 tm_year = timep->tm_year + YEAR0;
84
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);
94
95 yday = month = 0;
96 while (month < timep->tm_mon) {
97 yday += _ytab[LEAPYEAR(tm_year)][month];
98 month++;
99 }
100 yday += (timep->tm_mday - 1);
101 if (day + yday < 0) overflow++;
102 day += yday;
103
104 timep->tm_yday = yday;
105 timep->tm_wday = (day + 4) % 7; /* day 0 was thursday (4) */
106
107 seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec;
108
109 if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
110 seconds += day * SECS_DAY;
111
112 /* Now adjust according to timezone and daylight saving time */
113
114 if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
115 || ((_timezone < 0) && (seconds < -_timezone)))
116 overflow++;
117 seconds += _timezone;
118
119 if (timep->tm_isdst < 0)
120 dst = _dstget(timep);
121 else if (timep->tm_isdst)
122 dst = _dst_off;
123 else dst = 0;
124
125 if (dst > seconds) overflow++; /* dst is always non-negative */
126 seconds -= dst;
127
128 if (overflow) return (time_t)-1;
129
130 if ((time_t)seconds != seconds) return (time_t)-1;
131 return (time_t)seconds;
132}
Note: See TracBrowser for help on using the repository browser.