home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 4
/
DATAFILE_PDCD4.iso
/
unix
/
unixlib36d
/
src
/
c
/
mktime
< prev
next >
Wrap
Text File
|
1994-03-08
|
4KB
|
178 lines
static char sccs_id[] = "@(#) mktime.c 3.0 " __DATE__ " HJR";
/* mktime.c (c) Copyright 1990 H.Rogers */
#include <time.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
static unsigned int __tmonth[12] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static struct tm __tz[1] = /* time struct */
{
{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, ""}
};
/* Time zones are "[TZNAME][H][:M][DSTNAME]" where H:M gives the time *west*
* of GMT for the timezone. If DSTNAME appears then the time zone follows
* DST rules according to DSTNAME. Examples:
*
* "EST5EDT" USA Eastern time zone
* "CST6CDT" USA Central time zone
* "NFLDT3:30NFLD" Newfoundland time (1:30 ahead of Eastern)
* "OZCST-9:30" Australian Central time zone (no DST)
*
* DST is currently unimplemented: Other implementations involve very nasty
* code in order to cater for exception years (e.g. USA 1972). Also most
* assume USA rules for DST (which have changed 3 times since 1970), not UK
* rules (which have changed more often and are more complex :-( ). It's
* simpler to rely on the SysAdmin changing the system clock twice a year
* according to local custom. Leap seconds and the century offset are ignored,
* but the routines are correct to within a second till at least 2038... */
int timezone = 0;
void
tzset (void)
{
char *z;
register int i;
if (!(z = getenv ("TZ")))
z = "GMT0UK"; /* default to GMT/UKDST */
i = 0;
while (isalpha (*z))
{
if (i < 3)
{
__tz->tm_zone[i] = *z;
i++;
}
z++;
}
__tz->tm_zone[i] = 0;
i = (int) strtol (z, &z, 10) * 3600;
if (*z == ':')
{
z++;
i += (int) strtol (z, &z, 10) * 60;
}
__tz->tm_gmtoff = timezone = i;
}
static struct tm *__mktm (register time_t);
struct tm *
gmtime (register const time_t * tp)
{
if (!(__tz->tm_zone[0]))
tzset ();
return (__mktm (*tp));
}
struct tm *
localtime (register const time_t * tp)
{
if (!(__tz->tm_zone[0]))
tzset ();
return (__mktm ((*tp) - __tz->tm_gmtoff));
}
static struct tm *
__mktm (register time_t tm)
{
register struct tm *t = __tz;
register time_t i, j, k;
t->tm_isdst = -1;
t->tm_wday = (tm / 86400 + 4) % 7; /* 1st Jan 1970 = Thursday */
t->tm_sec = tm % 60;
tm /= 60;
t->tm_min = tm % 60;
tm /= 60;
t->tm_hour = tm % 24;
tm /= 24;
i = (365 << 1); /* two years */
if (tm >= i) /* >= 1972 */
{
j = (tm - i) / 1461;
tm -= i + j * 1461;
k = tm ? ((tm - 1) / 365) : 0;
if (k)
{
tm -= 1 + k * 365;
__tmonth[1] = 28;
}
else
__tmonth[1] = 29; /* Feb. hath 29 days in a leap year */
k += 2 + (j << 2);
}
else
/* < 1972 */
{
k = tm / 365;
tm -= k * 365;
__tmonth[1] = 28;
}
t->tm_year = k + 70;
t->tm_yday = tm;
k = tm;
j = 0;
while (k >= (i = __tmonth[j]))
k -= i, j++;
t->tm_mon = j;
t->tm_mday = k + 1;
return (t);
}
time_t
mktime (register struct tm * t)
{
register time_t r;
if ((t->tm_year - 70) < 0)
return ((time_t) - 1);
r = t->tm_year - 70;
if (r < 2)
r = r * 365;
else
{
register int i, j;
i = (r - 2) & 3;
j = ((r - 2) >> 2) * 1461;
if (i)
{
r = (365 << 1) + j + 1 + i * 365;
}
else
r = (365 << 1) + j;
}
r += t->tm_yday;
r = r * 24 + t->tm_hour;
r = r * 60 + t->tm_min;
r = r * 60 + t->tm_sec;
r += t->tm_gmtoff; /* mktime() is passed a localtime() struct */
return (r);
}