From 7c82b2e9c3e2b0401a6c55d36b3cdcb778d2e531 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Tue, 22 Apr 1997 17:36:57 +0000 Subject: [PATCH] From: Thomas Lockhart Subject: [PATCHES] date/time timezone patches (mail bounced?) Here are some hacks to get timezone behavior for the various time data types to be compatible with v6.0. Although we have some hooks already installed to get timezone info from the client to the server, it still isn't clear if that can correctly transfer enough timezone info to make the behavior the same as if timezone info were derived from the server as is now the case. We certainly won't resolve it in a day, so I think we are stuck with server-only timezones for v6.1. --- src/backend/utils/adt/dt.c | 65 ++++++++++++++++++++++++++------ src/backend/utils/adt/nabstime.c | 24 ++++++++---- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c index 9b49ce5bcd..46c7317c52 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.15 1997/04/05 02:51:41 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.16 1997/04/22 17:36:44 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -1400,8 +1400,23 @@ int datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec) { double date, time, sec; + time_t utime; + + if (tzp != NULL) { + /* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */ + if ((tm->tm_year > 1902) && (tm->tm_year < 2038)) { + utime = ((date2j(2000,1,1)-date2j(1970,1,1))*86400+dt); + localtime((time_t *) &utime); +#ifdef DATEDEBUG +printf( "datetime2tm- use system time zone = %ld (CTimeZone = %d)\n", (long int) utime, CTimeZone); +#endif + dt = dt2local( dt, timezone); + + } else { + dt = dt2local( dt, *tzp); + }; + }; - if (tzp != NULL) dt = dt2local( dt, *tzp); time = (modf( dt/86400, &date)*86400); date += date2j(2000,1,1); if (time < 0) { @@ -1529,9 +1544,9 @@ printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month } /* tm2timespan() */ -DateTime dt2local(DateTime dt, int timezone) +DateTime dt2local(DateTime dt, int tz) { - dt -= timezone; + dt -= tz; dt = JROUND(dt); return(dt); } /* dt2local() */ @@ -1711,6 +1726,8 @@ printf( "DecodeDateTime- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); case DTK_TIME: if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1; + /* check upper limit on hours; other limits checked in DecodeTime() */ + if (tm->tm_hour > 23) return -1; break; case DTK_TZ: @@ -1863,6 +1880,20 @@ printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M)) return(((fmask & DTK_TIME_M) == DTK_TIME_M)? 1: -1); + /* timezone not specified? then find local timezone if possible */ + /* XXX HACK to get correct behavior relative to Postgres v6.0 - tgl 97/04/07 */ + if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M) + && (tzp != NULL) && (! (fmask & DTK_M(TZ))) + && (tm->tm_year > 1902) && (tm->tm_year < 2038)) { + tm->tm_year -= 1900; + tm->tm_mon -= 1; + mktime(tm); + tm->tm_year += 1900; + tm->tm_mon += 1; + + *tzp = timezone; + }; + return 0; } /* DecodeDateTime() */ @@ -2066,6 +2097,8 @@ printf( "DecodeDate- illegal field %s value is %d\n", field[i], val); /* DecodeTime() * Decode time string which includes delimiters. + * Only check the lower limit on hours, since this same code + * can be used to represent time spans. */ int DecodeTime(char *str, int fmask, int *tmask, struct tm *tm, double *fsec) @@ -2099,6 +2132,11 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm *tm, double *fsec) }; }; + /* do a sanity check */ + if ((tm->tm_hour < 0) + || (tm->tm_min < 0) || (tm->tm_min > 59) + || (tm->tm_sec < 0) || (tm->tm_sec > 59)) return -1; + return 0; } /* DecodeTime() */ @@ -2654,6 +2692,9 @@ printf( "EncodeSpecialDateTime- unrecognized date\n"); } /* EncodeSpecialDateTime() */ +/* EncodeDateTime() + * Encode date and time interpreted as local time. + */ int EncodeDateTime(struct tm *tm, double fsec, int style, char *str) { char mabbrev[4], dabbrev[4]; @@ -2668,8 +2709,8 @@ int EncodeDateTime(struct tm *tm, double fsec, int style, char *str) tm->tm_isdst = -1; #ifdef DATEDEBUG -printf( "EncodeDateTime- timezone is %s; offset is %d; daylight is %d\n", - CTZName, CTimeZone, CDayLight); +printf( "EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n", + tzname[0], CTZName, (long int) timezone, CTimeZone, daylight, CDayLight); #endif day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday); @@ -2723,10 +2764,8 @@ printf( "EncodeDateTime- day is %d\n", day); sprintf( str, "%02d/%02d", tm->tm_mon, tm->tm_mday); }; if (tm->tm_year > 0) { - sprintf( (str+5), "/%04d %02d:%02d:%5.2f %s", + sprintf( (str+5), "/%04d %02d:%02d:%05.2f %s", tm->tm_year, tm->tm_hour, tm->tm_min, sec, CTZName); - /* XXX brute-force fill in leading zero on seconds */ - if (*(str+17) == ' ') *(str+17) = '0'; } else { sprintf( (str+5), "/%04d %02d:%02d %s", @@ -2742,10 +2781,12 @@ printf( "EncodeDateTime- day is %d\n", day); sprintf( (str+4), "%3s %02d", mabbrev, tm->tm_mday); }; if (tm->tm_year > 0) { - sprintf( (str+10), " %02d:%02d:%5.2f %04d %s", +#if FALSE + sprintf( (str+10), " %02d:%02d:%05.2f %04d %s", tm->tm_hour, tm->tm_min, sec, tm->tm_year, CTZName); - /* XXX brute-force fill in leading zero on seconds */ - if (*(str+17) == ' ') *(str+17) = '0'; +#endif + sprintf( (str+10), " %02d:%02d:%05.2f %04d %s", + tm->tm_hour, tm->tm_min, sec, tm->tm_year, (daylight? tzname[1]: tzname[0])); } else { sprintf( (str+10), " %02d:%02d %04d %s", diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 2b912109c9..b227528ed3 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.23 1997/04/15 17:46:52 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.24 1997/04/22 17:36:57 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -102,8 +102,16 @@ abstime2tm(AbsoluteTime time, int *tzp, struct tm *tm) { struct tm *tt; +#if FALSE if (tzp != NULL) time -= *tzp; tt = gmtime((time_t *) &time); +#endif + /* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */ + if (tzp != NULL) { + tt = localtime((time_t *) &time); + } else { + tt = gmtime((time_t *) &time); + }; tm->tm_year = tt->tm_year+1900; tm->tm_mon = tt->tm_mon+1; @@ -160,7 +168,7 @@ tm2abstime( struct tm *tm, int tz) if (!AbsoluteTimeIsReal(sec)) return(INVALID_ABSTIME); - return sec; + return(sec); } /* tm2abstime() */ @@ -530,27 +538,27 @@ abstime_datetime(AbsoluteTime abstime) switch (abstime) { case INVALID_ABSTIME: - DATETIME_INVALID(*result); + DATETIME_INVALID(*result); break; case NOSTART_ABSTIME: - DATETIME_NOBEGIN(*result); + DATETIME_NOBEGIN(*result); break; case NOEND_ABSTIME: - DATETIME_NOEND(*result); + DATETIME_NOEND(*result); break; case EPOCH_ABSTIME: - DATETIME_EPOCH(*result); + DATETIME_EPOCH(*result); break; case CURRENT_ABSTIME: - DATETIME_CURRENT(*result); + DATETIME_CURRENT(*result); break; default: - *result = abstime + ((date2j( 1970, 1, 1) - date2j( 2000, 1, 1))*86400); + *result = abstime + ((date2j( 1970, 1, 1) - date2j( 2000, 1, 1))*86400); break; };