|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 4458 (0x116a)
Types: TextFile
Names: »timemk.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec3/localtime/timemk.c«
#
/*LINTLIBRARY*/
#ifndef lint
#ifndef NOID
static char sccsid[] = "@(#)timemk.c 3.1";
#endif /* !NOID */
#endif /* !lint */
#ifdef STD_INSPIRED
/*
** Code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob
** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
** It does a binary search of the time_t space. Since time_t's are
** just 32 bits, its a max of 32 iterations (even at 64 bits it
** would still be very reasonable).
**
** This code does handle "out of bounds" values in the way described
** for "mktime" in the October, 1986 draft of the proposed ANSI C Standard;
** though this is an accident of the implementation and *cannot* be made to
** work correctly for the purposes there described.
**
** A warning applies if you try to use these functions with a version of
** "localtime" that has overflow problems (such as System V Release 2.0
** or 4.3 BSD localtime).
** If you're not using GMT and feed a value to localtime
** that's near the minimum (or maximum) possible time_t value, localtime
** may return a struct that represents a time near the maximum (or minimum)
** possible time_t value (because of overflow). If such a returned struct tm
** is fed to timelocal, it will not return the value originally feed to
** localtime.
*/
#include "time.h"
#include "tzfile.h"
#include "sys/types.h"
#ifndef WRONG
#define WRONG (-1)
#endif /* !WRONG */
extern struct tm * localtime();
extern struct tm * gmtime();
extern struct tm * offtime();
static time_t
timemk(timeptr, funcp, offset)
struct tm * timeptr;
struct tm * (* funcp)();
long offset;
{
register int direction;
register int bits;
time_t t;
struct tm yourtm, mytm;
yourtm = *timeptr;
/*
** Correct the tm supplied, in case some of its values are
** out of range.
*/
while (yourtm.tm_sec >= SECS_PER_MIN)
++yourtm.tm_min, yourtm.tm_sec -= SECS_PER_MIN;
while (yourtm.tm_sec < 0)
--yourtm.tm_min, yourtm.tm_sec += SECS_PER_MIN;
while (yourtm.tm_min >= MINS_PER_HOUR)
++yourtm.tm_hour, yourtm.tm_min -= MINS_PER_HOUR;
while (yourtm.tm_min < 0)
--yourtm.tm_hour, yourtm.tm_min += MINS_PER_HOUR;
while (yourtm.tm_hour >= HOURS_PER_DAY)
++yourtm.tm_mday, yourtm.tm_hour -= HOURS_PER_DAY;
while (yourtm.tm_hour < 0)
--yourtm.tm_mday, yourtm.tm_hour += HOURS_PER_DAY;
while (yourtm.tm_mday > 31) /* trust me [kre] */
++yourtm.tm_mon, yourtm.tm_mday -= 31;
while (yourtm.tm_mday <= 0)
--yourtm.tm_mon, yourtm.tm_mday += 31;
while (yourtm.tm_mon >= MONS_PER_YEAR)
++yourtm.tm_year, yourtm.tm_mon -= MONS_PER_YEAR;
while (yourtm.tm_mon < 0)
--yourtm.tm_year, yourtm.tm_mon += MONS_PER_YEAR;
/*
** Calcluate the number of magnitude bits in a time_t
** (this works regardless of whether time_t is
** signed or unsigned, though lint complains if unsigned).
*/
for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
;
/*
** If time_t is signed, then 0 is the median value,
** if time_t is unsigned, then 1 << bits is median.
*/
t = (t < 0) ? 0 : ((time_t) 1 << bits);
for ( ; ; ) {
mytm = (funcp == offtime) ?
*((*funcp)(&t, offset)) : *((*funcp)(&t));
if ((direction = (mytm.tm_year - yourtm.tm_year)) == 0 &&
(direction = (mytm.tm_mon - yourtm.tm_mon)) == 0 &&
(direction = (mytm.tm_mday - yourtm.tm_mday)) == 0 &&
(direction = (mytm.tm_hour - yourtm.tm_hour)) == 0 &&
(direction = (mytm.tm_min - yourtm.tm_min)) == 0)
direction = mytm.tm_sec - yourtm.tm_sec;
if (direction == 0) {
*timeptr = mytm;
return t;
}
if (bits-- < 0) {
*timeptr = yourtm; /* restore "original" value */
if (yourtm.tm_mday == 31) {
timeptr->tm_mday = 1;
++(timeptr->tm_mon);
t = timemk(timeptr, funcp);
if (t != WRONG)
return t;
*timeptr = yourtm;
} else if (yourtm.tm_mon == TM_FEBRUARY &&
yourtm.tm_mday > 28) {
timeptr->tm_mday -= 28;
++(timeptr->tm_mon);
t = timemk(timeptr, funcp);
if (t != WRONG)
return t;
*timeptr = yourtm;
}
return WRONG;
}
if (bits < 0)
--t;
else if (direction > 0)
t -= (time_t) 1 << bits;
else t += (time_t) 1 << bits;
}
}
time_t
timelocal(timeptr)
struct tm * timeptr;
{
return timemk(timeptr, localtime, 0L);
}
time_t
timegm(timeptr)
struct tm * timeptr;
{
return timemk(timeptr, gmtime, 0L);
}
time_t
timeoff(timeptr, offset)
struct tm * timeptr;
long offset;
{
return timemk(timeptr, offtime, offset);
}
#endif /* STD_INSPIRED */