nabstime.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:12k
- /*
- * nabstime.c
- * parse almost any absolute date getdate(3) can (& some it can't)
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: nabstime.c,v 1.55.2.1 1999/08/02 05:24:54 scrappy Exp $
- *
- */
- #include <ctype.h>
- #include <sys/types.h>
- #include "postgres.h"
- #ifdef HAVE_FLOAT_H
- #include <float.h>
- #endif
- #ifdef HAVE_LIMITS_H
- #include <limits.h>
- #endif
- #ifndef USE_POSIX_TIME
- #include <sys/timeb.h>
- #endif
- #include "access/xact.h"
- #include "miscadmin.h"
- #include "utils/builtins.h"
- static AbsoluteTime tm2abstime(struct tm * tm, int tz);
- #define MIN_DAYNUM -24856 /* December 13, 1901 */
- #define MAX_DAYNUM 24854 /* January 18, 2038 */
- /* GetCurrentAbsoluteTime()
- * Get the current system time. Set timezone parameters if not specified elsewhere.
- * Define HasTZSet to allow clients to specify the default timezone.
- *
- * Returns the number of seconds since epoch (January 1 1970 GMT)
- */
- AbsoluteTime
- GetCurrentAbsoluteTime(void)
- {
- time_t now;
- #ifdef USE_POSIX_TIME
- struct tm *tm;
- now = time(NULL);
- #else /* ! USE_POSIX_TIME */
- struct timeb tb; /* the old V7-ism */
- ftime(&tb);
- now = tb.time;
- #endif
- if (!HasCTZSet)
- {
- #ifdef USE_POSIX_TIME
- #if defined(HAVE_TM_ZONE)
- tm = localtime(&now);
- CTimeZone = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
- CDayLight = (tm->tm_isdst > 0);
- #ifdef NOT_USED
- /*
- * XXX is there a better way to get local timezone string w/o
- * tzname? - tgl 97/03/18
- */
- strftime(CTZName, MAXTZLEN, "%Z", tm);
- #endif
- /*
- * XXX FreeBSD man pages indicate that this should work - thomas
- * 1998-12-12
- */
- strcpy(CTZName, tm->tm_zone);
- #elif defined(HAVE_INT_TIMEZONE)
- tm = localtime(&now);
- CDayLight = tm->tm_isdst;
- CTimeZone =
- #ifdef __CYGWIN32__
- (tm->tm_isdst ? (_timezone - 3600) : _timezone);
- #else
- (tm->tm_isdst ? (timezone - 3600) : timezone);
- #endif
- strcpy(CTZName, tzname[tm->tm_isdst]);
- #else
- #error USE_POSIX_TIME defined but no time zone available
- #endif
- #else /* ! USE_POSIX_TIME */
- CTimeZone = tb.timezone * 60;
- CDayLight = (tb.dstflag != 0);
- /*
- * XXX does this work to get the local timezone string in V7? -
- * tgl 97/03/18
- */
- strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
- #endif
- };
- #ifdef DATEDEBUG
- printf("GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTCn",
- CTZName, CTimeZone);
- #endif
- return (AbsoluteTime) now;
- } /* GetCurrentAbsoluteTime() */
- void
- GetCurrentTime(struct tm * tm)
- {
- int tz;
- abstime2tm(GetCurrentTransactionStartTime(), &tz, tm, NULL);
- return;
- } /* GetCurrentTime() */
- void
- abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn)
- {
- #ifdef USE_POSIX_TIME
- struct tm *tx;
- #else /* ! USE_POSIX_TIME */
- struct timeb tb; /* the old V7-ism */
- ftime(&tb);
- #endif
- #ifdef USE_POSIX_TIME
- if (tzp != NULL)
- tx = localtime((time_t *) &time);
- else
- {
- tx = gmtime((time_t *) &time);
- };
- #endif
- #if defined(DATEDEBUG)
- #if defined(HAVE_TM_ZONE)
- printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s dst=%dn",
- tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec,
- tx->tm_zone, tx->tm_isdst);
- #elif defined(HAVE_INT_TIMEZONE)
- printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s %s dst=%dn",
- tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec,
- tzname[0], tzname[1], tx->tm_isdst);
- #endif
- #endif
- #ifdef USE_POSIX_TIME
- tm->tm_year = tx->tm_year + 1900;
- tm->tm_mon = tx->tm_mon + 1;
- tm->tm_mday = tx->tm_mday;
- tm->tm_hour = tx->tm_hour;
- tm->tm_min = tx->tm_min;
- tm->tm_sec = tx->tm_sec;
- tm->tm_isdst = tx->tm_isdst;
- #if defined(HAVE_TM_ZONE)
- tm->tm_gmtoff = tx->tm_gmtoff;
- tm->tm_zone = tx->tm_zone;
- if (tzp != NULL)
- *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
- /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
- if (tzn != NULL)
- strcpy(tzn, tm->tm_zone);
- #elif defined(HAVE_INT_TIMEZONE)
- if (tzp != NULL)
- #ifdef __CYGWIN__
- *tzp = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
- #else
- *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
- #endif
- if (tzn != NULL)
- strcpy(tzn, tzname[tm->tm_isdst]);
- #else
- #error POSIX time support is broken
- #endif
- #else /* ! USE_POSIX_TIME */
- if (tzp != NULL)
- *tzp = tb.timezone * 60;
- /*
- * XXX does this work to get the local timezone string in V7? - tgl
- * 97/03/18
- */
- if (tzn != NULL)
- strftime(tzn, MAXTZLEN, "%Z", localtime(&now));
- #endif
- return;
- } /* abstime2tm() */
- /* tm2abstime()
- * Convert a tm structure to abstime.
- * Note that tm has full year (not 1900-based) and 1-based month.
- */
- static AbsoluteTime
- tm2abstime(struct tm * tm, int tz)
- {
- int day,
- sec;
- /* 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;
- /* check for reserved values (e.g. "current" on edge of usual range */
- if (!AbsoluteTimeIsReal(sec))
- return INVALID_ABSTIME;
- return sec;
- } /* tm2abstime() */
- /* nabstimein()
- * Decode date/time string and return abstime.
- */
- AbsoluteTime
- nabstimein(char *str)
- {
- AbsoluteTime result;
- double fsec;
- int tz = 0;
- struct tm date,
- *tm = &date;
- char *field[MAXDATEFIELDS];
- char lowstr[MAXDATELEN + 1];
- int dtype;
- int nf,
- ftype[MAXDATEFIELDS];
- if (!PointerIsValid(str))
- elog(ERROR, "Bad (null) abstime external representation", NULL);
- if (strlen(str) > MAXDATELEN)
- elog(ERROR, "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(ERROR, "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:
- result = tm2abstime(tm, tz);
- break;
- case DTK_EPOCH:
- result = EPOCH_ABSTIME;
- break;
- case DTK_CURRENT:
- result = CURRENT_ABSTIME;
- break;
- case DTK_LATE:
- result = NOEND_ABSTIME;
- break;
- case DTK_EARLY:
- result = NOSTART_ABSTIME;
- break;
- case DTK_INVALID:
- result = INVALID_ABSTIME;
- break;
- default:
- elog(ERROR, "Bad abstime (internal coding error) '%s'", str);
- result = INVALID_ABSTIME;
- break;
- };
- return result;
- } /* nabstimein() */
- /* nabstimeout()
- * Given an AbsoluteTime return the English text version of the date
- */
- char *
- nabstimeout(AbsoluteTime time)
- {
- char *result;
- int tz;
- double fsec = 0;
- struct tm tt,
- *tm = &tt;
- char buf[MAXDATELEN + 1];
- char zone[MAXDATELEN + 1],
- *tzn = zone;
- switch (time)
- {
- case EPOCH_ABSTIME:
- strcpy(buf, EPOCH);
- break;
- case INVALID_ABSTIME:
- strcpy(buf, INVALID);
- break;
- case CURRENT_ABSTIME:
- strcpy(buf, DCURRENT);
- break;
- case NOEND_ABSTIME:
- strcpy(buf, LATE);
- break;
- case NOSTART_ABSTIME:
- strcpy(buf, EARLY);
- break;
- default:
- abstime2tm(time, &tz, tm, tzn);
- EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
- break;
- }
- result = palloc(strlen(buf) + 1);
- strcpy(result, buf);
- return result;
- } /* nabstimeout() */
- /*
- * AbsoluteTimeIsBefore -- true iff time1 is before time2.
- * AbsoluteTimeIsBefore -- true iff time1 is after time2.
- */
- bool
- AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2)
- {
- Assert(AbsoluteTimeIsValid(time1));
- Assert(AbsoluteTimeIsValid(time2));
- if (time1 == CURRENT_ABSTIME)
- time1 = GetCurrentTransactionStartTime();
- if (time2 == CURRENT_ABSTIME)
- time2 = GetCurrentTransactionStartTime();
- return time1 < time2;
- }
- #ifdef NOT_USED
- bool
- AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
- {
- Assert(AbsoluteTimeIsValid(time1));
- Assert(AbsoluteTimeIsValid(time2));
- if (time1 == CURRENT_ABSTIME)
- time1 = GetCurrentTransactionStartTime();
- if (time2 == CURRENT_ABSTIME)
- time2 = GetCurrentTransactionStartTime();
- return time1 > time2;
- }
- #endif
- /* abstime_finite()
- */
- bool
- abstime_finite(AbsoluteTime abstime)
- {
- return ((abstime != INVALID_ABSTIME)
- && (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME));
- } /* abstime_finite() */
- /*
- * abstimeeq - returns 1, iff arguments are equal
- * abstimene - returns 1, iff arguments are not equal
- * abstimelt - returns 1, iff t1 less than t2
- * 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
- */
- bool
- abstimeeq(AbsoluteTime t1, AbsoluteTime t2)
- {
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- return FALSE;
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
- return t1 == t2;
- }
- bool
- abstimene(AbsoluteTime t1, AbsoluteTime t2)
- {
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- return FALSE;
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
- return t1 != t2;
- }
- bool
- abstimelt(AbsoluteTime t1, AbsoluteTime t2)
- {
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- return FALSE;
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
- return t1 < t2;
- }
- bool
- abstimegt(AbsoluteTime t1, AbsoluteTime t2)
- {
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- return FALSE;
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
- return t1 > t2;
- }
- bool
- abstimele(AbsoluteTime t1, AbsoluteTime t2)
- {
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- return FALSE;
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
- return t1 <= t2;
- }
- bool
- abstimege(AbsoluteTime t1, AbsoluteTime t2)
- {
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- return FALSE;
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
- return t1 >= t2;
- }
- /* datetime_abstime()
- * Convert datetime to abstime.
- */
- AbsoluteTime
- datetime_abstime(DateTime *datetime)
- {
- AbsoluteTime result;
- double fsec;
- struct tm tt,
- *tm = &tt;
- if (!PointerIsValid(datetime))
- {
- result = INVALID_ABSTIME;
- }
- else if (DATETIME_IS_INVALID(*datetime))
- {
- result = INVALID_ABSTIME;
- }
- else if (DATETIME_IS_NOBEGIN(*datetime))
- {
- result = NOSTART_ABSTIME;
- }
- else if (DATETIME_IS_NOEND(*datetime))
- {
- result = NOEND_ABSTIME;
- }
- else
- {
- if (DATETIME_IS_RELATIVE(*datetime))
- {
- datetime2tm(SetDateTime(*datetime), NULL, tm, &fsec, NULL);
- result = tm2abstime(tm, 0);
- }
- else if (datetime2tm(*datetime, NULL, tm, &fsec, NULL) == 0)
- {
- result = tm2abstime(tm, 0);
- }
- else
- {
- result = INVALID_ABSTIME;
- };
- };
- return result;
- } /* datetime_abstime() */
- /* abstime_datetime()
- * Convert abstime to datetime.
- */
- DateTime *
- abstime_datetime(AbsoluteTime abstime)
- {
- DateTime *result;
- if (!PointerIsValid(result = palloc(sizeof(DateTime))))
- elog(ERROR, "Unable to allocate space to convert abstime to datetime", NULL);
- switch (abstime)
- {
- case INVALID_ABSTIME:
- DATETIME_INVALID(*result);
- break;
- case NOSTART_ABSTIME:
- DATETIME_NOBEGIN(*result);
- break;
- case NOEND_ABSTIME:
- DATETIME_NOEND(*result);
- break;
- case EPOCH_ABSTIME:
- DATETIME_EPOCH(*result);
- break;
- case CURRENT_ABSTIME:
- DATETIME_CURRENT(*result);
- break;
- default:
- *result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400);
- break;
- };
- return result;
- } /* abstime_datetime() */