539 lines
15 KiB
C
539 lines
15 KiB
C
/* Time and date functions */
|
|
/* Copyright (c) Mix Software 1988 */
|
|
|
|
char *ctime(time)
|
|
long time;
|
|
{
|
|
char *asctime();
|
|
struct tm *localtime();
|
|
return asctime(localtime(time));
|
|
} /* ctime */
|
|
|
|
size_t strftime(s, maxsize, format, timeptr)
|
|
char *s; /* buffer for result */
|
|
size_t maxsize; /* maximum size of s */
|
|
char *format; /* format string */
|
|
struct tm *timeptr; /* time to convert */
|
|
{ /* formatted time */
|
|
static char *shortday[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
|
|
static char *longday[7] = {"Sunday","Monday","Tuesday","Wednesday",
|
|
"Thursday","Friday","Saturday"};
|
|
static char *shortmonth[12] = {"Jan","Feb","Mar","Apr","May","Jun",
|
|
"Jul","Aug","Sep","Oct","Nov","Dec"};
|
|
static char *longmonth[12] = {"January","February","March","April",
|
|
"May","June","July","August","September",
|
|
"October","November","December"};
|
|
static char *am_pm[2] = {"AM","PM"};
|
|
static int _strput(int, char *, int);
|
|
char *asctime();
|
|
extern char *tzname[2];
|
|
#define put(ch) {if (--length) *s++ = ch; else return 0;}
|
|
char ch, *p;
|
|
char str[20];
|
|
int length = maxsize;
|
|
int value;
|
|
while (*format != '\0') {
|
|
if (*format != '%') put(*format++)
|
|
else {
|
|
p = str;
|
|
memset(p,0,sizeof(str));
|
|
switch (*++format) {
|
|
case 'a' :
|
|
p = shortday[timeptr->tm_wday];
|
|
break;
|
|
case 'A' :
|
|
p = longday[timeptr->tm_wday];
|
|
break;
|
|
case 'b' :
|
|
p = shortmonth[timeptr->tm_mon];
|
|
break;
|
|
case 'B' :
|
|
p = longmonth[timeptr->tm_mon];
|
|
break;
|
|
case 'c' :
|
|
p = asctime(timeptr);
|
|
break;
|
|
case 'd' :
|
|
_asct2dig(timeptr->tm_mday,p);
|
|
break;
|
|
case 'H' :
|
|
_asct2dig(timeptr->tm_hour,p);
|
|
break;
|
|
case 'I' :
|
|
value = timeptr->tm_hour;
|
|
if (value > 12) value -= 12;
|
|
_asct2dig(value,p);
|
|
break;
|
|
case 'j' :
|
|
case 'J' :
|
|
_asct3dig(timeptr->tm_yday,p);
|
|
break;
|
|
case 'm' :
|
|
_asct2dig(timeptr->tm_mon+1,p);
|
|
break;
|
|
case 'M' :
|
|
_asct2dig(timeptr->tm_min,p);
|
|
break;
|
|
case 'p' :
|
|
p = am_pm[timeptr->tm_hour / 12];
|
|
break;
|
|
case 'S' :
|
|
_asct2dig(timeptr->tm_sec,p);
|
|
break;
|
|
case 'U' :
|
|
value = timeptr->tm_wday - (timeptr->tm_yday % 7);
|
|
if (value < 0) value += 7; /* week day of Jan 1 */
|
|
value = (timeptr->tm_yday + value - 1) / 7;
|
|
_asct2dig(value,p);
|
|
break;
|
|
case 'w' :
|
|
*p = timeptr->tm_wday + '0';
|
|
break;
|
|
case 'W' :
|
|
value = timeptr->tm_wday - (timeptr->tm_yday % 7);
|
|
if (value < 0) value += 7; /* week day of Jan 1 */
|
|
value = (timeptr->tm_yday + value) / 7;
|
|
_asct2dig(value,p);
|
|
break;
|
|
case 'x' :
|
|
_asct2dig(timeptr->tm_mon+1,str);
|
|
_asct2dig(timeptr->tm_mday,&str[3]);
|
|
_asct2dig(timeptr->tm_year % 100,&str[6]);
|
|
str[2] = '/';
|
|
str[5] = '/';
|
|
break;
|
|
case 'X' :
|
|
_asct2dig(timeptr->tm_hour,str);
|
|
_asct2dig(timeptr->tm_min,&str[3]);
|
|
_asct2dig(timeptr->tm_sec % 100,&str[6]);
|
|
str[2] = ':';
|
|
str[5] = ':';
|
|
break;
|
|
case 'y' :
|
|
_asct2dig(timeptr->tm_year % 100,p);
|
|
break;
|
|
case 'Y' :
|
|
_asct2dig(timeptr->tm_year / 100,str);
|
|
_asct2dig(timeptr->tm_year % 100,&str[2]);
|
|
break;
|
|
case 'Z' :
|
|
if (timeptr->tm_isdst) p = tzname[1]; else p = tzname[0];
|
|
if (p == NULL) p = str;
|
|
break;
|
|
case '%' :
|
|
*p = '%';
|
|
break;
|
|
} /* switch */
|
|
while (*p != '\0') put(*p++)
|
|
++format;
|
|
} /* '%' */
|
|
} /* while */
|
|
*s = '\0';
|
|
return maxsize - length;
|
|
#undef put
|
|
} /* strftime */
|
|
|
|
char *asctime(time)
|
|
struct tm *time;
|
|
{ /* convert time to a character string */
|
|
static char *monthname[13] = {"Jan","Feb","Mar","Apr","May","Jun",
|
|
"Jul","Aug","Sep","Oct","Nov","Dec"};
|
|
static char *dayname[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
|
|
static char timebuf[26];
|
|
int yy;
|
|
strcpy(timebuf,"www mmm dd hh:mm:ss yyyy\n");
|
|
memcpy(timebuf,dayname[time->tm_wday],3);
|
|
memcpy(&timebuf[4],monthname[time->tm_mon],3);
|
|
_asct2dig(time->tm_mday,&timebuf[8]);
|
|
_asct2dig(time->tm_hour,&timebuf[11]);
|
|
_asct2dig(time->tm_min,&timebuf[14]);
|
|
_asct2dig(time->tm_sec,&timebuf[17]);
|
|
yy = time->tm_year < 100 ? 19 : 20;
|
|
_asct2dig(yy,&timebuf[20]);
|
|
_asct2dig(time->tm_year % 100,&timebuf[22]);
|
|
return timebuf;
|
|
|
|
} /* asctime */
|
|
|
|
_asct2dig(n, p)
|
|
int n;
|
|
char *p;
|
|
{
|
|
*p++ = (n / 10) + '0';
|
|
*p = (n % 10) + '0';
|
|
}
|
|
|
|
_asct3dig(n, p)
|
|
int n;
|
|
char *p;
|
|
{
|
|
*p++ = (n / 100) + '0';
|
|
n = n % 100;
|
|
*p++ = (n / 10) + '0';
|
|
*p = (n % 10) + '0';
|
|
}
|
|
|
|
time_t mktime(timeptr)
|
|
struct tm *timeptr;
|
|
{
|
|
long _timesec(int, int, int, int, int, int);
|
|
struct tm *localtime();
|
|
struct tm *_timecvt(time_t);
|
|
time_t t;
|
|
t = _timesec(timeptr->tm_year+1900, timeptr->tm_mon+1, timeptr->tm_mday,
|
|
timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
|
|
*timeptr = *localtime(&t);
|
|
return t;
|
|
}
|
|
|
|
int stime(tp) /* set time */
|
|
long *tp;
|
|
{
|
|
struct tm *t;
|
|
union REGS time, date;
|
|
t = localtime(tp);
|
|
time.h.ah = 0x2d;
|
|
time.h.ch = t->tm_hour;
|
|
time.h.cl = t->tm_min;
|
|
time.h.dh = t->tm_sec;
|
|
time.h.dl = 0;
|
|
date.h.ah = 0x2b;
|
|
date.x.cx = t->tm_year+1900;
|
|
date.h.dh = t->tm_mon+1;
|
|
date.h.dl = t->tm_mday;
|
|
intdos(&date,&date);
|
|
intdos(&time,&time);
|
|
return 0;
|
|
}
|
|
|
|
struct utimbuf {
|
|
time_t actime; /* access time */
|
|
time_t modtime; /* modification time */
|
|
};
|
|
|
|
int utime(filename, times)
|
|
char *filename;
|
|
struct utimbuf *times;
|
|
{
|
|
extern int _doserrno, errno;
|
|
union REGS r;
|
|
struct tm *localtime(time_t *), *tptr;
|
|
union {
|
|
struct ftime time;
|
|
struct {
|
|
int time;
|
|
int date;
|
|
} i;
|
|
} filetime;
|
|
time_t t, time();
|
|
int handle;
|
|
int status;
|
|
if (times == NULL) t = time(NULL); else t = times->modtime;
|
|
tptr = localtime(&t);
|
|
if (_sys_ad(0x3d00,filename,&handle) != 0)
|
|
{ errno = _doserrno; return -1; }
|
|
if (tptr->tm_year < 80) filetime.time.ft_year = 0;
|
|
else filetime.time.ft_year = tptr->tm_year-80;
|
|
filetime.time.ft_month = tptr->tm_mon+1;
|
|
filetime.time.ft_day = tptr->tm_mday;
|
|
if (tptr->tm_hour < 0) filetime.time.ft_hour = 0;
|
|
else filetime.time.ft_hour = tptr->tm_hour;
|
|
filetime.time.ft_min = tptr->tm_min;
|
|
filetime.time.ft_tsec = tptr->tm_sec >> 1;
|
|
r.x.ax = 0x5701;
|
|
r.x.bx = handle;
|
|
if (_sysabcd(0x5701,handle,filetime.i.time,filetime.i.date,&status) != 0) {
|
|
errno = _doserrno;
|
|
_sys_ab(0x3e00,handle,&handle);
|
|
return -1;
|
|
}
|
|
_sys_ab(0x3e00,handle,&handle);
|
|
return 0;
|
|
}
|
|
|
|
struct tm *gmtime(time)
|
|
long *time;
|
|
{
|
|
struct tm *_timecvt();
|
|
return _timecvt(*time);
|
|
} /* gmtime */
|
|
|
|
struct tm *localtime(time)
|
|
long *time;
|
|
{
|
|
extern long timezone;
|
|
extern int daylight;
|
|
void tzset();
|
|
struct tm *_timecvt();
|
|
static tzdone = 0;
|
|
if (tzdone == 0) {tzset(); tzdone = 1; }
|
|
if (daylight) return _timecvt(*time-timezone+3600);
|
|
return _timecvt(*time-timezone);
|
|
} /* localtime */
|
|
|
|
void unixtodos(utime, dateptr, timeptr)
|
|
long utime;
|
|
struct date *dateptr;
|
|
struct time *timeptr;
|
|
{
|
|
extern struct tm *_timecvt();
|
|
extern long timezone;
|
|
extern int daylight;
|
|
struct tm *t;
|
|
long localtime;
|
|
localtime = utime - timezone;
|
|
if (daylight) localtime += 3600l;
|
|
t = _timecvt(localtime);
|
|
dateptr->da_year = t->tm_year + 1900;
|
|
dateptr->da_mon = t->tm_mon+1;
|
|
dateptr->da_day = t->tm_mday;
|
|
timeptr->ti_hour = t->tm_hour;
|
|
timeptr->ti_min = t->tm_min;
|
|
timeptr->ti_sec = t->tm_sec;
|
|
timeptr->ti_hund = 0;
|
|
}
|
|
|
|
struct tm *_timecvt(time)
|
|
long time;
|
|
{ /* convert binary time to greenwich mean time */
|
|
static struct tm gm;
|
|
static int daypermonth[12] = {31, 28, 31, 30, 31, 30,
|
|
31, 31, 30, 31, 30, 31};
|
|
extern int daylight;
|
|
long secs, days;
|
|
int years, leaps, dayofyear;
|
|
int month = 0;
|
|
int *mptr = daypermonth;
|
|
days = time / 86400;
|
|
years = days/365;
|
|
leaps = (years+1) / 4;
|
|
dayofyear = days - (long)years * 365 - (long)leaps;
|
|
if (dayofyear < 0) {
|
|
years--;
|
|
dayofyear += 365;
|
|
}
|
|
gm.tm_yday = dayofyear;
|
|
gm.tm_year = years+70;
|
|
if ((years % 4) == 2) daypermonth[1] = 29; else daypermonth[1] = 28;
|
|
while (dayofyear > *mptr) {
|
|
++month;
|
|
dayofyear -= *mptr++;
|
|
}
|
|
gm.tm_mon = month;
|
|
gm.tm_mday = dayofyear+1;
|
|
gm.tm_wday = (days + 4) % 7;
|
|
secs = time - days*86400;
|
|
gm.tm_hour = secs / 3600;
|
|
secs -= (gm.tm_hour * 3600L);
|
|
gm.tm_min = secs / 60;
|
|
gm.tm_sec = secs - (gm.tm_min * 60);
|
|
gm.tm_isdst = daylight;
|
|
return &gm;
|
|
} /* _timecvt */
|
|
|
|
void ftime(timeptr)
|
|
struct timeb *timeptr;
|
|
{
|
|
long _timesec();
|
|
void tzset();
|
|
extern long timezone;
|
|
extern int daylight;
|
|
union REGS timecall, datecall;
|
|
union REGS time, date1, date2;
|
|
tzset();
|
|
timecall.h.ah = 0x2c;
|
|
datecall.h.ah = 0x2a;
|
|
intdos(&datecall,&date1);
|
|
intdos(&timecall,&time);
|
|
intdos(&datecall,&date2);
|
|
if (date2.x.dx != date1.x.dx) { /* date change at midnight */
|
|
if (time.h.ch != 23) { /* date already changed when time read */
|
|
date1.x.cx = date2.x.cx;
|
|
date1.x.dx = date2.x.dx;
|
|
}
|
|
}
|
|
timeptr->time = _timesec(date1.x.cx, date1.h.dh, date1.h.dl,
|
|
time.h.ch, time.h.cl, time.h.dh);
|
|
timeptr->millitm = time.h.dl*10;
|
|
timeptr->timezone = timezone/60;
|
|
timeptr->dstflag = daylight;
|
|
} /* ftime */
|
|
|
|
unsigned sleep(seconds)
|
|
unsigned seconds;
|
|
{ /* suspend execution */
|
|
long time();
|
|
long start, now;
|
|
start = time(NULL);
|
|
do {
|
|
now = time(NULL);
|
|
} while ((now-start) < seconds);
|
|
}
|
|
|
|
long time(timeptr)
|
|
long *timeptr;
|
|
{
|
|
long _timesec();
|
|
long curtime;
|
|
union REGS timecall, datecall;
|
|
union REGS time, date1, date2;
|
|
timecall.h.ah = 0x2c;
|
|
datecall.h.ah = 0x2a;
|
|
intdos(&datecall,&date1);
|
|
intdos(&timecall,&time);
|
|
intdos(&datecall,&date2);
|
|
if (date2.x.dx != date1.x.dx) { /* date change at midnight */
|
|
if (time.h.ch != 23) { /* date already changed when time read */
|
|
date1.x.cx = date2.x.cx;
|
|
date1.x.dx = date2.x.dx;
|
|
}
|
|
}
|
|
curtime = _timesec(date1.x.cx, date1.h.dh, date1.h.dl,
|
|
time.h.ch, time.h.cl, time.h.dh);
|
|
if (timeptr != NULL) *timeptr = curtime;
|
|
return curtime;
|
|
} /* time */
|
|
|
|
long dostounix(dateptr, timeptr)
|
|
struct date *dateptr;
|
|
struct time *timeptr;
|
|
{
|
|
long _timesec();
|
|
return _timesec(dateptr->da_year,dateptr->da_mon,dateptr->da_day,
|
|
timeptr->ti_hour, timeptr->ti_min, timeptr->ti_sec);
|
|
}
|
|
|
|
clock_t clock(void)
|
|
{
|
|
extern struct {
|
|
unsigned int year;
|
|
unsigned char day;
|
|
unsigned char month;
|
|
unsigned char hour;
|
|
unsigned char minute;
|
|
unsigned char hour;
|
|
unsigned char hundredth;
|
|
unsigned char second;
|
|
} $$CLOCK; /* time when process started */
|
|
long time;
|
|
union REGS t, d;
|
|
t.h.ah = 0x2c;
|
|
d.h.ah = 0x2a;
|
|
intdos(&d,&d);
|
|
intdos(&t,&t);
|
|
time = _timesec(d.x.cx,d.h.dh,d.h.dl,t.h.cl,t.h.ch,t.h.dh);
|
|
time = time - _timesec($$CLOCK.year,$$CLOCK.month,$$CLOCK.day,
|
|
$$CLOCK.hour,$$CLOCK.minute,$$CLOCK.second);
|
|
return time*100+t.h.dl-$$CLOCK.hundredth;
|
|
}
|
|
|
|
long _timesec(year, month, day, hour, min, sec)
|
|
int year, month, day, hour, min, sec;
|
|
{ /* convert time to seconds since Jan 1 1970 */
|
|
extern long timezone;
|
|
extern int daylight;
|
|
static int daypermonth[13] = {0, 0, 31, 28+31,
|
|
31+59, 30+31+59, 31+30+31+59,
|
|
30+151, 31+30+151, 31+31+30+151,
|
|
30+243, 31+30+243, 30+31+30+243};
|
|
int years, leaps;
|
|
long days, secs;
|
|
years = year - 1970;
|
|
leaps = (years + 1) / 4;
|
|
if (((years % 4) == 2) && (month > 2)) ++leaps;
|
|
days = (long)years*365 + (long)leaps + (long)daypermonth[month]
|
|
+ (long)(day-1);
|
|
secs = days*86400 + (long)hour*3600 + (long)min*60 + (long)sec + timezone;
|
|
if (daylight) return (secs-3600);
|
|
return secs;
|
|
} /* _timesec */
|
|
|
|
void tzset()
|
|
{
|
|
extern int daylight;
|
|
extern long timezone;
|
|
extern char *tzname[2];
|
|
char *tz;
|
|
int onehour = 3600;
|
|
tz = getenv("TZ=");
|
|
if (tz != NULL) {
|
|
strncpy(tzname[0],tz,3);
|
|
if (strlen(tz) > 3) {
|
|
tz += 3;
|
|
if (*tz == '-') {
|
|
onehour = -onehour;
|
|
++tz;
|
|
}
|
|
timezone = 0;
|
|
while (isdigit(*tz)) {
|
|
timezone = timezone*10 + (long)onehour*(long)(*tz - '0');
|
|
++tz;
|
|
}
|
|
if (*tz) daylight = 1; else daylight = 0;
|
|
strncpy(tzname[1],tz,3);
|
|
}
|
|
else {
|
|
timezone = 0;
|
|
daylight = 0;
|
|
*tzname[1] = '\0';
|
|
}
|
|
}
|
|
} /* tzset */
|
|
|
|
double difftime(time2,time1)
|
|
time_t time1, time2;
|
|
{
|
|
return time2-time1;
|
|
}
|
|
|
|
int daylight = 1;
|
|
long timezone = 28800;
|
|
char *tzname[2] = {"PST", "PDT"};
|
|
|
|
void getdate(dateblk)
|
|
struct date *dateblk;
|
|
{
|
|
union REGS r;
|
|
r.h.ah = 0x2a;
|
|
intdos(&r,&r);
|
|
dateblk->da_year = r.x.cx;
|
|
dateblk->da_mon = r.h.dh;
|
|
dateblk->da_day = r.h.dl;
|
|
}
|
|
|
|
void gettime(timep)
|
|
struct time *timep;
|
|
{
|
|
union REGS r;
|
|
r.h.ah = 0x2c;
|
|
intdos(&r,&r);
|
|
timep->ti_min = r.h.cl;
|
|
timep->ti_hour = r.h.ch;
|
|
timep->ti_hund = r.h.dl;
|
|
timep->ti_sec = r.h.dh;
|
|
}
|
|
|
|
void setdate(dateblk)
|
|
struct date *dateblk;
|
|
{
|
|
union REGS r;
|
|
r.x.cx = dateblk->da_year;
|
|
r.h.dh = dateblk->da_mon;
|
|
r.h.dl = dateblk->da_day;
|
|
r.h.ah = 0x2b;
|
|
intdos(&r,&r);
|
|
}
|
|
|
|
void settime(timep)
|
|
struct time *timep;
|
|
{
|
|
union REGS r;
|
|
r.h.cl = timep->ti_min;
|
|
r.h.ch = timep->ti_hour;
|
|
r.h.dl = timep->ti_hund;
|
|
r.h.dh = timep->ti_sec;
|
|
r.h.ah = 0x2d;
|
|
intdos(&r,&r);
|
|
}
|
|
|