]> git.sur5r.net Git - openldap/commitdiff
Move time parsers from ppolicy.c to liblutil; preserve greater precision
authorHoward Chu <hyc@openldap.org>
Tue, 28 Sep 2004 12:12:13 +0000 (12:12 +0000)
committerHoward Chu <hyc@openldap.org>
Tue, 28 Sep 2004 12:12:13 +0000 (12:12 +0000)
include/lutil.h
libraries/liblutil/utils.c

index 8c7894e16f516a5dc05bffac2205557a50616850..462d5685560fdb0fba098909bc5b7957cf68806f 100644 (file)
@@ -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 ));
index 4813a063e23ded86e5785d5e02f445ccdb8184af..2666f85214f9ac04771e21434c82376c08feefc9 100644 (file)
@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <ac/stdlib.h>
 #include <ac/string.h>
+#include <ac/ctype.h>
 #include <ac/unistd.h>
 #include <ac/time.h>
 #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