mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-04 06:01:23 -05:00
ITS#9120 change reference year from 1970 to 0000
Now handles +/-8740 years centered around year 0000 (1BCE)
This commit is contained in:
parent
a4af93f16b
commit
97c145919d
2 changed files with 61 additions and 38 deletions
|
|
@ -169,8 +169,9 @@ typedef struct lutil_tm {
|
|||
} lutil_tm;
|
||||
|
||||
typedef struct lutil_timet {
|
||||
unsigned int tt_sec; /* seconds since 1900 */
|
||||
int tt_gsec; /* seconds since 1900, high 7 bits */
|
||||
unsigned int tt_sec; /* seconds since 0000 */
|
||||
int tt_gsec; /* seconds since 0000, high 7 bits, sign-flipped */
|
||||
/* sign flipped to sort properly as unsigned ints */
|
||||
unsigned int tt_usec; /* microseconds */
|
||||
} lutil_timet;
|
||||
|
||||
|
|
|
|||
|
|
@ -151,75 +151,92 @@ size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta )
|
|||
return ret + 4;
|
||||
}
|
||||
|
||||
/* Proleptic Gregorian Calendar, 1BCE = year 0 */
|
||||
|
||||
int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
|
||||
{
|
||||
static int moffset[12] = {
|
||||
0, 31, 59, 90, 120,
|
||||
151, 181, 212, 243,
|
||||
273, 304, 334 };
|
||||
int sec;
|
||||
int sec, year;
|
||||
long tmp;
|
||||
|
||||
tt->tt_usec = tm->tm_usec;
|
||||
|
||||
/* special case 0000/01/01+00:00:00 is returned as zero */
|
||||
if ( tm->tm_year == -1900 && tm->tm_mon == 0 && tm->tm_mday == 1 &&
|
||||
tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0 ) {
|
||||
tt->tt_sec = 0;
|
||||
tt->tt_gsec = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* tm->tm_year is years since 1900 */
|
||||
/* calculate days from years since 1970 (epoch) */
|
||||
tt->tt_sec = tm->tm_year - 70;
|
||||
tt->tt_sec *= 365L;
|
||||
/* calculate days from 0000 */
|
||||
year = tm->tm_year + 1900;
|
||||
tmp = year * 365;
|
||||
|
||||
/* count leap days in preceding years */
|
||||
tt->tt_sec += ((tm->tm_year -69) >> 2);
|
||||
|
||||
/* add in leap days */
|
||||
sec = (year - 1) / 4;
|
||||
tmp += sec;
|
||||
sec /= 25;
|
||||
tmp -= sec;
|
||||
sec /= 4;
|
||||
tmp += sec;
|
||||
/* Year 0000 was a leap year */
|
||||
if (year > 0)
|
||||
tmp++;
|
||||
|
||||
/* calculate days from months */
|
||||
tt->tt_sec += moffset[tm->tm_mon];
|
||||
tmp += moffset[tm->tm_mon];
|
||||
|
||||
/* add in this year's leap day, if any */
|
||||
if (((tm->tm_year & 3) == 0) && (tm->tm_mon > 1)) {
|
||||
tt->tt_sec ++;
|
||||
}
|
||||
/* add in this year's leap day, if any */
|
||||
if (tm->tm_mon > 1) {
|
||||
sec = (year % 4) ? 0 : (year % 100) ? 1 : (year % 400) ? 0 : 1;
|
||||
tmp += sec;
|
||||
}
|
||||
|
||||
/* add in days in this month */
|
||||
tt->tt_sec += (tm->tm_mday - 1);
|
||||
/* add in days in this month */
|
||||
tmp += (tm->tm_mday - 1);
|
||||
|
||||
/* this function can handle a range of about 17408 years... */
|
||||
/* 86400 seconds in a day, divided by 128 = 675 */
|
||||
tt->tt_sec *= 675;
|
||||
tmp *= 675;
|
||||
|
||||
/* move high 7 bits into tt_gsec */
|
||||
tt->tt_gsec = tt->tt_sec >> 25;
|
||||
tt->tt_sec -= tt->tt_gsec << 25;
|
||||
tt->tt_gsec = tmp >> 25;
|
||||
tmp -= tt->tt_gsec << 25;
|
||||
|
||||
/* get hours */
|
||||
sec = tm->tm_hour;
|
||||
/* toggle sign bit, keep positive greater than negative */
|
||||
tt->tt_gsec &= 0x7f;
|
||||
tt->tt_gsec ^= 0x40;
|
||||
|
||||
/* convert to minutes */
|
||||
sec *= 60L;
|
||||
sec += tm->tm_min;
|
||||
/* get hours */
|
||||
sec = tm->tm_hour;
|
||||
|
||||
/* convert to seconds */
|
||||
sec *= 60L;
|
||||
sec += tm->tm_sec;
|
||||
/* convert to minutes */
|
||||
sec *= 60L;
|
||||
sec += tm->tm_min;
|
||||
|
||||
/* convert to seconds */
|
||||
sec *= 60L;
|
||||
sec += tm->tm_sec;
|
||||
|
||||
/* add remaining seconds */
|
||||
tt->tt_sec <<= 7;
|
||||
tt->tt_sec += sec;
|
||||
tmp <<= 7;
|
||||
tmp += sec;
|
||||
tt->tt_sec = tmp;
|
||||
|
||||
/* return success */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lutil_parsetime( char *atm, struct lutil_tm *tm )
|
||||
{
|
||||
while (atm && tm) {
|
||||
char *ptr = atm;
|
||||
char *ptr;
|
||||
unsigned i, fracs;
|
||||
int neg = 0;
|
||||
|
||||
if (*atm == '-') {
|
||||
neg = 1;
|
||||
atm++;
|
||||
}
|
||||
ptr = atm;
|
||||
|
||||
/* Is the stamp reasonably long? */
|
||||
for (i=0; isdigit((unsigned char) atm[i]); i++);
|
||||
|
|
@ -234,6 +251,8 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
|
|||
tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
|
||||
tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
|
||||
tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
|
||||
if (neg)
|
||||
tm->tm_year = -tm->tm_year;
|
||||
tm->tm_year -= 1900;
|
||||
/* month 01-12 to 0-11 */
|
||||
tm->tm_mon = *ptr++ - '0';
|
||||
|
|
@ -273,7 +292,10 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
|
|||
for (i = fracs; i<6; i++)
|
||||
tm->tm_usec *= 10;
|
||||
}
|
||||
} else {
|
||||
tm->tm_usec = 0;
|
||||
}
|
||||
tm->tm_usub = 0;
|
||||
|
||||
/* Must be UTC */
|
||||
if (*ptr != 'Z') break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue