#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 #else #include #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); }