100 lines
1.8 KiB
C
100 lines
1.8 KiB
C
#include "time_header.h"
|
|
|
|
/*
|
|
* IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
|
|
* shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
|
|
* is not the case if we are accounting for leap seconds.
|
|
* So, we provide the following conversion routines for use
|
|
* when exchanging timestamps with POSIX conforming systems.
|
|
*
|
|
*/
|
|
|
|
static int_fast64_t
|
|
leapcorr(struct state const *sp, time_t t)
|
|
{
|
|
register struct lsinfo const *lp;
|
|
register int i;
|
|
|
|
i = sp->leapcnt;
|
|
while (--i >= 0) {
|
|
lp = &sp->lsis[i];
|
|
if (t >= lp->ls_trans)
|
|
return lp->ls_corr;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
time_t time2posix_z(struct state *sp, time_t t)
|
|
{
|
|
return t - leapcorr(sp, t);
|
|
}
|
|
|
|
time_t time2posix(time_t t)
|
|
{
|
|
int err = lock();
|
|
|
|
if (err) {
|
|
errno = err;
|
|
return -1;
|
|
}
|
|
|
|
if (!lcl_is_set)
|
|
tzset_unlocked();
|
|
if (lclptr)
|
|
t = time2posix_z(lclptr, t);
|
|
|
|
unlock();
|
|
|
|
return t;
|
|
}
|
|
|
|
time_t posix2time_z(struct state *sp, time_t t)
|
|
{
|
|
time_t x;
|
|
time_t y;
|
|
|
|
/*
|
|
** For a positive leap second hit, the result
|
|
** is not unique. For a negative leap second
|
|
** hit, the corresponding time doesn't exist,
|
|
** so we return an adjacent second.
|
|
*/
|
|
x = t + leapcorr(sp, t);
|
|
y = x - leapcorr(sp, x);
|
|
|
|
if (y < t) {
|
|
do {
|
|
x++;
|
|
y = x - leapcorr(sp, x);
|
|
} while (y < t);
|
|
x -= y != t;
|
|
} else if (y > t) {
|
|
do {
|
|
--x;
|
|
y = x - leapcorr(sp, x);
|
|
} while (y > t);
|
|
x += y != t;
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
time_t posix2time(time_t t)
|
|
{
|
|
int err = lock();
|
|
|
|
if (err) {
|
|
errno = err;
|
|
return -1;
|
|
}
|
|
|
|
if (!lcl_is_set)
|
|
tzset_unlocked();
|
|
if (lclptr)
|
|
t = posix2time_z(lclptr, t);
|
|
unlock();
|
|
|
|
return t;
|
|
}
|