diff options
Diffstat (limited to 'src/backend/utils/adt')
| -rw-r--r-- | src/backend/utils/adt/date.c | 58 | ||||
| -rw-r--r-- | src/backend/utils/adt/datetime.c | 346 | ||||
| -rw-r--r-- | src/backend/utils/adt/dt.c | 385 | ||||
| -rw-r--r-- | src/backend/utils/adt/nabstime.c | 99 | ||||
| -rw-r--r-- | src/backend/utils/adt/timestamp.c | 20 |
5 files changed, 669 insertions, 239 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 8d2587ce38..3f6d192424 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.6 1997/03/14 23:19:57 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.7 1997/04/02 18:33:09 scrappy Exp $ * * NOTES * This code is actually (almost) unused. @@ -32,15 +32,14 @@ #include "postgres.h" #include "miscadmin.h" +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif #include "access/xact.h" #include "utils/builtins.h" /* where function declarations go */ #include "utils/palloc.h" #include "utils/dt.h" -#ifndef USE_NEW_TIME_CODE -#define USE_NEW_TIME_CODE 1 -#endif - #define INVALID_RELTIME_STR "Undefined RelTime" #define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1) #define RELTIME_LABEL '@' @@ -235,6 +234,55 @@ char *tintervalout(TimeInterval interval) * PUBLIC ROUTINES * *****************************************************************************/ +RelativeTime +timespan_reltime(TimeSpan *timespan) +{ + RelativeTime time; + double span; + + if (!PointerIsValid(timespan)) + time = INVALID_RELTIME; + + if (TIMESPAN_IS_INVALID(*timespan)) { + time = INVALID_RELTIME; + + } else { + span = ((((double) 30*86400)*timespan->month) + timespan->time); + +#ifdef DATEDEBUG +printf( "timespan_reltime- convert m%d s%f to %f [%d %d]\n", + timespan->month, timespan->time, span, INT_MIN, INT_MAX); +#endif + + time = (((span > INT_MIN) && (span < INT_MAX))? span: INVALID_RELTIME); + }; + + return(time); +} /* timespan_reltime() */ + + +TimeSpan * +reltime_timespan(RelativeTime reltime) +{ + TimeSpan *result; + + if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) + elog(WARN,"Memory allocation failed, can't convert reltime to timespan",NULL); + + switch(reltime) { + case INVALID_RELTIME: + TIMESPAN_INVALID(*result); + break; + + default: + result->time = reltime; + result->month = 0; + }; + + return(result); +} /* reltime_timespan() */ + + /* * mktinterval - creates a time interval with endpoints t1 and t2 */ diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index e5569281d0..43207b2a87 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -7,18 +7,19 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.1 1997/03/14 23:20:01 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.2 1997/04/02 18:33:22 scrappy Exp $ * *------------------------------------------------------------------------- */ #include <stdio.h> /* for sprintf() */ #include <string.h> -#include <postgres.h> -#include <miscadmin.h> -#include <utils/builtins.h> -#include <utils/nabstime.h> -#include <utils/datetime.h> +#include "postgres.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/nabstime.h" +#include "utils/datetime.h" +#include "access/xact.h" static int day_tab[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31}, @@ -72,36 +73,23 @@ printf( "date_in- input string is %s\n", str); elog(WARN,"Bad date external representation %s",str); switch (dtype) { -#if FALSE case DTK_DATE: - date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday); - time = time2j(tm->tm_hour,tm->tm_min,(double)tm->tm_sec); - if (tzp != 0) { - j2local(&date, &time, -(tzp*60)); - } else { - j2local(&date, &time, -timezone); - }; break; -#endif + + case DTK_CURRENT: + GetCurrentTime(tm); + break; case DTK_EPOCH: tm->tm_year = 1970; tm->tm_mon = 1; tm->tm_mday = 1; - case DTK_DATE: break; default: elog(WARN,"Unrecognized date external representation %s",str); }; -#if FALSE - if (tm->tm_year < 70) - tm->tm_year += 2000; - else if (tm->tm_year < 100) - tm->tm_year += 1900; -#endif - if (tm->tm_year < 0 || tm->tm_year > 32767) elog(WARN, "date_in: year must be limited to values 0 through 32767 in '%s'", str); if (tm->tm_mon < 1 || tm->tm_mon > 12) @@ -256,6 +244,82 @@ date_mii(DateADT dateVal, int4 days) return(date_pli(dateVal, -days)); } /* date_mii() */ + +/* date_datetime() + * Convert date to datetime data type. + */ +DateTime * +date_datetime(int4 dateVal) +{ + DateTime *result; + + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN,"Memory allocation failed, can't convert date to datetime",NULL); + + *result = (dateVal - date2j( 2000, 1, 1)); + *result *= 86400; + + return(result); +} /* date_datetime() */ + + +/* datetime_date() + * Convert datetime to date data type. + */ +DateADT +datetime_date(DateTime *datetime) +{ + DateADT result; + + if (!PointerIsValid(datetime)) + elog(WARN,"Unable to convert null datetime to date",NULL); + + result = (*datetime / 86400); + + return(result); +} /* datetime_date() */ + + +/* abstime_date() + * Convert abstime to date data type. + */ +DateADT +abstime_date(AbsoluteTime abstime) +{ + DateADT result; + struct tt, *tm = &tt; + + switch (abstime) { + case INVALID_ABSTIME: + case NOSTART_ABSTIME: + case NOEND_ABSTIME: + elog(WARN,"Unable to convert reserved abstime value to date",NULL); + break; + + case EPOCH_ABSTIME: + result = date2j(1970,1,1) - date2j(2000,1,1); + break; + + case CURRENT_ABSTIME: + GetCurrentTime(tm); + result = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1); + break; + + default: +#if FALSE + tm = localtime((time_t *) &abstime); + tm->tm_year += 1900; + tm->tm_mon += 1; + /* XXX must shift to local time before converting - tgl 97/04/01 */ +#endif + abstime2tm(abstime, &CTimeZone, tm); + result = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1); + break; + }; + + return(result); +} /* abstime_date() */ + #else bool @@ -392,69 +456,15 @@ date_smaller(int4 dateVal1, int4 dateVal2) int32 date_mi(int4 dateVal1, int4 dateVal2) { -#if USE_NEW_TIME_CODE - DateADT *date1, *date2; int days; + date1 = (DateADT *) &dateVal1; date2 = (DateADT *) &dateVal2; days = (date2j(date1->year, date1->month, date1->day) - date2j(date2->year, date2->month, date2->day)); -#else - - DateADT dv1, dv2; - DateADT *date1, *date2; - int32 days = 0; - int i; - - /* This circumlocution allows us to assume that date1 is always - before date2. */ - dv1 = date_smaller (dateVal1, dateVal2); - dv2 = date_larger (dateVal1, dateVal2); - date1 = (DateADT *) &dv1; - date2 = (DateADT *) &dv2; - - /* Sum number of days in each full year between date1 and date2. */ - for (i = date1->year + 1; i < date2->year; ++i) - days += isleap(i) ? 366 : 365; - - if (days) - { - /* We need to wrap around the year. Add in number of days in each - full month from date1 to end of year. */ - for (i = date1->month + 1; i <= 12; ++i) - days += day_tab[isleap(date1->year)][i - 1]; - - /* Add in number of days in each full month from start of year to - date2. */ - for (i = 1; i < date2->month; ++i) - days += day_tab[isleap(date2->year)][i - 1]; - } - else - { - /* Add in number of days in each full month from date1 to date2. */ - for (i = date1->month + 1; i < date2->month; ++i) - days += day_tab[isleap(date1->year)][i - 1]; - } - - if (days || date1->month != date2->month) - { - /* Add in number of days left in month for date1. */ - days += day_tab[isleap(date1->year)][date1->month - 1] - date1->day; - - /* Add in day of month of date2. */ - days += date2->day; - } - else - { - /* Everything's in the same month, so just subtract the days! */ - days = date2->day - date1->day; - } - -#endif - return (days); } @@ -463,8 +473,6 @@ date_mi(int4 dateVal1, int4 dateVal2) int4 date_pli(int4 dateVal, int32 days) { -#if USE_NEW_TIME_CODE - DateADT *date1 = (DateADT *) &dateVal; int date, year, month, day; @@ -474,41 +482,6 @@ date_pli(int4 dateVal, int32 days) date1->month = month; date1->day = day; -#else - - DateADT *date1 = (DateADT *) &dateVal; - /* Use separate day variable because date1->day is a narrow type. */ - int32 day = date1->day + days; - - if (days > 0) { - /* Loop as long as day has wrapped around end of month. */ - while (day > day_tab[isleap(date1->year)][date1->month - 1]) { - day -= day_tab[isleap(date1->year)][date1->month - 1]; - if (++date1->month > 12) { - /* Month wrapped around. */ - date1->month = 1; - ++date1->year; - } - } - - } else { - /* Loop as long as day has wrapped around beginning of month. */ - while (day < 1) { - /* Decrement month first, because a negative day number - should be held as relative to the previous month's end. */ - if (--date1->month < 1) { - /* Month wrapped around. */ - date1->month = 12; - --date1->year; - } - - day += day_tab[isleap(date1->year)][date1->month - 1]; - } - } - date1->day = day; - -#endif - return (dateVal); } /* date_pli() */ @@ -519,8 +492,93 @@ date_mii(int4 dateVal, int32 days) return (date_pli(dateVal, -days)); } +DateTime * +date_datetime(int4 dateVal) +{ + DateTime *result; + DateADT *date = (DateADT *) &dateVal; + + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN,"Memory allocation failed, can't convert date to datetime",NULL); + + *result = (date2j(date->year, date->month, date->day) - date2j( 2000, 1, 1)); + *result *= 86400; + +#ifdef DATEDEBUG +printf( "date_datetime- convert %04d-%02d-%02d to %f\n", + date->year, date->month, date->day, *result); +#endif + + return(result); +} /* date_datetime() */ + +int4 +datetime_date(DateTime *datetime) +{ + int4 result; + int year, month, day; + DateADT *date = (DateADT *) &result; + + if (!PointerIsValid(datetime)) + elog(WARN,"Unable to convert null datetime to date",NULL); + + j2date( ((*datetime / 86400) + date2j( 2000, 1, 1)), &year, &month, &day); + date->year = year; + date->month = month; + date->day = day; + + return(result); +} /* datetime_date() */ + +int4 +abstime_date(AbsoluteTime abstime) +{ + int4 result; + DateADT *date = (DateADT *) &result; + struct tm tt, *tm = &tt; + + switch (abstime) { + case INVALID_ABSTIME: + case NOSTART_ABSTIME: + case NOEND_ABSTIME: + elog(WARN,"Unable to convert reserved abstime value to date",NULL); + break; + + case EPOCH_ABSTIME: + date->year = 1970; + date->month = 1; + date->day = 1; + break; + + case CURRENT_ABSTIME: +#if FALSE + GetCurrentTime(tm); +#endif + abstime = GetCurrentTransactionStartTime() + CTimeZone; + date->year = tm->tm_year; + date->month = tm->tm_mon; + date->day = tm->tm_mday; + break; + + default: +#if FALSE + tm = localtime((time_t *) &abstime); + tm->tm_year += 1900; + tm->tm_mon += 1; +#endif + abstime2tm(abstime, &CTimeZone, tm); + date->year = tm->tm_year; + date->month = tm->tm_mon; + date->day = tm->tm_mday; + break; + }; + + return(result); +} /* abstime_date() */ + #endif + /***************************************************************************** * Time ADT *****************************************************************************/ @@ -583,15 +641,14 @@ time_out(TimeADT *time) return NULL; if (time->sec == 0.0) { - sprintf(buf, "%02d:%02d", - (int)time->hr, (int)time->min); + sprintf(buf, "%02d:%02d", (int)time->hr, (int)time->min); } else { if (((int) time->sec) == time->sec) { sprintf(buf, "%02d:%02d:%02d", - (int)time->hr, (int)time->min, (int)time->sec); + (int)time->hr, (int)time->min, (int)time->sec); } else { sprintf(buf, "%02d:%02d:%09.6f", - (int)time->hr, (int)time->min, time->sec); + (int)time->hr, (int)time->min, time->sec); }; }; @@ -666,6 +723,29 @@ time_cmp(TimeADT *time1, TimeADT *time2) return((*time1 < *time2)? -1: (((*time1 < *time2)? 1: 0))); } /* time_cmp() */ + +/* datetime_datetime() + * Convert date and time to datetime data type. + */ +DateTime * +datetime_datetime(DateADT date, TimeADT *time) +{ + DateTime *result; + + if (!PointerIsValid(time)) { + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN,"Memory allocation failed, can't convert to datetime",NULL); + + DATETIME_INVALID(*result); + + } else { + result = date_datetime(date); + *result += *time; + }; + + return(result); +} /* datetime_datetime() */ + #else bool @@ -734,6 +814,34 @@ time_cmp(TimeADT *time1, TimeADT *time2) return 0; } +DateTime * +datetime_datetime(int4 dateVal, TimeADT *time) +{ + DateTime *result; +#ifdef DATEDEBUG + DateADT *date = (DateADT *) &dateVal; +#endif + + if (!PointerIsValid(time)) { + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN,"Memory allocation failed, can't convert to datetime",NULL); + + DATETIME_INVALID(*result); + + } else { + +#ifdef DATEDEBUG +printf( "datetime_datetime- convert %04d-%02d-%02d %02d:%02d:%05.2f\n", + date->year, date->month, date->day, time->hr, time->min, time->sec); +#endif + + result = date_datetime(dateVal); + *result += (((time->hr*60)+time->min)*60+time->sec); + }; + + return(result); +} /* datetime_datetime() */ + #endif int32 /* RelativeTime */ diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c index f56eb68a5f..28f31a1472 100644 --- a/src/backend/utils/adt/dt.c +++ b/src/backend/utils/adt/dt.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.13 1997/03/28 07:16:59 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.14 1997/04/02 18:33:32 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,7 @@ #include <errno.h> #include "postgres.h" -#include <miscadmin.h> +#include "miscadmin.h" #ifdef HAVE_FLOAT_H # include <float.h> #endif @@ -34,6 +34,10 @@ #define USE_DATE_CACHE 1 +#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0))) + +int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; + char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; @@ -55,26 +59,26 @@ datetime_in(char *str) double fsec; struct tm tt, *tm = &tt; - int tzp; + int tz; int dtype; int nf; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN]; + char lowstr[MAXDATELEN+1]; if (!PointerIsValid(str)) - elog(WARN, "Bad (null) datetime external representation", NULL); + elog(WARN,"Bad (null) datetime external representation",NULL); if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0)) + || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) elog(WARN,"Bad datetime external representation %s",str); if (!PointerIsValid(result = PALLOCTYPE(DateTime))) - elog(WARN, "Memory allocation failed, can't input datetime '%s'",str); + elog(WARN,"Memory allocation failed, can't input datetime '%s'",str); switch (dtype) { case DTK_DATE: - *result = tm2datetime( tm, fsec, tzp); + *result = tm2datetime( tm, fsec, &tz); #ifdef DATEDEBUG printf( "datetime_in- date is %f\n", *result); @@ -103,7 +107,7 @@ printf( "datetime_in- date is %f\n", *result); break; default: - elog(WARN, "Internal coding error, can't input datetime '%s'",str); + elog(WARN,"Internal coding error, can't input datetime '%s'",str); }; return(result); @@ -118,7 +122,7 @@ datetime_out(DateTime *dt) char *result; struct tm tt, *tm = &tt; double fsec; - char buf[MAXDATELEN]; + char buf[MAXDATELEN+1]; if (!PointerIsValid(dt)) return(NULL); @@ -126,7 +130,7 @@ datetime_out(DateTime *dt) if (DATETIME_IS_RESERVED(*dt)) { EncodeSpecialDateTime(*dt, buf); - } else if (datetime2tm( *dt, tm, &fsec) == 0) { + } else if (datetime2tm( *dt, &CTimeZone, tm, &fsec) == 0) { EncodeDateTime(tm, fsec, DateStyle, buf); } else { @@ -134,7 +138,7 @@ datetime_out(DateTime *dt) }; if (!PointerIsValid(result = PALLOC(strlen(buf)+1))) - elog(WARN, "Memory allocation failed, can't output datetime", NULL); + elog(WARN,"Memory allocation failed, can't output datetime",NULL); strcpy( result, buf); @@ -159,7 +163,7 @@ timespan_in(char *str) int nf; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN]; + char lowstr[MAXDATELEN+1]; tm->tm_year = 0; tm->tm_mon = 0; @@ -170,14 +174,14 @@ timespan_in(char *str) fsec = 0; if (!PointerIsValid(str)) - elog(WARN, "Bad (null) timespan external representation", NULL); + elog(WARN,"Bad (null) timespan external representation",NULL); if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0)) elog(WARN,"Bad timespan external representation %s",str); if (!PointerIsValid(span = PALLOCTYPE(TimeSpan))) - elog(WARN, "Memory allocation failed, can't input timespan '%s'",str); + elog(WARN,"Memory allocation failed, can't input timespan '%s'",str); switch (dtype) { case DTK_DELTA: @@ -189,7 +193,7 @@ timespan_in(char *str) break; default: - elog(WARN, "Internal coding error, can't input timespan '%s'",str); + elog(WARN,"Internal coding error, can't input timespan '%s'",str); }; return(span); @@ -205,7 +209,7 @@ timespan_out(TimeSpan *span) struct tm tt, *tm = &tt; double fsec; - char buf[MAXDATELEN]; + char buf[MAXDATELEN+1]; if (!PointerIsValid(span)) return(NULL); @@ -229,6 +233,26 @@ timespan_out(TimeSpan *span) *****************************************************************************/ +bool +datetime_finite(DateTime *datetime) +{ + if (!PointerIsValid(datetime)) + return FALSE; + + return(! DATETIME_NOT_FINITE(*datetime)); +} /* datetime_finite() */ + + +bool +timespan_finite(TimeSpan *timespan) +{ + if (!PointerIsValid(timespan)) + return FALSE; + + return(! TIMESPAN_NOT_FINITE(*timespan)); +} /* timespan_finite() */ + + /*---------------------------------------------------------- * Relational operators for datetime. *---------------------------------------------------------*/ @@ -267,14 +291,14 @@ SetDateTime( DateTime dt) { if (DATETIME_IS_CURRENT(dt)) { GetCurrentTime(&tt); - dt = tm2datetime( &tt, 0, 0); + dt = tm2datetime( &tt, 0, NULL); #ifdef DATEDEBUG printf( "SetDateTime- current time is %f\n", dt); #endif } else { /* if (DATETIME_IS_EPOCH(dt1)) */ GetEpochTime(&tt); - dt = tm2datetime( &tt, 0, 0); + dt = tm2datetime( &tt, 0, NULL); #ifdef DATEDEBUG printf( "SetDateTime- epoch time is %f\n", dt); #endif @@ -520,7 +544,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2) dt2 = *datetime2; if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) - elog(WARN, "Memory allocation failed, can't subtract dates",NULL); + elog(WARN,"Memory allocation failed, can't subtract dates",NULL); if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); @@ -538,46 +562,83 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2) } /* datetime_sub() */ +/* datetime_add_span() + * Add a timespan to a datetime data type. + * Note that timespan has provisions for qualitative year/month + * units, so try to do the right thing with them. + * To add a month, increment the month, and use the same day of month. + * Then, if the next month has fewer days, set the day of month + * to the last day of month. + */ DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span) { DateTime *result; +#if FALSE double date, time; int year, mon, mday; +#endif if ((!PointerIsValid(datetime)) || (!PointerIsValid(span))) return NULL; if (!PointerIsValid(result = PALLOCTYPE(DateTime))) - elog(WARN, "Memory allocation failed, can't add dates",NULL); + elog(WARN,"Memory allocation failed, can't add dates",NULL); #ifdef DATEDEBUG -printf( "date_add- add %f to %d %f\n", *datetime, span->month, span->time); -#endif - - *result = *datetime; - if (DATETIME_IS_RELATIVE(*result)) *result = SetDateTime(*result); - - if (span->month != 0) { - time = JROUND(modf( (*result/86400), &date)*86400); - date += date2j(2000,1,1); - - j2date( ((int) date), &year, &mon, &mday); - mon += span->month; - if (mon > 12) { - year += mon / 12; - mon %= 12; - } else if (mon < 0) { - year += mon / 12; - mon %= 12; - year -= 1; - mon += 12; +printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->time); +#endif + + if (DATETIME_NOT_FINITE(*datetime)) { + *result = *datetime; + + } else if (TIMESPAN_IS_INVALID(*span)) { + DATETIME_INVALID(*result); + + } else { + *result = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); + + if (span->month != 0) { + struct tm tt, *tm = &tt; + double fsec; + + if (datetime2tm( *result, NULL, tm, &fsec) == 0) { +#ifdef DATEDEBUG +printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); +#endif + tm->tm_mon += span->month; + if (tm->tm_mon > 12) { + tm->tm_year += (tm->tm_mon / 12); + tm->tm_mon = (tm->tm_mon % 12); + } else if (tm->tm_mon < 1) { + tm->tm_year += ((tm->tm_mon / 12) - 1); + tm->tm_mon = ((tm->tm_mon % 12) + 12); + }; + + /* adjust for end of month boundary problems... */ + if (tm->tm_mday > mdays[ tm->tm_mon-1]) { + if ((tm->tm_mon == 2) && isleap( tm->tm_year)) { + tm->tm_mday = (mdays[ tm->tm_mon-1]+1); + } else { + tm->tm_mday = mdays[ tm->tm_mon-1]; + }; + }; + +#ifdef DATEDEBUG +printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); +#endif + *result = tm2datetime( tm, fsec, NULL); + + } else { + DATETIME_INVALID(*result); + }; }; - *result += ((date2j( year, mon, mday)-date2j(2000,1,1))*86400); - *result += time; - }; - *result = JROUND(*result + span->time); +#if FALSE + *result = JROUND(*result + span->time); +#endif + *result += span->time; + }; return(result); } /* datetime_add_span() */ @@ -607,13 +668,13 @@ TimeSpan *timespan_um(TimeSpan *timespan) return NULL; if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) - elog(WARN, "Memory allocation failed, can't subtract dates",NULL); + elog(WARN,"Memory allocation failed, can't subtract dates",NULL); result->time = -(timespan->time); result->month = -(timespan->month); return(result); -} /* datetime_sub() */ +} /* timespan_um() */ TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2) @@ -624,7 +685,7 @@ TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2) return NULL; if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) - elog(WARN, "Memory allocation failed, can't add timespans",NULL); + elog(WARN,"Memory allocation failed, can't add timespans",NULL); result->month = (span1->month + span2->month); result->time = JROUND(span1->time + span2->time); @@ -640,7 +701,7 @@ TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2) return NULL; if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) - elog(WARN, "Memory allocation failed, can't subtract timespans",NULL); + elog(WARN,"Memory allocation failed, can't subtract timespans",NULL); result->month = (span1->month - span2->month); result->time = JROUND(span1->time - span2->time); @@ -654,6 +715,125 @@ TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2) *---------------------------------------------------------*/ +/* datetime_text() + * Convert datetime to text data type. + */ +text * +datetime_text(DateTime *datetime) +{ + text *result; + char *str; + int len; + + if (!PointerIsValid(datetime)) + return NULL; + + str = datetime_out(datetime); + + if (!PointerIsValid(str)) + return NULL; + + len = (strlen(str)+VARHDRSZ); + + if (!PointerIsValid(result = PALLOC(len))) + elog(WARN,"Memory allocation failed, can't convert datetime to text",NULL); + + VARSIZE(result) = len; + memmove(VARDATA(result), str, (len-VARHDRSZ)); + + PFREE(str); + + return(result); +} /* datetime_text() */ + + +/* text_datetime() + * Convert text string to datetime. + * Text type is not null terminated, so use temporary string + * then call the standard input routine. + */ +DateTime * +text_datetime(text *str) +{ + DateTime *result; + int i; + char *sp, *dp, dstr[MAXDATELEN+1]; + + if (!PointerIsValid(str)) + return NULL; + + sp = VARDATA(str); + dp = dstr; + for (i = 0; i < (VARSIZE(str)-VARHDRSZ); i++) *dp++ = *sp++; + *dp = '\0'; + + result = datetime_in(dstr); + + return(result); +} /* text_datetime() */ + + +/* timespan_text() + * Convert timespan to text data type. + */ +text * +timespan_text(TimeSpan *timespan) +{ + text *result; + char *str; + int len; + + if (!PointerIsValid(timespan)) + return NULL; + + str = timespan_out(timespan); + + if (!PointerIsValid(str)) + return NULL; + + len = (strlen(str)+VARHDRSZ); + + if (!PointerIsValid(result = PALLOC(len))) + elog(WARN,"Memory allocation failed, can't convert timespan to text",NULL); + + VARSIZE(result) = len; + memmove(VARDATA(result), str, (len-VARHDRSZ)); + + PFREE(str); + + return(result); +} /* timespan_text() */ + + +/* text_timespan() + * Convert text string to timespan. + * Text type may not be null terminated, so copy to temporary string + * then call the standard input routine. + */ +TimeSpan * +text_timespan(text *str) +{ + TimeSpan *result; + int i; + char *sp, *dp, dstr[MAXDATELEN+1]; + + if (!PointerIsValid(str)) + return NULL; + + sp = VARDATA(str); + dp = dstr; + for (i = 0; i < (VARSIZE(str)-VARHDRSZ); i++) *dp++ = *sp++; + *dp = '\0'; + + result = timespan_in(dstr); + + return(result); +} /* text_timespan() */ + + +/* datetime_part() + * Extract specified field from datetime. + */ float64 datetime_part(text *units, DateTime *datetime) { @@ -662,7 +842,7 @@ datetime_part(text *units, DateTime *datetime) DateTime dt; int type, val; int i; - char *up, *lp, lowunits[MAXDATELEN]; + char *up, *lp, lowunits[MAXDATELEN+1]; double fsec; struct tm tt, *tm = &tt; @@ -670,7 +850,7 @@ datetime_part(text *units, DateTime *datetime) return NULL; if (!PointerIsValid(result = PALLOCTYPE(float64data))) - elog(WARN, "Memory allocation failed, can't get date part",NULL); + elog(WARN,"Memory allocation failed, can't get date part",NULL); up = VARDATA(units); lp = lowunits; @@ -694,7 +874,7 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val); dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); - if (datetime2tm( dt, tm, &fsec) == 0) { + if (datetime2tm( dt, &CTimeZone, tm, &fsec) == 0) { switch (val) { case DTK_TZ: *result = CTimeZone; @@ -768,6 +948,9 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val); } /* datetime_part() */ +/* timespan_part() + * Extract specified field from timespan. + */ float64 timespan_part(text *units, TimeSpan *timespan) { @@ -775,7 +958,7 @@ timespan_part(text *units, TimeSpan *timespan) int type, val; int i; - char *up, *lp, lowunits[MAXDATELEN]; + char *up, *lp, lowunits[MAXDATELEN+1]; double fsec; struct tm tt, *tm = &tt; @@ -783,7 +966,7 @@ timespan_part(text *units, TimeSpan *timespan) return NULL; if (!PointerIsValid(result = PALLOCTYPE(float64data))) - elog(WARN, "Memory allocation failed, can't get date part",NULL); + elog(WARN,"Memory allocation failed, can't get date part",NULL); up = VARDATA(units); lp = lowunits; @@ -879,10 +1062,6 @@ printf( "timespan_part- units %s type=%d value=%d\n", lowunits, type, val); * PRIVATE ROUTINES * *****************************************************************************/ -#if USE_NEW_TIME_CODE -#define DATE_MAXLEN 47 -#endif - /* definitions for squeezing values into "value" */ #define ABS_SIGNBIT 0200 #define VALMASK 0177 @@ -1218,11 +1397,12 @@ int j2day( int date) * Also, month is one-based, _not_ zero-based. */ int -datetime2tm( DateTime dt, struct tm *tm, double *fsec) +datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec) { double date, time, sec; - time = (modf( dt2local( dt, CTimeZone)/86400, &date)*86400); + if (tzp != NULL) dt = dt2local( dt, *tzp); + time = (modf( dt/86400, &date)*86400); date += date2j(2000,1,1); if (time < 0) { time += 86400; @@ -1233,7 +1413,8 @@ datetime2tm( DateTime dt, struct tm *tm, double *fsec) if (date < 0) return -1; #ifdef DATEDEBUG -printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time); +printf( "datetime2tm- date is %f (%f %f)\n", + ((tzp != NULL)? dt2local(dt, -(*tzp)): dt), date, time); #endif j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); @@ -1254,8 +1435,8 @@ printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, t tm->tm_isdst = -1; #ifdef DATEDEBUG -printf( "datetime2tm- timezone is %s; offset is %d; daylight is %d\n", - CTZName, CTimeZone, CDayLight); +printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n", + CTZName, ((tzp != NULL)? *tzp: 0), CTimeZone, CDayLight); #endif return 0; @@ -1268,7 +1449,7 @@ printf( "datetime2tm- timezone is %s; offset is %d; daylight is %d\n", * Also, month is one-based, _not_ zero-based. */ DateTime -tm2datetime( struct tm *tm, double fsec, int tzp) { +tm2datetime( struct tm *tm, double fsec, int *tzp) { DateTime result; double date, time; @@ -1284,7 +1465,7 @@ tm2datetime( struct tm *tm, double fsec, int tzp) { printf( "tm2datetime- date is %f (%f %f %d)\n", result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec)); printf( "tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); #endif - if (tzp != 0) result = dt2local(result, -tzp); + if (tzp != NULL) result = dt2local(result, -(*tzp)); return(result); } /* tm2datetime() */ @@ -1832,30 +2013,14 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm *tm) *tmask = 0; + /* look first for text fields, since that will be unambiguous month */ for (i = 0; i < nf; i++) { - str = field[i]; - len = strlen(str); - - if (len <= 0) - return -1; - - if (isdigit(*str)) { - if (DecodeNumber( len, str, fmask, &dmask, tm, &fsec) != 0) - return -1; - - } else if (isalpha(*str)) { + if (isalpha(*field[i])) { type = DecodeSpecial( i, field[i], &val); if (type == IGNORE) continue; dmask = DTK_M(type); switch (type) { - case YEAR: -#ifdef DATEDEBUG -printf( "DecodeDate- year field %s value is %d\n", field[i], val); -#endif - tm->tm_mon = val; - break; - case MONTH: #ifdef DATEDEBUG printf( "DecodeDate- month field %s value is %d\n", field[i], val); @@ -1863,20 +2028,31 @@ printf( "DecodeDate- month field %s value is %d\n", field[i], val); tm->tm_mon = val; break; - case DAY: -#ifdef DATEDEBUG -printf( "DecodeDate- month field %s value is %d\n", field[i], val); -#endif - tm->tm_mon = val; - break; - default: #ifdef DATEDEBUG printf( "DecodeDate- illegal field %s value is %d\n", field[i], val); #endif return -1; }; + if (fmask & dmask) return -1; + + fmask |= dmask; + *tmask |= dmask; + + /* mark this field as being completed */ + field[i] = NULL; }; + }; + + /* now pick up remaining numeric fields */ + for (i = 0; i < nf; i++) { + if (field[i] == NULL) continue; + + if ((len = strlen(field[i])) <= 0) + return -1; + + if (DecodeNumber( len, field[i], fmask, &dmask, tm, &fsec) != 0) + return -1; if (fmask & dmask) return -1; @@ -1955,6 +2131,19 @@ printf( "DecodeNumber- %s is %d fmask=%08x tmask=%08x\n", str, val, fmask, *tmas printf( "DecodeNumber- match %d (%s) as year\n", val, str); #endif *tmask = DTK_M(YEAR); + + /* already have a year? then see if we can substitute... */ + if (fmask & DTK_M(YEAR)) { + if ((!(fmask & DTK_M(DAY))) + && ((tm->tm_year >= 1) && (tm->tm_year <= 31))) { +#ifdef DATEDEBUG +printf( "DecodeNumber- misidentified year previously; swap with day %d\n", tm->tm_mday); +#endif + tm->tm_mday = tm->tm_year; + *tmask = DTK_M(DAY); + }; + }; + tm->tm_year = val; /* special case day of year? */ @@ -1966,7 +2155,7 @@ printf( "DecodeNumber- match %d (%s) as year\n", val, str); &tm->tm_year,&tm->tm_mon,&tm->tm_mday); /* already have year? then could be month */ - } else if ((fmask && DTK_M(YEAR)) && (! (fmask & DTK_M(MONTH))) + } else if ((fmask & DTK_M(YEAR)) && (! (fmask & DTK_M(MONTH))) && ((val >= 1) && (val <= 12))) { #ifdef DATEDEBUG printf( "DecodeNumber- match %d (%s) as month\n", val, str); @@ -1975,11 +2164,7 @@ printf( "DecodeNumber- match %d (%s) as month\n", val, str); tm->tm_mon = val; /* no year and EuroDates enabled? then could be day */ -#if USE_EURODATES } else if ((EuroDates || (fmask & DTK_M(MONTH))) -#else - } else if ((fmask & DTK_M(MONTH)) -#endif && (! ((fmask & DTK_M(YEAR)) && (fmask & DTK_M(DAY)))) && ((val >= 1) && (val <= 31))) { #ifdef DATEDEBUG @@ -1996,6 +2181,14 @@ printf( "DecodeNumber- (2) match %d (%s) as month\n", val, str); *tmask = DTK_M(MONTH); tm->tm_mon = val; + } else if ((! (fmask & DTK_M(DAY))) + && ((val >= 1) && (val <= 31))) { +#ifdef DATEDEBUG +printf( "DecodeNumber- (2) match %d (%s) as day\n", val, str); +#endif + *tmask = DTK_M(DAY); + tm->tm_mday = val; + } else if (! (fmask & DTK_M(YEAR))) { #ifdef DATEDEBUG printf( "DecodeNumber- (2) match %d (%s) as year\n", val, str); @@ -2467,7 +2660,7 @@ int EncodeDateTime(struct tm *tm, double fsec, int style, char *str) int day, hour, min; double sec; #ifdef DATEDEBUG - char buf[MAXDATELEN]; + char buf[MAXDATELEN+1]; #endif sec = (tm->tm_sec + fsec); diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 3ae1978b73..8f1420bbd2 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.21 1997/03/28 07:12:53 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.22 1997/04/02 18:33:50 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -27,6 +27,7 @@ #ifndef USE_POSIX_TIME #include <sys/timeb.h> #endif +#include "utils/builtins.h" #include "access/xact.h" @@ -90,11 +91,19 @@ printf( "GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTC\n", void GetCurrentTime(struct tm *tm) { - time_t now; + abstime2tm( GetCurrentTransactionStartTime(), &CTimeZone, tm); + + return; +} /* GetCurrentTime() */ + + +void +abstime2tm(AbsoluteTime time, int *tzp, struct tm *tm) +{ struct tm *tt; - now = GetCurrentTransactionStartTime()-CTimeZone; - tt = gmtime( &now); + if (tzp != NULL) time -= *tzp; + tt = gmtime((time_t *) &time); tm->tm_year = tt->tm_year+1900; tm->tm_mon = tt->tm_mon+1; @@ -105,11 +114,13 @@ GetCurrentTime(struct tm *tm) tm->tm_isdst = tt->tm_isdst; return; -} /* GetCurrentTime() */ +} /* abstime2tm() */ -AbsoluteTime tm2abstime( struct tm *tm, int tz); - +/* tm2abstime() + * Convert a tm structure to abstime. + * Note that tm has full year (not 1900-based) and 1-based month. + */ AbsoluteTime tm2abstime( struct tm *tm, int tz) { @@ -122,13 +133,13 @@ tm2abstime( struct tm *tm, int tz) || 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; + 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; + return(INVALID_ABSTIME); /* convert to seconds */ sec = tm->tm_sec + tz + (tm->tm_min +(day*24 + tm->tm_hour)*60)*60; @@ -136,7 +147,7 @@ tm2abstime( struct tm *tm, int tz) /* check for overflow */ if ((day == MAX_DAYNUM && sec < 0) || (day == MIN_DAYNUM && sec > 0)) - return INVALID_ABSTIME; + return(INVALID_ABSTIME); /* daylight correction */ if (tm->tm_isdst < 0) { /* unknown; find out */ @@ -147,7 +158,7 @@ tm2abstime( struct tm *tm, int tz) /* check for reserved values (e.g. "current" on edge of usual range */ if (!AbsoluteTimeIsReal(sec)) - return INVALID_ABSTIME; + return(INVALID_ABSTIME); return sec; } /* tm2abstime() */ @@ -369,6 +380,16 @@ AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2) } +/* abstime_finite() + */ +bool +abstime_finite(AbsoluteTime abstime) +{ + return((abstime != INVALID_ABSTIME) + && (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME)); +} /* abstime_datetime() */ + + /* * abstimeeq - returns 1, iff arguments are equal * abstimene - returns 1, iff arguments are not equal @@ -381,7 +402,7 @@ bool abstimeeq(AbsoluteTime t1, AbsoluteTime t2) { if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return 0; + return(FALSE); if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) @@ -394,7 +415,7 @@ bool abstimene(AbsoluteTime t1, AbsoluteTime t2) { if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return 0; + return(FALSE); if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) @@ -407,7 +428,7 @@ bool abstimelt(AbsoluteTime t1, AbsoluteTime t2) { if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return 0; + return(FALSE); if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) @@ -420,7 +441,7 @@ bool abstimegt(AbsoluteTime t1, AbsoluteTime t2) { if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return 0; + return(FALSE); if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) @@ -433,7 +454,7 @@ bool abstimele(AbsoluteTime t1, AbsoluteTime t2) { if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return 0; + return(FALSE); if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) @@ -446,7 +467,7 @@ bool abstimege(AbsoluteTime t1, AbsoluteTime t2) { if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return 0; + return(FALSE); if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) @@ -455,6 +476,7 @@ abstimege(AbsoluteTime t1, AbsoluteTime t2) return(t1 >= t2); } + /* datetime_abstime() * Convert datetime to abstime. */ @@ -480,10 +502,10 @@ datetime_abstime(DateTime *datetime) } else { if (DATETIME_IS_RELATIVE(*datetime)) { - datetime2tm( SetDateTime(*datetime), tm, &fsec); + datetime2tm( SetDateTime(*datetime), &CTimeZone, tm, &fsec); result = tm2abstime( tm, 0); - } else if (datetime2tm( *datetime, tm, &fsec) == 0) { + } else if (datetime2tm( *datetime, &CTimeZone, tm, &fsec) == 0) { result = tm2abstime( tm, 0); } else { @@ -493,3 +515,42 @@ datetime_abstime(DateTime *datetime) return(result); } /* datetime_abstime() */ + +/* abstime_datetime() + * Convert datetime to abstime. + */ +DateTime * +abstime_datetime(AbsoluteTime abstime) +{ + DateTime *result; + + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN,"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); + }; + + return(result); +} /* abstime_datetime() */ diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 641dff80e0..99c7d0f70f 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -88,3 +88,23 @@ timestampge(time_t t1, time_t t2) { return difftime(t1, t2) <= 0; } + +DateTime * +timestamp_datetime(time_t timestamp) +{ + DateTime *result; + + double fsec = 0; + struct tm *tm; + + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN,"Memory allocation failed, can't convert timestamp to datetime",NULL); + + tm = localtime((time_t *) ×tamp); + tm->tm_year += 1900; + tm->tm_mon += 1; + + *result = tm2datetime(tm, fsec, NULL); + + return(result); +} /* timestamp_datetime() */ |
