From: Howard Chu Date: Tue, 28 Sep 2004 12:12:13 +0000 (+0000) Subject: Move time parsers from ppolicy.c to liblutil; preserve greater precision X-Git-Tag: OPENLDAP_REL_ENG_2_3_0ALPHA~486 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1ca9556c1bcea897f851c9141e8d62eff6f9e266;p=openldap Move time parsers from ppolicy.c to liblutil; preserve greater precision --- diff --git a/include/lutil.h b/include/lutil.h index 8c7894e16f..462d568556 100644 --- a/include/lutil.h +++ b/include/lutil.h @@ -147,6 +147,30 @@ lutil_progname LDAP_P(( int argc, char *argv[] )); +struct slap_tm { + int tm_sec; /* seconds 0-60 (1 leap second) */ + int tm_min; /* minutes 0-59 */ + int tm_hour; /* hours 0-23 */ + int tm_mday; /* day 1-31 */ + int tm_mon; /* month 0-11 */ + int tm_year; /* year - 1900 */ + int tm_usec; /* microseconds */ +} slap_tm; + +struct slap_timet { + unsigned int tt_sec; /* seconds since 1900 */ + int tt_gsec; /* seconds since 1900, high 7 bits */ + unsigned int tt_usec; /* microseconds */ +} slap_timet; + +LDAP_LUTIL_F( int ) +lutil_parsetime LDAP_P(( + char *atm, struct slap_tm * )); + +LDAP_LUTIL_F( int ) +lutil_tm2time LDAP_P(( + struct slap_tm *, struct slap_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 4813a063e2..2666f85214 100644 --- a/libraries/liblutil/utils.c +++ b/libraries/liblutil/utils.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #ifdef HAVE_IO_H @@ -135,6 +136,130 @@ size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta ) return ret + 5; } +int lutil_tm2time( struct slap_tm *tm, struct slap_timet *tt ) +{ + static int moffset[12] = { + 0, 31, 59, 90, 120, + 151, 181, 212, 243, + 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); + + /* 86400 seconds in a day, divided by 128 = 675 */ + tt->tt_sec *= 675; + tt->tt_gsec = tt->tt_sec >> 25; + tt->tt_sec -= tt->tt_gsec << 25; + + /* convert to hours */ + sec = tm->tm_hour; + + /* convert to minutes */ + sec *= 60L; + sec += tm->tm_min; + + /* convert to seconds */ + sec *= 60L; + sec += tm->tm_sec; + + tt->tt_sec <<= 7; + tt->tt_sec += sec; + + /* return success */ + return 0; +} + +int lutil_parsetime( char *atm, struct slap_tm *tm ) +{ + while (atm && tm) { + char *ptr = atm; + int i, fracs; + + /* Is the stamp reasonably long? */ + for (i=0; isdigit(atm[i]); i++); + if (i < sizeof("00000101000000")-1) + break; + + /* + * parse the time into a struct tm + */ + /* 4 digit year to year - 1900 */ + tm->tm_year = *ptr++ - '0'; + 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'; + tm->tm_year -= 1900; + /* month 01-12 to 0-11 */ + tm->tm_mon = *ptr++ - '0'; + tm->tm_mon *=10; tm->tm_mon += *ptr++ - '0'; + if (tm->tm_mon < 1 || tm->tm_mon > 12) break; + tm->tm_mon--; + + /* day of month 01-31 */ + tm->tm_mday = *ptr++ - '0'; + tm->tm_mday *=10; tm->tm_mday += *ptr++ - '0'; + if (tm->tm_mday < 1 || tm->tm_mday > 31) break; + + /* Hour 00-23 */ + tm->tm_hour = *ptr++ - '0'; + tm->tm_hour *=10; tm->tm_hour += *ptr++ - '0'; + if (tm->tm_hour < 0 || tm->tm_hour > 23) break; + + /* Minute 00-59 */ + tm->tm_min = *ptr++ - '0'; + tm->tm_min *=10; tm->tm_min += *ptr++ - '0'; + if (tm->tm_min < 0 || tm->tm_min > 59) break; + + /* Second 00-61 */ + tm->tm_sec = *ptr++ - '0'; + tm->tm_sec *=10; tm->tm_sec += *ptr++ - '0'; + if (tm->tm_sec < 0 || tm->tm_sec > 61) break; + + /* Fractions of seconds */ + for (i = 0, fracs = 0;isdigit(*ptr);) { + i*=10; i+= *ptr++ - '0'; + fracs++; + } + tm->tm_usec = i; + if (i) { + for (i = fracs; i<6; i++) + tm->tm_usec *= 10; + } + + /* Must be UTC */ + if (*ptr != 'Z') break; + + return 0; + } + return -1; +} /* strcopy is like strcpy except it returns a pointer to the trailing NUL of * the result string. This allows fast construction of catenated strings