diff --git a/include/lutil.h b/include/lutil.h index 6cf8aad0c4..8b3f391d71 100644 --- a/include/lutil.h +++ b/include/lutil.h @@ -169,8 +169,8 @@ typedef struct lutil_tm { } lutil_tm; typedef struct lutil_timet { - unsigned int tt_sec; /* seconds since 0000 */ - int tt_gsec; /* seconds since 0000, high 7 bits, sign-flipped */ + unsigned int tt_sec; /* seconds since epoch, 0000 or 1970 */ + int tt_gsec; /* seconds since epoch, high 7 bits, maybe sign-flipped */ /* sign flipped to sort properly as unsigned ints */ unsigned int tt_usec; /* microseconds */ } lutil_timet; @@ -180,11 +180,16 @@ LDAP_LUTIL_F( int ) lutil_parsetime LDAP_P(( char *atm, struct lutil_tm * )); -/* Convert structured time to time in seconds since 1900 */ +/* Convert structured time to time in seconds since 1970 (Unix epoch) */ LDAP_LUTIL_F( int ) lutil_tm2time LDAP_P(( struct lutil_tm *, struct lutil_timet * )); +/* Convert structured time to time in seconds since 0000 (Proleptic Gregorian) */ +LDAP_LUTIL_F( int ) +lutil_tm2gtime LDAP_P(( + struct lutil_tm *, struct lutil_timet * )); + #ifdef _WIN32 LDAP_LUTIL_F( void ) lutil_slashpath LDAP_P(( char* path )); diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c index 94a33ff318..d3a80d18c9 100644 --- a/libraries/liblutil/utils.c +++ b/libraries/liblutil/utils.c @@ -151,14 +151,78 @@ 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 }; + 273, 304, 334 }; + int sec; + + 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; + + /* count leap days in preceding years */ + tt->tt_sec += ((tm->tm_year -69) >> 2); + + /* calculate days from months */ + tt->tt_sec += 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 days in this month */ + tt->tt_sec += (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; + + /* move high 7 bits into tt_gsec */ + tt->tt_gsec = tt->tt_sec >> 25; + tt->tt_sec -= tt->tt_gsec << 25; + + /* get hours */ + sec = tm->tm_hour; + + /* 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; + + /* return success */ + return 0; +} + +/* Proleptic Gregorian Calendar, 1BCE = year 0 */ + +int lutil_tm2gtime( 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, year; long tmp; @@ -169,7 +233,6 @@ int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt ) year = tm->tm_year + 1900; tmp = year * 365; - /* add in leap days */ sec = (year - 1) / 4; tmp += sec; @@ -181,7 +244,7 @@ int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt ) if (year > 0) tmp++; - /* calculate days from months */ + /* calculate days from months */ tmp += moffset[tm->tm_mon]; /* add in this year's leap day, if any */ diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 7f9d8d0f0e..92407391e9 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -5843,7 +5843,7 @@ int generalizedTimeIndexer( assert(values[i].bv_val != NULL && values[i].bv_len >= 10); /* Use 40 bits of time for key */ if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) { - lutil_tm2time( &tm, &tt ); + lutil_tm2gtime( &tm, &tt ); tmp[0] = tt.tt_gsec & 0xff; tmp[4] = tt.tt_sec & 0xff; tt.tt_sec >>= 8; @@ -5890,7 +5890,7 @@ int generalizedTimeFilter( if ( value->bv_val && value->bv_len >= 10 && lutil_parsetime( value->bv_val, &tm ) == 0 ) { - lutil_tm2time( &tm, &tt ); + lutil_tm2gtime( &tm, &tt ); tmp[0] = tt.tt_gsec & 0xff; tmp[4] = tt.tt_sec & 0xff; tt.tt_sec >>= 8;