105 lines
2.1 KiB
C
105 lines
2.1 KiB
C
|
/*
|
||
|
* localtime_r.c
|
||
|
* Original Author: Adapted from tzcode maintained by Arthur David Olson.
|
||
|
*
|
||
|
* Converts the calendar time pointed to by tim_p into a broken-down time
|
||
|
* expressed as local time. Returns a pointer to a structure containing the
|
||
|
* broken-down time.
|
||
|
*/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#define SECSPERMIN 60L
|
||
|
#define MINSPERHOUR 60L
|
||
|
#define HOURSPERDAY 24L
|
||
|
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||
|
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
|
||
|
#define DAYSPERWEEK 7
|
||
|
#define MONSPERYEAR 12
|
||
|
|
||
|
#define YEAR_BASE 1900
|
||
|
#define EPOCH_YEAR 1970
|
||
|
#define EPOCH_WDAY 4
|
||
|
|
||
|
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
|
||
|
|
||
|
static _CONST int mon_lengths[2][MONSPERYEAR] = {
|
||
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||
|
} ;
|
||
|
|
||
|
static _CONST int year_lengths[2] = {
|
||
|
365,
|
||
|
366
|
||
|
} ;
|
||
|
|
||
|
struct tm *
|
||
|
_DEFUN (localtime_r, (tim_p, res),
|
||
|
_CONST time_t * tim_p _AND
|
||
|
struct tm *res)
|
||
|
{
|
||
|
long days, rem;
|
||
|
int y;
|
||
|
int yleap;
|
||
|
_CONST int *ip;
|
||
|
|
||
|
days = ((long) *tim_p) / SECSPERDAY;
|
||
|
rem = ((long) *tim_p) % SECSPERDAY;
|
||
|
while (rem < 0)
|
||
|
{
|
||
|
rem += SECSPERDAY;
|
||
|
--days;
|
||
|
}
|
||
|
while (rem >= SECSPERDAY)
|
||
|
{
|
||
|
rem -= SECSPERDAY;
|
||
|
++days;
|
||
|
}
|
||
|
|
||
|
/* compute hour, min, and sec */
|
||
|
res->tm_hour = (int) (rem / SECSPERHOUR);
|
||
|
rem %= SECSPERHOUR;
|
||
|
res->tm_min = (int) (rem / SECSPERMIN);
|
||
|
res->tm_sec = (int) (rem % SECSPERMIN);
|
||
|
|
||
|
/* compute day of week */
|
||
|
if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
|
||
|
res->tm_wday += DAYSPERWEEK;
|
||
|
|
||
|
/* compute year & day of year */
|
||
|
y = EPOCH_YEAR;
|
||
|
if (days >= 0)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
yleap = isleap(y);
|
||
|
if (days < year_lengths[yleap])
|
||
|
break;
|
||
|
y++;
|
||
|
days -= year_lengths[yleap];
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
--y;
|
||
|
yleap = isleap(y);
|
||
|
days += year_lengths[yleap];
|
||
|
} while (days < 0);
|
||
|
}
|
||
|
|
||
|
res->tm_year = y - YEAR_BASE;
|
||
|
res->tm_yday = days;
|
||
|
ip = mon_lengths[yleap];
|
||
|
for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
|
||
|
days -= ip[res->tm_mon];
|
||
|
res->tm_mday = days + 1;
|
||
|
|
||
|
/* set daylight saving time flag */
|
||
|
res->tm_isdst = -1;
|
||
|
|
||
|
return (res);
|
||
|
}
|