#ifndef lint
static char sccsid[] = "@(#)$Id: date.c,v 1.2 1994/11/01 06:08:21 sob Exp sob $";
#endif
/*
* Collection of routines for dealing with ASCII time strings.
* These may actually be useful in their own right.
*/
#include "common.h"
#ifdef USG
#include <time.h>
#else
#include <sys/time.h>
#endif
dodate(ac, av)
int ac;
char *av[];
{
struct tm *gmt;
#ifdef USG
time_t now;
(void) time(&now);
gmt = gmtime(&now);
#else /* not USG */
struct timeval now;
(void) gettimeofday(&now, (struct timezone *)NULL);
gmt = gmtime(&now.tv_sec);
#endif /* not USG */
printf("%d %04.4d%02.2d%02.2d%02.2d%02.2d%02.2d\r\n", INF_DATE,
gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
(void) fflush(stdout);
}
/*
* dtol -- convert date to long integer. This is not implicitly
* local time, or any other kind of time, for that matter. If you
* pass it a date you think is GMT, you wind up with that number of
* seconds...
*
* Now regards any year < 70 as being after Y2K. Will still break due
* to time_t overflow. D. Glover, 29/11/99
*
* Parameters: "date_ascii" is in the form "yymmddhhmmss".
*
* Returns: Long integer containing number
* of seconds since 000000 Jan 1, 1970,
* and "date". -1 on error.
*
* Side effects: None.
*/
#define twodigtoi(x) (((x[0]) - '0') + (x[1] - '0')*10)
#define dysize(y) ((y % 4 ? 365 : 366))
static int dmsize[12] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
long
dtol(date_ascii)
char *date_ascii;
{
char date[32], *date_str;
char *lhs, *rhs;
char temp;
long seconds;
int year, month, day, hour, mins, secs;
int len, i;
len = strlen(date_ascii);
if (len != sizeof("yymmddhhmmss")-1)
return (-1);
(void) strcpy(date, date_ascii);
date_str = date;
#ifdef DEBUG
if (debug > 1)
syslog(LOG_DEBUG, "(1) date_str = \"%s\"", date_str);
#endif
rhs = date_str + len - 1;
lhs = date_str;
for (; lhs < rhs; ++lhs, --rhs) {
temp = *lhs;
*lhs = *rhs;
*rhs = temp;
if (!isdigit(temp) || !isdigit(*lhs))
return (-1);
}
lhs = date_str;
#ifdef DEBUG
if (debug > 1)
syslog(LOG_DEBUG, "(2) date_str = \"%s\"", date_str);
#endif
secs = twodigtoi(lhs);
lhs += 2;
mins = twodigtoi(lhs);
lhs += 2;
hour = twodigtoi(lhs);
lhs += 2;
day = twodigtoi(lhs);
lhs += 2;
month = twodigtoi(lhs);
lhs += 2;
year = twodigtoi(lhs);
if (month < 1 || month > 12 ||
day < 1 || day > 31 ||
mins < 0 || mins > 59 ||
secs < 0 || secs > 59)
return (-1);
if (hour == 24) {
hour = 0;
day++;
}
if (hour < 0 || hour > 23)
return (-1);
seconds = 0;
/* We need to handle years correctly per RFC977. This fix is consistent with
* the approach in inn-2.0. Years before 1970 wouldn't work anyway, but this
* will also run out of steam after 2038...
* We seem to have Y2K as a leap year already, by accident rather than
* design. DG 29/11/99
*/
if (year <70)
year += 2000;
else
year += 1900;
for (i = 1970; i < year; i++)
seconds += dysize(i);
/* Leap year */
if (dysize(year) == 366 && month >= 3)
seconds++;
while (--month)
seconds += dmsize[month-1];
seconds += day-1;
seconds = 24 * seconds + hour;
seconds = 60 * seconds + mins;
seconds = 60 * seconds + secs;
return (seconds);
}
/*
* ltod -- convert long integer to date string.
*
* Now returns 4-digit years. D. Glover 29/11/99
*
* Parameters: "date" is in the number of seconds
* since the epoch.
*
* Returns: Pointer to static data in the form
* yyyymmddhhmmss\0.
*
* Side effects: None.
*/
char *
ltod(date)
long date;
{
static char timebuf[32];
struct tm *tp;
tp = gmtime(&date);
(void) sprintf(timebuf, "%04d%02d%02d%02d%02d%02d",
tp->tm_year +1900, /* DG 29/11/99 - return 4-digit year */
tp->tm_mon + 1, /* 0 to 11??? How silly. */
tp->tm_mday,
tp->tm_hour,
tp->tm_min,
tp->tm_sec);
return (timebuf);
}
/*
* local_to_gmt -- convert a local time (in form of number of
* seconds since you-know-when) to GMT.
*
* Parameters: "date" is date we want converted, in
* seconds since 000000 1 Jan 1970.
*
* Returns: Number of seconds corrected for local
* and dst.
*/
long
local_to_gmt(date)
long date;
{
#ifdef USG
#if !defined(dgux) && !defined(M_XENIX)
extern long timezone;
#endif
tzset();
date += timezone;
#else /* not USG */
struct timeval tv;
struct timezone tz;
(void) gettimeofday(&tv, &tz);
date += (long) tz.tz_minuteswest * 60;
#endif /* not USG */
/* now fix up local daylight time */
if (localtime((time_t *)&date)->tm_isdst)
date -= 60*60;
return (date);
}
/*
* gmt_to_local -- take a GMT time expressed in seconds since
* the epoch, and convert it to local time.
*
* Parameters: "date" is the number of seconds...
*
* Returns: Number of seconds corrected to reflect
* local time and dst.
*/
long
gmt_to_local(date)
long date;
{
#ifdef USG
#if !defined(dgux) && !defined(M_XENIX)
extern long timezone;
#endif
tzset();
date -= timezone;
#else /* not USG */
struct timeval tv;
struct timezone tz;
(void) gettimeofday(&tv, &tz);
date -= (long) tz.tz_minuteswest * 60;
#endif /* not USG */
/* now fix up local daylight time */
if (localtime((time_t *)&date)->tm_isdst)
date += 60*60;
return (date);
}
syntax highlighted by Code2HTML, v. 0.9.1