ack/lang/cem/libcc.ansi/time/mktime.c

129 lines
3.2 KiB
C
Raw Normal View History

1989-06-12 15:22:14 +00:00
/*
* mktime - convert local time into calendar time
*/
/* $Header$ */
#include <time.h>
#include <limits.h>
#include "loc_incl.h"
1989-12-18 15:33:48 +00:00
/* The code assumes that time_t is an unsigned long. When it is not, some
* things may have to change.
*/
1989-06-12 15:22:14 +00:00
time_t
mktime(register struct tm *timep)
{
1989-12-18 15:33:48 +00:00
register long day, year;
register int tm_year;
int yday, month;
register time_t seconds;
int overflow;
1989-06-12 15:22:14 +00:00
unsigned dst;
timep->tm_min += timep->tm_sec / 60;
timep->tm_sec %= 60;
if (timep->tm_sec < 0) {
timep->tm_sec += 60;
timep->tm_min--;
}
timep->tm_hour += timep->tm_min / 60;
timep->tm_min = timep->tm_min % 60;
if (timep->tm_min < 0) {
timep->tm_min += 60;
timep->tm_hour--;
}
day = timep->tm_hour / 24;
timep->tm_hour= timep->tm_hour % 24;
if (timep->tm_hour < 0) {
timep->tm_hour += 24;
day--;
}
timep->tm_year += timep->tm_mon / 12;
timep->tm_mon %= 12;
if (timep->tm_mon < 0) {
timep->tm_mon += 12;
timep->tm_year--;
}
day += (timep->tm_mday - 1);
while (day < 0) {
1989-12-18 15:33:48 +00:00
day += YEARSIZE(YEAR0 + timep->tm_year - 1);
1989-06-12 15:22:14 +00:00
timep->tm_year--;
}
1989-12-18 15:33:48 +00:00
while (day >= YEARSIZE(YEAR0 + timep->tm_year)) {
day -= YEARSIZE(YEAR0 + timep->tm_year);
1989-06-12 15:22:14 +00:00
timep->tm_year++;
}
1989-12-18 15:33:48 +00:00
while (day >= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]) {
day -= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
1989-06-12 15:22:14 +00:00
if (++(timep->tm_mon) == 12) {
timep->tm_mon = 0;
timep->tm_year++;
}
}
timep->tm_mday = day + 1;
1989-12-18 15:33:48 +00:00
_tzset(); /* set timezone and dst info */
year = EPOCH_YR;
if (timep->tm_year < year - YEAR0) return -1;
1989-06-12 15:22:14 +00:00
seconds = 0;
1989-12-18 15:33:48 +00:00
day = 0; /* means days since day 0 now */
overflow = 0;
/* Assume that when day becomes negative, there will certainly
* be overflow on seconds.
* The check for overflow needs not to be done for leapyears
* divisible by 400.
* The code only works when year (1970) is not a leapyear.
*/
#if EPOCH_YR != 1970
#error EPOCH_YR != 1970
#endif
tm_year = timep->tm_year + YEAR0;
if (LONG_MAX / 365 < tm_year - year) overflow++;
day = (tm_year - year) * 365;
if (LONG_MAX - day < (tm_year - year) / 4 + 1) overflow++;
day += (tm_year - year) / 4
+ ((tm_year % 4) && tm_year % 4 < year % 4);
day -= (tm_year - year) / 100
+ ((tm_year % 100) && tm_year % 100 < year % 100);
day += (tm_year - year) / 400
+ ((tm_year % 400) && tm_year % 400 < year % 400);
1989-06-12 15:22:14 +00:00
yday = month = 0;
1989-12-18 15:33:48 +00:00
while (month < timep->tm_mon) {
yday += _ytab[LEAPYEAR(tm_year)][month];
1989-06-12 15:22:14 +00:00
month++;
}
yday += (timep->tm_mday - 1);
1989-12-18 15:33:48 +00:00
if (day + yday < 0) overflow++;
day += yday;
1989-06-12 15:22:14 +00:00
1989-12-18 15:33:48 +00:00
timep->tm_yday = yday;
timep->tm_wday = (day + 4) % 7; /* day 0 was thursday (4) */
1989-06-12 15:22:14 +00:00
seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec;
1989-06-12 15:22:14 +00:00
1989-12-18 15:33:48 +00:00
if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
seconds += day * SECS_DAY;
1989-06-12 15:22:14 +00:00
1989-12-18 15:33:48 +00:00
/* Now adjust according to timezone and daylight saving time */
1989-06-12 15:22:14 +00:00
1989-12-18 15:33:48 +00:00
if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
|| ((_timezone < 0) && (seconds < -_timezone)))
overflow++;
seconds += _timezone;
1989-06-12 15:22:14 +00:00
1989-12-18 15:33:48 +00:00
if (timep->tm_isdst < 0)
dst = _dstget(timep);
else if (timep->tm_isdst)
dst = _dst_off;
else dst = 0;
1989-06-12 15:22:14 +00:00
1989-12-18 15:33:48 +00:00
if (dst > seconds) overflow++; /* dst is always non-negative */
seconds -= dst;
1989-06-12 15:22:14 +00:00
if (overflow) return (time_t)-1;
return seconds;
}