aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/nabstime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/nabstime.c')
-rw-r--r--src/backend/utils/adt/nabstime.c877
1 files changed, 221 insertions, 656 deletions
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index 83858920780..e678805c989 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.13 1997/01/27 01:51:21 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.14 1997/03/14 23:20:31 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,494 +22,174 @@
#endif
#include "access/xact.h"
-#define MAXDATEFIELDS 25
-
-#define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\t')
-
-/* this is fast but dirty. note the return's in the middle. */
-#define GOBBLE_NUM(cp, c, x, ip) \
- (c) = *(cp)++; \
- if ((c) < '0' || (c) > '9') \
- return -1; /* missing digit */ \
- (x) = (c) - '0'; \
- (c) = *(cp)++; \
- if ((c) >= '0' && (c) <= '9') { \
- (x) = 10*(x) + (c) - '0'; \
- (c) = *(cp)++; \
- } \
- if ((c) != ':' && (c) != '\0' && !ISSPACE(c)) \
- return -1; /* missing colon */ \
- *(ip) = (x) /* N.B.: no semi-colon here */
-
-#define EPOCH 1970
-#define DAYS_PER_400YRS (time_t)146097
-#define DAYS_PER_4YRS (time_t)1461
-#define SECS_PER_DAY 86400
-#define SECS_PER_HOUR 3600
-#define DIVBY4(n) ((n) >> 2)
-#define YRNUM(c, y) (DIVBY4(DAYS_PER_400YRS*(c)) + DIVBY4(DAYS_PER_4YRS*(y)))
-#define DAYNUM(c,y,mon,d) (YRNUM((c), (y)) + mdays[mon] + (d))
-#define EPOCH_DAYNUM DAYNUM(19, 69, 10, 1) /* really January 1, 1970 */
+#if USE_EURODATES
+extern int EuroDates;
+#endif
+
+#if FALSE
+#define MAXDATELEN 47
+#define MAXDATEFIELDS 25
+#endif
+
#define MIN_DAYNUM -24856 /* December 13, 1901 */
#define MAX_DAYNUM 24854 /* January 18, 2038 */
-/* definitions for squeezing values into "value" */
-#define ABS_SIGNBIT 0200
-#define VALMASK 0177
-#define NEG(n) ((n)|ABS_SIGNBIT)
-#define SIGNEDCHAR(c) ((c)&ABS_SIGNBIT? -((c)&VALMASK): (c))
-#define FROMVAL(tp) (-SIGNEDCHAR((tp)->value) * 10) /* uncompress */
-#define TOVAL(tp, v) ((tp)->value = ((v) < 0? NEG((-(v))/10): (v)/10))
-#define IsLeapYear(yr) ((yr%4) == 0)
-
-char nmdays[] = {
- 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-/* days since start of year. mdays[0] is March, mdays[11] is February */
-static short mdays[] = {
- 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337
-};
-
-/* exports */
-static int dtok_numparsed;
-
-/*
- * to keep this table reasonably small, we divide the lexval for TZ and DTZ
- * entries by 10 and truncate the text field at MAXTOKLEN characters.
- * the text field is not guaranteed to be NUL-terminated.
- */
-static datetkn datetktbl[] = {
-/* text token lexval */
-{ "acsst", DTZ, 63}, /* Cent. Australia */
-{ "acst", TZ, 57}, /* Cent. Australia */
-{ "adt", DTZ, NEG(18)}, /* Atlantic Daylight Time */
-{ "aesst", DTZ, 66}, /* E. Australia */
-{ "aest", TZ, 60}, /* Australia Eastern Std Time */
-{ "ahst", TZ, 60}, /* Alaska-Hawaii Std Time */
-{ "am", AMPM, AM},
-{ "apr", MONTH, 4},
-{ "april", MONTH, 4},
-{ "ast", TZ, NEG(24)}, /* Atlantic Std Time (Canada) */
-{ "at", PG_IGNORE, 0}, /* "at" (throwaway) */
-{ "aug", MONTH, 8},
-{ "august", MONTH, 8},
-{ "awsst", DTZ, 54}, /* W. Australia */
-{ "awst", TZ, 48}, /* W. Australia */
-{ "bst", TZ, 6}, /* British Summer Time */
-{ "bt", TZ, 18}, /* Baghdad Time */
-{ "cadt", DTZ, 63}, /* Central Australian DST */
-{ "cast", TZ, 57}, /* Central Australian ST */
-{ "cat", TZ, NEG(60)}, /* Central Alaska Time */
-{ "cct", TZ, 48}, /* China Coast */
-{ "cdt", DTZ, NEG(30)}, /* Central Daylight Time */
-{ "cet", TZ, 6}, /* Central European Time */
-{ "cetdst", DTZ, 12}, /* Central European Dayl.Time */
-{ "cst", TZ, NEG(36)}, /* Central Standard Time */
-{ "dec", MONTH, 12},
-{ "decemb", MONTH, 12},
-{ "dnt", TZ, 6}, /* Dansk Normal Tid */
-{ "dst", PG_IGNORE, 0},
-{ "east", TZ, NEG(60)}, /* East Australian Std Time */
-{ "edt", DTZ, NEG(24)}, /* Eastern Daylight Time */
-{ "eet", TZ, 12}, /* East. Europe, USSR Zone 1 */
-{ "eetdst", DTZ, 18}, /* Eastern Europe */
-{ "est", TZ, NEG(30)}, /* Eastern Standard Time */
-{ "feb", MONTH, 2},
-{ "februa", MONTH, 2},
-{ "fri", PG_IGNORE, 5},
-{ "friday", PG_IGNORE, 5},
-{ "fst", TZ, 6}, /* French Summer Time */
-{ "fwt", DTZ, 12}, /* French Winter Time */
-{ "gmt", TZ, 0}, /* Greenwish Mean Time */
-{ "gst", TZ, 60}, /* Guam Std Time, USSR Zone 9 */
-{ "hdt", DTZ, NEG(54)}, /* Hawaii/Alaska */
-{ "hmt", DTZ, 18}, /* Hellas ? ? */
-{ "hst", TZ, NEG(60)}, /* Hawaii Std Time */
-{ "idle", TZ, 72}, /* Intl. Date Line, East */
-{ "idlw", TZ, NEG(72)}, /* Intl. Date Line, West */
-{ "ist", TZ, 12}, /* Israel */
-{ "it", TZ, 22}, /* Iran Time */
-{ "jan", MONTH, 1},
-{ "januar", MONTH, 1},
-{ "jst", TZ, 54}, /* Japan Std Time,USSR Zone 8 */
-{ "jt", TZ, 45}, /* Java Time */
-{ "jul", MONTH, 7},
-{ "july", MONTH, 7},
-{ "jun", MONTH, 6},
-{ "june", MONTH, 6},
-{ "kst", TZ, 54}, /* Korea Standard Time */
-{ "ligt", TZ, 60}, /* From Melbourne, Australia */
-{ "mar", MONTH, 3},
-{ "march", MONTH, 3},
-{ "may", MONTH, 5},
-{ "mdt", DTZ, NEG(36)}, /* Mountain Daylight Time */
-{ "mest", DTZ, 12}, /* Middle Europe Summer Time */
-{ "met", TZ, 6}, /* Middle Europe Time */
-{ "metdst", DTZ, 12}, /* Middle Europe Daylight Time*/
-{ "mewt", TZ, 6}, /* Middle Europe Winter Time */
-{ "mez", TZ, 6}, /* Middle Europe Zone */
-{ "mon", PG_IGNORE, 1},
-{ "monday", PG_IGNORE, 1},
-{ "mst", TZ, NEG(42)}, /* Mountain Standard Time */
-{ "mt", TZ, 51}, /* Moluccas Time */
-{ "ndt", DTZ, NEG(15)}, /* Nfld. Daylight Time */
-{ "nft", TZ, NEG(21)}, /* Newfoundland Standard Time */
-{ "nor", TZ, 6}, /* Norway Standard Time */
-{ "nov", MONTH, 11},
-{ "novemb", MONTH, 11},
-{ "nst", TZ, NEG(21)}, /* Nfld. Standard Time */
-{ "nt", TZ, NEG(66)}, /* Nome Time */
-{ "nzdt", DTZ, 78}, /* New Zealand Daylight Time */
-{ "nzst", TZ, 72}, /* New Zealand Standard Time */
-{ "nzt", TZ, 72}, /* New Zealand Time */
-{ "oct", MONTH, 10},
-{ "octobe", MONTH, 10},
-{ "on", PG_IGNORE, 0}, /* "on" (throwaway) */
-{ "pdt", DTZ, NEG(42)}, /* Pacific Daylight Time */
-{ "pm", AMPM, PM},
-{ "pst", TZ, NEG(48)}, /* Pacific Standard Time */
-{ "sadt", DTZ, 63}, /* S. Australian Dayl. Time */
-{ "sast", TZ, 57}, /* South Australian Std Time */
-{ "sat", PG_IGNORE, 6},
-{ "saturd", PG_IGNORE, 6},
-{ "sep", MONTH, 9},
-{ "sept", MONTH, 9},
-{ "septem", MONTH, 9},
-{ "set", TZ, NEG(6)}, /* Seychelles Time ?? */
-{ "sst", DTZ, 12}, /* Swedish Summer Time */
-{ "sun", PG_IGNORE, 0},
-{ "sunday", PG_IGNORE, 0},
-{ "swt", TZ, 6}, /* Swedish Winter Time */
-{ "thu", PG_IGNORE, 4},
-{ "thur", PG_IGNORE, 4},
-{ "thurs", PG_IGNORE, 4},
-{ "thursd", PG_IGNORE, 4},
-{ "tue", PG_IGNORE, 2},
-{ "tues", PG_IGNORE, 2},
-{ "tuesda", PG_IGNORE, 2},
-{ "ut", TZ, 0},
-{ "utc", TZ, 0},
-{ "wadt", DTZ, 48}, /* West Australian DST */
-{ "wast", TZ, 42}, /* West Australian Std Time */
-{ "wat", TZ, NEG(6)}, /* West Africa Time */
-{ "wdt", DTZ, 54}, /* West Australian DST */
-{ "wed", PG_IGNORE, 3},
-{ "wednes", PG_IGNORE, 3},
-{ "weds", PG_IGNORE, 3},
-{ "wet", TZ, 0}, /* Western Europe */
-{ "wetdst", DTZ, 6}, /* Western Europe */
-{ "wst", TZ, 48}, /* West Australian Std Time */
-{ "ydt", DTZ, NEG(48)}, /* Yukon Daylight Time */
-{ "yst", TZ, NEG(54)}, /* Yukon Standard Time */
-{ "zp4", TZ, NEG(24)}, /* GMT +4 hours. */
-{ "zp5", TZ, NEG(30)}, /* GMT +5 hours. */
-{ "zp6", TZ, NEG(36)}, /* GMT +6 hours. */
-};
-
-static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
/*
* parse and convert absolute date in timestr (the normal interface)
*
* Returns the number of seconds since epoch (January 1 1970 GMT)
*/
+
+#ifndef USE_POSIX_TIME
+long int timezone;
+long int daylight;
+#endif
+
AbsoluteTime
-nabstimein(char* timestr)
+GetCurrentAbsoluteTime(void)
{
- int tz = 0;
- struct tm date;
-
- if (!timestr)
- return INVALID_ABSTIME;
- while (ISSPACE(*timestr))
- ++timestr;
-
- if (!strcasecmp(timestr, "epoch"))
- return EPOCH_ABSTIME;
- if (!strcasecmp(timestr, "now"))
- return GetCurrentTransactionStartTime();
- if (!strcasecmp(timestr, "current"))
- return CURRENT_ABSTIME;
- if (!strcasecmp(timestr, "infinity"))
- return NOEND_ABSTIME;
- if (!strcasecmp(timestr, "-infinity"))
- return NOSTART_ABSTIME;
- if (prsabsdate(timestr, &date, &tz) < 0)
- return INVALID_ABSTIME;
- return dateconv(&date, tz);
-}
+ time_t now;
-/*
- * just parse the absolute date in timestr and get back a broken-out date.
- */
-int
-prsabsdate(char *timestr,
- struct tm *tm,
- int *tzp) /* - minutes west */
-{
- register int nf;
- char *fields[MAXDATEFIELDS];
- static char delims[] = "- \t\n/,";
-
- nf = split(timestr, fields, MAXDATEFIELDS, delims+1);
- if (nf > MAXDATEFIELDS)
- return -1;
- if (tryabsdate(fields, nf, tm, tzp) < 0) {
- register char *p = timestr;
-
- /*
- * could be a DEC-date; glue it all back together, split it
- * with dash as a delimiter and try again. Yes, this is a
- * hack, but so are DEC-dates.
- */
- while (--nf > 0) {
- while (*p++ != '\0')
- ;
- p[-1] = ' ';
- }
- nf = split(timestr, fields, MAXDATEFIELDS, delims);
- if (nf > MAXDATEFIELDS)
- return -1;
- if (tryabsdate(fields, nf, tm, tzp) < 0)
- return -1;
- }
- return 0;
-}
+#ifdef USE_POSIX_TIME
+ now = time(NULL);
-/*
- * try to parse pre-split timestr as an absolute date
- */
-int
-tryabsdate(char *fields[], int nf, struct tm *tm, int *tzp)
-{
- register int i;
- register datetkn *tp;
- register long flg = 0, ty;
- int mer = HR24, bigval = -1;
-#ifndef USE_POSIX_TIME
- struct timeb now; /* the old V7-ism */
-
- (void) ftime(&now);
- *tzp = now.timezone;
-#else /* USE_POSIX_TIME */
#if defined(HAVE_TZSET) && defined(HAVE_INT_TIMEZONE)
- tzset();
-#ifndef win32
- *tzp = timezone / 60; /* this is an X/Open-ism */
-#else
- *tzp = _timezone / 60; /* this is an X/Open-ism */
-#endif /* win32 */
+ tzset();
#else /* !HAVE_TZSET */
- time_t now = time((time_t *) NULL);
struct tm *tmnow = localtime(&now);
-
- *tzp = - tmnow->tm_gmtoff / 60; /* tm_gmtoff is Sun/DEC-ism */
+
+ timezone = - tmnow->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
+ daylight = (tmnow->tm_isdst > 0);
#endif
+
+#else /* ! USE_POSIX_TIME */
+ struct timeb tbnow; /* the old V7-ism */
+
+ (void) ftime(&tbnow);
+ now = tbnow.time;
+ timezone = tbnow.timezone * 60;
+ daylight = (tbnow.dstflag != 0);
#endif
-
- tm->tm_mday = tm->tm_mon = tm->tm_year = -1; /* mandatory */
- tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
- tm->tm_isdst = -1; /* assume we don't know. */
- dtok_numparsed = 0;
-
- for (i = 0; i < nf; i++) {
- if (fields[i][0] == '\0')
- continue;
- tp = datetoktype(fields[i], &bigval);
- ty = (1L << tp->type) & ~(1L << PG_IGNORE);
- if (flg&ty)
- return -1; /* repeated type */
- flg |= ty;
- switch (tp->type) {
- case YEAR:
- tm->tm_year = bigval;
- break;
- case DAY:
- tm->tm_mday = bigval;
- break;
- case MONTH:
- tm->tm_mon = tp->value;
- break;
- case TIME:
- if (parsetime(fields[i], tm) < 0)
- return -1;
- break;
- case DTZ:
- tm->tm_isdst++;
- /* FALLTHROUGH */
- case TZ:
- *tzp = FROMVAL(tp);
- break;
- case PG_IGNORE:
- break;
- case AMPM:
- mer = tp->value;
- break;
- default:
- return -1; /* bad token type: CANTHAPPEN */
- }
- }
- if (tm->tm_year == -1 || tm->tm_mon == -1 || tm->tm_mday == -1)
- return -1; /* missing component */
- if (mer == PM)
- tm->tm_hour += 12;
- return 0;
-}
+
+ return((AbsoluteTime) now);
+} /* GetCurrentAbsoluteTime() */
-/* return -1 on failure */
-int
-parsetime(char *time, struct tm *tm)
+void
+GetCurrentTime(struct tm *tm)
{
- register char c;
- register int x;
-
- tm->tm_sec = 0;
- GOBBLE_NUM(time, c, x, &tm->tm_hour);
- if (c != ':')
- return -1; /* only hour; too short */
- GOBBLE_NUM(time, c, x, &tm->tm_min);
- if (c != ':')
- return 0; /* no seconds; okay */
- GOBBLE_NUM(time, c, x, &tm->tm_sec);
- /* this may be considered too strict. garbage at end of time? */
- return (c == '\0' || ISSPACE(c)? 0: -1);
-}
+ time_t now;
+ struct tm *tt;
+ now = GetCurrentTransactionStartTime();
+ tt = gmtime( &now);
-/*
- * split - divide a string into fields, like awk split()
+ tm->tm_year = tt->tm_year+1900;
+ tm->tm_mon = tt->tm_mon+1;
+ tm->tm_mday = tt->tm_mday;
+ tm->tm_hour = tt->tm_hour;
+ tm->tm_min = tt->tm_min;
+ tm->tm_sec = tt->tm_sec;
+ tm->tm_isdst = tt->tm_isdst;
+
+ return;
+} /* GetCurrentTime() */
+
+
+/* nabstimein()
+ * Decode date/time string and return abstime.
*/
-int /* number of fields, including overflow */
-split(char *string,
- char *fields[], /* list is not NULL-terminated */
- int nfields, /* number of entries available in fields[] */
- char *sep) /* "" white, "c" single char, "ab" [ab]+ */
+AbsoluteTime
+nabstimein(char* str)
{
- register char *p = string;
- register char c; /* latest character */
- register char sepc = sep[0];
- register char sepc2;
- register int fn;
- register char **fp = fields;
- register char *sepp;
- register int trimtrail;
-
- /* white space */
- if (sepc == '\0') {
- while ((c = *p++) == ' ' || c == '\t')
- continue;
- p--;
- trimtrail = 1;
- sep = " \t"; /* note, code below knows this is 2 long */
- sepc = ' ';
- } else
- trimtrail = 0;
- sepc2 = sep[1]; /* now we can safely pick this up */
-
- /* catch empties */
- if (*p == '\0')
- return(0);
-
- /* single separator */
- if (sepc2 == '\0') {
- fn = nfields;
- for (;;) {
- *fp++ = p;
- fn--;
- if (fn == 0)
- break;
- while ((c = *p++) != sepc)
- if (c == '\0')
- return(nfields - fn);
- *(p-1) = '\0';
- }
- /* we have overflowed the fields vector -- just count them */
- fn = nfields;
- for (;;) {
- while ((c = *p++) != sepc)
- if (c == '\0')
- return(fn);
- fn++;
- }
- /* not reached */
- }
-
- /* two separators */
- if (sep[2] == '\0') {
- fn = nfields;
- for (;;) {
- *fp++ = p;
- fn--;
- while ((c = *p++) != sepc && c != sepc2)
- if (c == '\0') {
- if (trimtrail && **(fp-1) == '\0')
- fn++;
- return(nfields - fn);
- }
- if (fn == 0)
- break;
- *(p-1) = '\0';
- while ((c = *p++) == sepc || c == sepc2)
- continue;
- p--;
- }
- /* we have overflowed the fields vector -- just count them */
- fn = nfields;
- while (c != '\0') {
- while ((c = *p++) == sepc || c == sepc2)
- continue;
- p--;
- fn++;
- while ((c = *p++) != '\0' && c != sepc && c != sepc2)
- continue;
- }
- /* might have to trim trailing white space */
- if (trimtrail) {
- p--;
- while ((c = *--p) == sepc || c == sepc2)
- continue;
- p++;
- if (*p != '\0') {
- if (fn == nfields+1)
- *p = '\0';
- fn--;
- }
- }
- return(fn);
- }
-
- /* n separators */
- fn = 0;
- for (;;) {
- if (fn < nfields)
- *fp++ = p;
- fn++;
- for (;;) {
- c = *p++;
- if (c == '\0')
- return(fn);
- sepp = sep;
- while ((sepc = *sepp++) != '\0' && sepc != c)
- continue;
- if (sepc != '\0') /* it was a separator */
- break;
- }
- if (fn < nfields)
- *(p-1) = '\0';
- for (;;) {
- c = *p++;
- sepp = sep;
- while ((sepc = *sepp++) != '\0' && sepc != c)
- continue;
- if (sepc == '\0') /* it wasn't a separator */
- break;
- }
- p--;
- }
-
- /* not reached */
-}
+ int sec;
+ double fsec;
+ int day, tz = 0;
+ struct tm date, *tm = &date;
+
+ char *field[MAXDATEFIELDS];
+ char lowstr[MAXDATELEN+1];
+ int dtype;
+ int nf, ftype[MAXDATEFIELDS];
+
+ if (!PointerIsValid(str))
+ elog(WARN,"Bad (null) abstime external representation",NULL);
+
+ if (strlen(str) > MAXDATELEN)
+ elog( WARN, "Bad (length) abstime external representation '%s'",str);
+
+ if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
+ || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
+ elog( WARN, "Bad abstime external representation '%s'",str);
+
+#ifdef DATEDEBUG
+printf( "nabstimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE);
+#endif
+
+ switch (dtype) {
+ case DTK_DATE:
+#if FALSE
+ return(dateconv( &date, tz));
+#endif
+ /* validate, before going out of range on some members */
+ if (tm->tm_year < 1901 || tm->tm_year > 2038
+ || tm->tm_mon < 1 || tm->tm_mon > 12
+ || tm->tm_mday < 1 || tm->tm_mday > 31
+ || tm->tm_hour < 0 || tm->tm_hour >= 24
+ || tm->tm_min < 0 || tm->tm_min > 59
+ || tm->tm_sec < 0 || tm->tm_sec > 59)
+ return INVALID_ABSTIME;
+
+ day = (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j( 1970, 1, 1));
+
+ /* check for time out of range */
+ if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM))
+ return INVALID_ABSTIME;
+
+ /* convert to seconds */
+ sec = tm->tm_sec + tz + (tm->tm_min +(day*24 + tm->tm_hour)*60)*60;
+
+ /* check for overflow */
+ if ((day == MAX_DAYNUM && sec < 0) ||
+ (day == MIN_DAYNUM && sec > 0))
+ return INVALID_ABSTIME;
+
+ /* daylight correction */
+ if (tm->tm_isdst < 0) { /* unknown; find out */
+ tm->tm_isdst = (daylight > 0);
+ };
+ if (tm->tm_isdst > 0)
+ sec -= 60*60;
+
+ /* check for reserved values (e.g. "current" on edge of usual range */
+ if (!AbsoluteTimeIsReal(sec))
+ return INVALID_ABSTIME;
+
+ return sec;
+
+ case DTK_EPOCH:
+ return EPOCH_ABSTIME;
+
+ case DTK_CURRENT:
+ return CURRENT_ABSTIME;
+
+ case DTK_LATE:
+ return NOEND_ABSTIME;
+
+ case DTK_EARLY:
+ return NOSTART_ABSTIME;
+
+ case DTK_INVALID:
+ return INVALID_ABSTIME;
+
+ default:
+ };
+
+ elog(WARN,"Bad abstime (internal coding error) '%s'",str);
+ return INVALID_ABSTIME;
+} /* nabstimein() */
+
/*
* Given an AbsoluteTime return the English text version of the date
@@ -529,11 +209,11 @@ nabstimeout(AbsoluteTime time)
char* result;
switch (time) {
- case EPOCH_ABSTIME: (void) strcpy(buf, "epoch"); break;
- case INVALID_ABSTIME: (void) strcpy(buf, "Invalid Abstime"); break;
- case CURRENT_ABSTIME: (void) strcpy(buf, "current"); break;
- case NOEND_ABSTIME: (void) strcpy(buf, "infinity"); break;
- case NOSTART_ABSTIME: (void) strcpy(buf, "-infinity"); break;
+ case EPOCH_ABSTIME: (void) strcpy(buf, EPOCH); break;
+ case INVALID_ABSTIME: (void) strcpy(buf, INVALID); break;
+ case CURRENT_ABSTIME: (void) strcpy(buf, DCURRENT); break;
+ case NOEND_ABSTIME: (void) strcpy(buf, LATE); break;
+ case NOSTART_ABSTIME: (void) strcpy(buf, EARLY); break;
default:
/* hack -- localtime happens to work for negative times */
(void) strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %Y %Z",
@@ -545,25 +225,36 @@ nabstimeout(AbsoluteTime time)
return result;
}
+
/* turn a (struct tm) and a few variables into a time_t, with range checking */
AbsoluteTime
dateconv(register struct tm *tm, int zone)
{
tm->tm_wday = tm->tm_yday = 0;
-
+
+#if FALSE
+ if (tm->tm_year < 70) {
+ tm->tm_year += 2000;
+ } else if (tm->tm_year < 1000) {
+ tm->tm_year += 1900;
+ };
+#endif
+
/* validate, before going out of range on some members */
- if (tm->tm_year < 0 || tm->tm_mon < 1 || tm->tm_mon > 12 ||
- tm->tm_mday < 1 || tm->tm_hour < 0 || tm->tm_hour >= 24 ||
- tm->tm_min < 0 || tm->tm_min > 59 ||
- tm->tm_sec < 0 || tm->tm_sec > 59)
- return -1;
-
+ if (tm->tm_year < 1901 || tm->tm_year > 2038
+ || tm->tm_mon < 1 || tm->tm_mon > 12
+ || tm->tm_mday < 1 || tm->tm_mday > 31
+ || tm->tm_hour < 0 || tm->tm_hour >= 24
+ || tm->tm_min < 0 || tm->tm_min > 59
+ || tm->tm_sec < 0 || tm->tm_sec > 59)
+ return INVALID_ABSTIME;
+
/*
* zone should really be -zone, and tz should be set to tp->value, not
* -tp->value. Or the table could be fixed.
*/
- tm->tm_min += zone; /* mktime lets it be out of range */
-
+ tm->tm_sec += zone; /* mktime lets it be out of range */
+
/* convert to seconds */
return qmktime(tm);
}
@@ -575,201 +266,78 @@ dateconv(register struct tm *tm, int zone)
* and tm_yday.
*/
time_t
-qmktime(struct tm *tp)
+qmktime(struct tm *tm)
{
- register int mon = tp->tm_mon;
- register int day = tp->tm_mday, year = tp->tm_year;
- register time_t daynum;
- time_t secondnum;
- register int century;
-
+ time_t sec;
+
+ int day;
+
+#if FALSE
/* If it was a 2 digit year */
- if (year < 100)
- year += 1900;
-
- /*
- * validate day against days-per-month table, with leap-year
- * correction
- */
- if (day > nmdays[mon])
- if (mon != 2 ||
- (year % 4 == 0 &&
- ((year % 100 != 0 || year % 400 == 0)) && day > 29))
- return -1; /* day too large for month */
-
- /* split year into century and year-of-century */
- century = year / 100;
- year %= 100;
- /*
- * We calculate the day number exactly, assuming the calendar has
- * always had the current leap year rules. (The leap year rules are
- * to compensate for the fact that the Earth's revolution around the
- * Sun takes 365.2425 days). We first need to rotate months so March
- * is 0, since we want the last month to have the reduced number of
- * days.
- */
- if (mon > 2)
- mon -= 3;
- else {
- mon += 9;
- if (year == 0) {
- century--;
- year = 99;
- } else
- --year;
- }
- daynum = -EPOCH_DAYNUM + DAYNUM(century, year, mon, day);
-
+ if (tm->tm_year < 100)
+ tm->tm_year += 1900;
+#endif
+
+ day = (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j( 1970, 1, 1));
+
/* check for time out of range */
- if (daynum < MIN_DAYNUM || daynum > MAX_DAYNUM)
+ if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM))
return INVALID_ABSTIME;
-
+
/* convert to seconds */
- secondnum =
- tp->tm_sec + (tp->tm_min +(daynum*24 + tp->tm_hour)*60)*60;
-
+ sec = tm->tm_sec + (tm->tm_min +(day*24 + tm->tm_hour)*60)*60;
+
/* check for overflow */
- if ((daynum == MAX_DAYNUM && secondnum < 0) ||
- (daynum == MIN_DAYNUM && secondnum > 0))
+ if ((day == MAX_DAYNUM && sec < 0) ||
+ (day == MIN_DAYNUM && sec > 0))
return INVALID_ABSTIME;
-
- /* check for "current", "infinity", "-infinity" */
- if (!AbsoluteTimeIsReal(secondnum))
+
+ /* check for reserved values (e.g. "current" on edge of usual range */
+ if (!AbsoluteTimeIsReal(sec))
return INVALID_ABSTIME;
-
- /* daylight correction */
- if (tp->tm_isdst < 0) /* unknown; find out */
- {
- struct tm *result;
-
- /* NT returns NULL for any time before 1/1/70 */
- result = localtime(&secondnum);
- if (result == NULL)
- return INVALID_ABSTIME;
- else
- tp->tm_isdst = result->tm_isdst;
- }
- if (tp->tm_isdst > 0)
- secondnum -= 60*60;
-
- return secondnum;
-}
-datetkn *
-datetoktype(char *s, int *bigvalp)
-{
- register char *cp = s;
- register char c = *cp;
- static datetkn t;
- register datetkn *tp = &t;
-
- if (isascii(c) && isdigit(c)) {
- register int len = strlen(cp);
-
- if (len > 3 && (cp[1] == ':' || cp[2] == ':'))
- tp->type = TIME;
- else {
- if (bigvalp != NULL)
- /* won't fit in tp->value */
- *bigvalp = atoi(cp);
- if (len == 4)
- tp->type = YEAR;
- else if (++dtok_numparsed == 1)
- tp->type = DAY;
- else
- tp->type = YEAR;
- }
- } else if (c == '-' || c == '+') {
- register int val = atoi(cp + 1);
- register int hr = val / 100;
- register int min = val % 100;
-
- val = hr*60 + min;
- if (c == '-')
- val = -val;
- tp->type = TZ;
- TOVAL(tp, val);
- } else {
- char lowtoken[TOKMAXLEN+1];
- register char *ltp = lowtoken, *endltp = lowtoken+TOKMAXLEN;
-
- /* copy to lowtoken to avoid modifying s */
- while ((c = *cp++) != '\0' && ltp < endltp)
- *ltp++ = (isascii(c) && isupper(c)? tolower(c): c);
- *ltp = '\0';
- tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
- if (tp == NULL) {
- tp = &t;
- tp->type = PG_IGNORE;
- }
- }
- return tp;
-}
+ /* daylight correction */
+ if (tm->tm_isdst < 0) { /* unknown; find out */
+ tm->tm_isdst = (daylight > 0);
+ };
+ if (tm->tm_isdst > 0)
+ sec -= 60*60;
-/*
- * Binary search -- from Knuth (6.2.1) Algorithm B. Special case like this
- * is WAY faster than the generic bsearch().
- */
-datetkn *
-datebsearch(char *key, datetkn *base, unsigned int nel)
-{
- register datetkn *last = base + nel - 1, *position;
- register int result;
-
- while (last >= base) {
- position = base + ((last - base) >> 1);
- result = key[0] - position->token[0];
- if (result == 0) {
- result = strncmp(key, position->token, TOKMAXLEN);
- if (result == 0)
- return position;
- }
- if (result < 0)
- last = position - 1;
- else
- base = position + 1;
- }
- return 0;
-}
+ return sec;
+} /* qmktime() */
/*
* AbsoluteTimeIsBefore -- true iff time1 is before time2.
+ * AbsoluteTimeIsBefore -- true iff time1 is after time2.
*/
-
bool
AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2)
{
- AbsoluteTime tm = GetCurrentTransactionStartTime();
-
Assert(AbsoluteTimeIsValid(time1));
Assert(AbsoluteTimeIsValid(time2));
-
- if ((time1 == CURRENT_ABSTIME) || (time2 == CURRENT_ABSTIME))
- return false;
+
if (time1 == CURRENT_ABSTIME)
- return (tm < time2);
+ time1 = GetCurrentTransactionStartTime();
+
if (time2 == CURRENT_ABSTIME)
- return (time1 < tm);
-
+ time2 = GetCurrentTransactionStartTime();
+
return (time1 < time2);
}
bool
AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
{
- AbsoluteTime tm = GetCurrentTransactionStartTime();
-
Assert(AbsoluteTimeIsValid(time1));
Assert(AbsoluteTimeIsValid(time2));
-
- if ((time1 == CURRENT_ABSTIME) || (time2 == CURRENT_ABSTIME))
- return false;
+
if (time1 == CURRENT_ABSTIME)
- return (tm > time2);
+ time1 = GetCurrentTransactionStartTime();
+
if (time2 == CURRENT_ABSTIME)
- return (time1 > tm);
-
+ time2 = GetCurrentTransactionStartTime();
+
return (time1 > time2);
}
@@ -781,9 +349,8 @@ AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
* abstimegt - returns 1, iff t1 greater than t2
* abstimele - returns 1, iff t1 less than or equal to t2
* abstimege - returns 1, iff t1 greater than or equal to t2
- *
*/
-int32
+bool
abstimeeq(AbsoluteTime t1, AbsoluteTime t2)
{
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
@@ -792,11 +359,11 @@ abstimeeq(AbsoluteTime t1, AbsoluteTime t2)
t1 = GetCurrentTransactionStartTime();
if (t2 == CURRENT_ABSTIME)
t2 = GetCurrentTransactionStartTime();
-
+
return(t1 == t2);
}
-int32
+bool
abstimene(AbsoluteTime t1, AbsoluteTime t2)
{
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
@@ -805,11 +372,11 @@ abstimene(AbsoluteTime t1, AbsoluteTime t2)
t1 = GetCurrentTransactionStartTime();
if (t2 == CURRENT_ABSTIME)
t2 = GetCurrentTransactionStartTime();
-
+
return(t1 != t2);
}
-int32
+bool
abstimelt(AbsoluteTime t1, AbsoluteTime t2)
{
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
@@ -818,11 +385,11 @@ abstimelt(AbsoluteTime t1, AbsoluteTime t2)
t1 = GetCurrentTransactionStartTime();
if (t2 == CURRENT_ABSTIME)
t2 = GetCurrentTransactionStartTime();
-
+
return(t1 < t2);
}
-int32
+bool
abstimegt(AbsoluteTime t1, AbsoluteTime t2)
{
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
@@ -831,11 +398,11 @@ abstimegt(AbsoluteTime t1, AbsoluteTime t2)
t1 = GetCurrentTransactionStartTime();
if (t2 == CURRENT_ABSTIME)
t2 = GetCurrentTransactionStartTime();
-
+
return(t1 > t2);
}
-int32
+bool
abstimele(AbsoluteTime t1, AbsoluteTime t2)
{
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
@@ -844,11 +411,11 @@ abstimele(AbsoluteTime t1, AbsoluteTime t2)
t1 = GetCurrentTransactionStartTime();
if (t2 == CURRENT_ABSTIME)
t2 = GetCurrentTransactionStartTime();
-
+
return(t1 <= t2);
}
-int32
+bool
abstimege(AbsoluteTime t1, AbsoluteTime t2)
{
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
@@ -857,8 +424,6 @@ abstimege(AbsoluteTime t1, AbsoluteTime t2)
t1 = GetCurrentTransactionStartTime();
if (t2 == CURRENT_ABSTIME)
t2 = GetCurrentTransactionStartTime();
-
+
return(t1 >= t2);
}
-
-