Re: Need C/C++ library for datetime/interval type
Posted in 1993
> Our project is using informix databases and needs to manipulate > data of type DATETIME/INTERVAL( like add/sub a legnth of time > in C code). These functions needed goes beyond > the c routines provided by Informix. > > If any netter has done some work like this and is willing to > share the information, or > if someone knows any public ftp site which has this information, > please let me know. It will be very > much appreciated. Here's some stuff I did a couple of years ago. I'm not supporting it, and It may not work perfectly but you can always hack it if you need to. 8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<---- #ifndef lint static char sccsinfo[] = "@(#)udt.ec 1.2 1/14/92"; #endif /*---------------------------------------------------* * * Module: udt * * Purpose: sql datetime / interval utils * * Author: William Hails * * Date: Thu Nov 28 10:01:21 GMT 1991 * *---------------------------------------------------*/ #include <stdio.h> #include <sys/types.h> #include <sys/timeb.h> #include <time.h> #include <ctype.h> #include "datetime.h" char *malloc(); #define new_(type) (type *) malloc(sizeof (type)) #define SECS_IN_DAY 86400 #define SECS_IN_HOUR 3600 #define SECS_IN_MINUTE 60 /*---------------------------------------------------* * Function: dttosecs * * Purpose: converts argument dt to seconds * * Arguments: pointer to dt in subrange day to second * i.e. day to minute or hour to second is OK * will fail with wrong result if any field > 100 * * Returns: int (seconds) * *---------------------------------------------------*/ int dttosecs(dt) dtime_t *dt; { char buf[20]; int dt_sign = 0; int res = 0, i; char *p, *strchr(); if (dttoasc(dt, buf)) return 0; p = buf; while(isspace(*p)) ++p; if (*p == '-') { dt_sign = 1; ++p; } for(i = TU_START(dt->dt_qual); i <= TU_END(dt->dt_qual); i += 2) { char *q; switch(i) { case TU_DAY: if((q = strchr(p, ' ')) != NULL) *q++ = '\\0'; res += atoi(p) * SECS_IN_DAY; p = q; break; case TU_HOUR: if((q = strchr(p, ':')) != NULL) *q++ = '\\0'; res += atoi(p) * SECS_IN_HOUR; p = q; break; case TU_MINUTE: if((q = strchr(p, ':')) != NULL) *q++ = '\\0'; res += atoi(p) * SECS_IN_MINUTE; p = q; break; case TU_SECOND: res += atoi(p); break; } } return (dt_sign ? -res : res); } /*---------------------------------------------------* * Function: itosecs * * Purpose: converts argument interval to seconds * * Arguments: pointer to interval in subrange day to second * i.e. day to minute or hour to second is OK * will fail with wrong result if any field > 100 * * Returns: int (seconds) * *---------------------------------------------------*/ int itosecs(in) intrvl_t *in; { char buf[20]; int in_sign = 0; int res = 0, i; char *p, *strchr(); if (intoasc(in, buf)) return NULL; p = buf; while(isspace(*p)) ++p; if (*p == '-') { in_sign = 1; ++p; } for(i = TU_START(in->in_qual); i <= TU_END(in->in_qual); i += 2) { char *q; switch(i) { case TU_DAY: if((q = strchr(p, ' ')) != NULL) *q++ = '\\0'; res += atoi(p) * SECS_IN_DAY; p = q; break; case TU_HOUR: if((q = strchr(p, ':')) != NULL) *q++ = '\\0'; res += atoi(p) * SECS_IN_HOUR; p = q; break; case TU_MINUTE: if((q = strchr(p, ':')) != NULL) *q++ = '\\0'; res += atoi(p) * SECS_IN_MINUTE; p = q; break; case TU_SECOND: res += atoi(p); break; } } return (in_sign ? -res : res); } /*---------------------------------------------------* * Function: dt_add * * Purpose: adds an interval to a datetime * * Arguments: datetime, interval * * Returns: pointer to datetime (static) or NULL * *---------------------------------------------------*/ dtime_t *dt_add(dt, in) dtime_t *dt; intrvl_t *in; { char buf[50]; long dt_jdate; int dt_hour = 0, dt_minute = 0, dt_second = 0; int in_day = 0, in_hour = 0, in_minute = 0, in_second = 0, in_sign = 0; char *p, *strtok(), *strchr(); int i, ret; static dtime_t res; /* real programmers do it in ASCII! */ if (TU_START(in->in_qual) < TU_DAY || TU_END(in->in_qual) > TU_SECOND) return NULL; res.dt_qual = TU_DTENCODE(TU_YEAR, TU_SECOND); if (dtextend(dt, &res)) return NULL; if (dttoasc(&res, buf)) return NULL; p = strchr(buf, ' '); *p++ = '\\0'; if (rdefmtdate(&dt_jdate, "yyyy-mm-dd", buf)) return NULL; dt_hour = atoi(strtok(p, ":")); dt_minute = atoi(strtok(NULL, ":")); dt_second = atoi(strtok(NULL, ":")); if (intoasc(in, buf)) return NULL; p = buf; while(isspace(*p)) ++p; if (*p == '-') { in_sign = 1; ++p; } for(i = TU_START(in->in_qual); i <= TU_END(in->in_qual); i += 2) { char *q; switch(i) { case TU_DAY: if((q = strchr(p, ' ')) != NULL) *q++ = '\\0'; in_day = atoi(p); p = q; break; case TU_HOUR: if((q = strchr(p, ':')) != NULL) *q++ = '\\0'; in_hour = atoi(p); p = q; break; case TU_MINUTE: if((q = strchr(p, ':')) != NULL) *q++ = '\\0'; in_minute = atoi(p); p = q; break; case TU_SECOND: in_second = atoi(p); break; } } if (in_sign) /* negative interval so subtract */ { int carry, sub; sub = in_second % 60; carry = in_second / 60; if ((dt_second -= sub) < 0) { ++carry; dt_second += 60; } sub = (in_minute + carry) % 60; carry = (in_minute + carry) / 60; if ((dt_minute -= sub) < 0) { ++carry; dt_minute += 60; } sub = (in_hour + carry) % 24; carry = (in_hour + carry) / 24; if ((dt_hour -= sub) < 0) { ++carry; dt_hour += 24; } sub = in_day + carry; dt_jdate -= sub; } else /* positive interval */ { int carry, add; add = in_second % 60; carry = in_second / 60; if ((dt_second += add) >= 60) { ++carry; dt_second -= 60; } add = (in_minute + carry) % 60; carry = (in_minute + carry) / 60; if ((dt_minute += add) >= 60) { ++carry; dt_minute -= 60; } add = (in_hour + carry) %