Index: src/backend/utils/adt/date.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/date.c,v retrieving revision 1.109 diff -c -r1.109 date.c *** src/backend/utils/adt/date.c 26 May 2005 02:04:13 -0000 1.109 --- src/backend/utils/adt/date.c 6 Jun 2005 17:30:25 -0000 *************** *** 18,23 **** --- 18,24 ---- #include #include #include + #include #include "access/hash.h" #include "libpq/pqformat.h" *************** *** 724,730 **** if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 725,731 ---- if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 767,773 **** if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 768,774 ---- if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 1327,1333 **** if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 1328,1334 ---- if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 1364,1370 **** if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 1365,1371 ---- if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 2247,2253 **** if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 2248,2254 ---- if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 2463,2515 **** /* timetz_zone() * Encode time with time zone type with specified time zone. */ Datum timetz_zone(PG_FUNCTION_ARGS) { text *zone = PG_GETARG_TEXT_P(0); ! TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; ! int type, ! val; ! char *lowzone; ! ! lowzone = downcase_truncate_identifier(VARDATA(zone), ! VARSIZE(zone) - VARHDRSZ, ! false); ! ! type = DecodeSpecial(0, lowzone, &val); ! result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); ! if (type == TZ || type == DTZ) ! { ! tz = val * 60; #ifdef HAVE_INT64_TIMESTAMP ! result->time = time->time + (time->zone - tz) * USECS_PER_SEC; ! while (result->time < INT64CONST(0)) ! result->time += USECS_PER_DAY; ! while (result->time >= USECS_PER_DAY) ! result->time -= USECS_PER_DAY; #else ! result->time = time->time + (time->zone - tz); ! while (result->time < 0) ! result->time += SECS_PER_DAY; ! while (result->time >= SECS_PER_DAY) ! result->time -= SECS_PER_DAY; #endif ! result->zone = tz; ! } ! else ! { ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" not recognized", lowzone))); ! ! PG_RETURN_NULL(); ! } PG_RETURN_TIMETZADT_P(result); } /* timetz_zone() */ --- 2464,2523 ---- /* timetz_zone() * Encode time with time zone type with specified time zone. + * Applies DST rules as of the current date. */ Datum timetz_zone(PG_FUNCTION_ARGS) { text *zone = PG_GETARG_TEXT_P(0); ! TimeTzADT *t = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; ! char tzname[TZ_STRLEN_MAX]; ! int len; ! pg_tz *tzp; ! struct pg_tm *tm; ! pg_time_t now; ! ! /* Find the specified timezone */ ! len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ); ! memcpy(tzname,VARDATA(zone),len); ! tzname[len]=0; ! tzp = pg_tzset(tzname); ! if (!tzp) { ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" not recognized", tzname))); ! PG_RETURN_NULL(); ! } ! /* Get the offset-from-GMT that is valid today for the selected zone */ ! if ((now = time(NULL)) < 0 || ! (tm = pg_localtime(&now, tzp)) == NULL) { ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("could not determine current time"))); ! PG_RETURN_NULL(); ! } ! result = (TimeTzADT *)palloc(sizeof(TimeTzADT)); ! ! tz = -tm->tm_gmtoff; #ifdef HAVE_INT64_TIMESTAMP ! result->time = t->time + (t->zone - tz) * USECS_PER_SEC; ! while (result->time < INT64CONST(0)) ! result->time += USECS_PER_DAY; ! while (result->time >= USECS_PER_DAY) ! result->time -= USECS_PER_DAY; #else ! result->time = t->time + (t->zone - tz); ! while (result->time < 0) ! result->time += SECS_PER_DAY; ! while (result->time >= SECS_PER_DAY) ! result->time -= SECS_PER_DAY; #endif ! result->zone = tz; PG_RETURN_TIMETZADT_P(result); } /* timetz_zone() */ Index: src/backend/utils/adt/formatting.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/formatting.c,v retrieving revision 1.87 diff -c -r1.87 formatting.c *** src/backend/utils/adt/formatting.c 25 May 2005 21:40:40 -0000 1.87 --- src/backend/utils/adt/formatting.c 6 Jun 2005 17:30:26 -0000 *************** *** 2910,2916 **** ZERO_tmtc(&tmtc); ! if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 2910,2916 ---- ZERO_tmtc(&tmtc); ! if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 2935,2941 **** ZERO_tmtc(&tmtc); ! if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc)) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 2935,2941 ---- ZERO_tmtc(&tmtc); ! if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); Index: src/backend/utils/adt/nabstime.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v retrieving revision 1.132 diff -c -r1.132 nabstime.c *** src/backend/utils/adt/nabstime.c 26 May 2005 02:04:13 -0000 1.132 --- src/backend/utils/adt/nabstime.c 6 Jun 2005 17:30:27 -0000 *************** *** 556,562 **** result = NOSTART_ABSTIME; else if (TIMESTAMP_IS_NOEND(timestamp)) result = NOEND_ABSTIME; ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0) { tz = DetermineLocalTimeZone(tm); result = tm2abstime(tm, tz); --- 556,562 ---- result = NOSTART_ABSTIME; else if (TIMESTAMP_IS_NOEND(timestamp)) result = NOEND_ABSTIME; ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0) { tz = DetermineLocalTimeZone(tm); result = tm2abstime(tm, tz); *************** *** 632,638 **** result = NOSTART_ABSTIME; else if (TIMESTAMP_IS_NOEND(timestamp)) result = NOEND_ABSTIME; ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0) result = tm2abstime(tm, 0); else { --- 632,638 ---- result = NOSTART_ABSTIME; else if (TIMESTAMP_IS_NOEND(timestamp)) result = NOEND_ABSTIME; ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0) result = tm2abstime(tm, 0); else { Index: src/backend/utils/adt/timestamp.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v retrieving revision 1.124 diff -c -r1.124 timestamp.c *** src/backend/utils/adt/timestamp.c 26 May 2005 02:04:13 -0000 1.124 --- src/backend/utils/adt/timestamp.c 6 Jun 2005 17:30:27 -0000 *************** *** 142,148 **** if (TIMESTAMP_NOT_FINITE(timestamp)) EncodeSpecialTimestamp(timestamp, buf); ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0) EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf); else ereport(ERROR, --- 142,148 ---- if (TIMESTAMP_NOT_FINITE(timestamp)) EncodeSpecialTimestamp(timestamp, buf); ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0) EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf); else ereport(ERROR, *************** *** 178,184 **** /* rangecheck: see if timestamp_out would like it */ if (TIMESTAMP_NOT_FINITE(timestamp)) /* ok */ ; ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 178,184 ---- /* rangecheck: see if timestamp_out would like it */ if (TIMESTAMP_NOT_FINITE(timestamp)) /* ok */ ; ! else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 381,387 **** if (TIMESTAMP_NOT_FINITE(dt)) EncodeSpecialTimestamp(dt, buf); ! else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0) EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); else ereport(ERROR, --- 381,387 ---- if (TIMESTAMP_NOT_FINITE(dt)) EncodeSpecialTimestamp(dt, buf); ! else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0) EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); else ereport(ERROR, *************** *** 419,425 **** /* rangecheck: see if timestamptz_out would like it */ if (TIMESTAMP_NOT_FINITE(timestamp)) /* ok */ ; ! else if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 419,425 ---- /* rangecheck: see if timestamptz_out would like it */ if (TIMESTAMP_NOT_FINITE(timestamp)) /* ok */ ; ! else if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 978,986 **** * Returns: * 0 on success * -1 on out of range */ int ! timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, fsec_t *fsec, char **tzn) { Timestamp date; Timestamp time; --- 978,989 ---- * Returns: * 0 on success * -1 on out of range + * + * If attimezone is NULL, the global timezone (including possblly brute forced + * timezone) will be used. */ int ! timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, fsec_t *fsec, char **tzn, pg_tz *attimezone) { Timestamp date; Timestamp time; *************** *** 991,997 **** * specified. Go ahead and rotate to the local time zone since we will * later bypass any calls which adjust the tm fields. */ ! if (HasCTZSet && (tzp != NULL)) { #ifdef HAVE_INT64_TIMESTAMP dt -= CTimeZone * USECS_PER_SEC; --- 994,1000 ---- * specified. Go ahead and rotate to the local time zone since we will * later bypass any calls which adjust the tm fields. */ ! if ((attimezone==NULL) && HasCTZSet && (tzp != NULL)) { #ifdef HAVE_INT64_TIMESTAMP dt -= CTimeZone * USECS_PER_SEC; *************** *** 1044,1050 **** * We have a brute force time zone per SQL99? Then use it without * change since we have already rotated to the time zone. */ ! if (HasCTZSet) { *tzp = CTimeZone; tm->tm_isdst = 0; --- 1047,1053 ---- * We have a brute force time zone per SQL99? Then use it without * change since we have already rotated to the time zone. */ ! if ((attimezone==NULL) && HasCTZSet) { *tzp = CTimeZone; tm->tm_isdst = 0; *************** *** 1075,1081 **** utime = (pg_time_t) dt; if ((Timestamp) utime == dt) { ! struct pg_tm *tx = pg_localtime(&utime, global_timezone); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; --- 1078,1084 ---- utime = (pg_time_t) dt; if ((Timestamp) utime == dt) { ! struct pg_tm *tx = pg_localtime(&utime, (attimezone!=NULL)?attimezone:global_timezone); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; *************** *** 1920,1926 **** *tm = &tt; fsec_t fsec; ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 1923,1929 ---- *tm = &tt; fsec_t fsec; ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 1999,2005 **** *tm = &tt; fsec_t fsec; ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 2002,2008 ---- *tm = &tt; fsec_t fsec; ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 2326,2333 **** result = (Interval *) palloc(sizeof(Interval)); ! if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL) == 0 && ! timestamp2tm(dt2, NULL, tm2, &fsec2, NULL) == 0) { fsec = (fsec1 - fsec2); tm->tm_sec = tm1->tm_sec - tm2->tm_sec; --- 2329,2336 ---- result = (Interval *) palloc(sizeof(Interval)); ! if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 && ! timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0) { fsec = (fsec1 - fsec2); tm->tm_sec = tm1->tm_sec - tm2->tm_sec; *************** *** 2440,2447 **** result = (Interval *) palloc(sizeof(Interval)); ! if (timestamp2tm(dt1, &tz1, tm1, &fsec1, &tzn) == 0 && ! timestamp2tm(dt2, &tz2, tm2, &fsec2, &tzn) == 0) { fsec = fsec1 - fsec2; tm->tm_sec = tm1->tm_sec - tm2->tm_sec; --- 2443,2450 ---- result = (Interval *) palloc(sizeof(Interval)); ! if (timestamp2tm(dt1, &tz1, tm1, &fsec1, &tzn, NULL) == 0 && ! timestamp2tm(dt2, &tz2, tm2, &fsec2, &tzn, NULL) == 0) { fsec = fsec1 - fsec2; tm->tm_sec = tm1->tm_sec - tm2->tm_sec; *************** *** 2744,2750 **** if (type == UNITS) { ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 2747,2753 ---- if (type == UNITS) { ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 2875,2881 **** if (type == UNITS) { ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 2878,2884 ---- if (type == UNITS) { ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3265,3271 **** if (type == UNITS) { ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3268,3274 ---- if (type == UNITS) { ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3399,3405 **** * convert to timestamptz to produce consistent * results */ ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3402,3408 ---- * convert to timestamptz to produce consistent * results */ ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3419,3425 **** break; } case DTK_DOW: ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3422,3428 ---- break; } case DTK_DOW: ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3427,3433 **** break; case DTK_DOY: ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3430,3436 ---- break; case DTK_DOY: ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3490,3496 **** if (type == UNITS) { ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3493,3499 ---- if (type == UNITS) { ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3625,3631 **** break; case DTK_DOW: ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3628,3634 ---- break; case DTK_DOW: ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3633,3639 **** break; case DTK_DOY: ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3636,3642 ---- break; case DTK_DOY: ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3809,3846 **** { text *zone = PG_GETARG_TEXT_P(0); Timestamp timestamp = PG_GETARG_TIMESTAMP(1); ! TimestampTz result; int tz; ! int type, ! val; ! char *lowzone; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_TIMESTAMPTZ(timestamp); ! lowzone = downcase_truncate_identifier(VARDATA(zone), ! VARSIZE(zone) - VARHDRSZ, ! false); ! ! type = DecodeSpecial(0, lowzone, &val); ! ! if (type == TZ || type == DTZ) ! { ! tz = -(val * 60); ! ! result = dt2local(timestamp, tz); ! } ! else ! { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" not recognized", ! lowzone))); ! PG_RETURN_NULL(); } ! PG_RETURN_TIMESTAMPTZ(result); } /* timestamp_zone() */ /* timestamp_izone() --- 3812,3851 ---- { text *zone = PG_GETARG_TEXT_P(0); Timestamp timestamp = PG_GETARG_TIMESTAMP(1); ! Timestamp result; int tz; ! pg_tz *tzp; ! char tzname[TZ_STRLEN_MAX+1]; ! int len; ! struct pg_tm tm; ! fsec_t fsec; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_TIMESTAMPTZ(timestamp); ! /* Find the specified timezone? */ ! len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ); ! memcpy(tzname,VARDATA(zone),len); ! tzname[len] = 0; ! tzp = pg_tzset(tzname); ! if (!tzp) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" not recognised", ! tzname))); PG_RETURN_NULL(); } ! /* Apply the timezone change */ ! if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0 || ! tm2timestamp(&tm, fsec, NULL, &result) != 0) { ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("could not convert to time zone \"%s\"", ! tzname))); ! PG_RETURN_NULL(); ! } ! PG_RETURN_TIMESTAMPTZ(timestamp2timestamptz(result)); } /* timestamp_zone() */ /* timestamp_izone() *************** *** 3900,3906 **** else { ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3905,3911 ---- else { ! if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3935,3941 **** else { ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); --- 3940,3946 ---- else { ! if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); *************** *** 3944,3950 **** (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); } - PG_RETURN_TIMESTAMP(result); } --- 3949,3954 ---- *************** *** 3960,3990 **** Timestamp result; int tz; ! int type, ! val; ! char *lowzone; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! lowzone = downcase_truncate_identifier(VARDATA(zone), ! VARSIZE(zone) - VARHDRSZ, ! false); ! ! type = DecodeSpecial(0, lowzone, &val); ! if (type == TZ || type == DTZ) ! { ! tz = val * 60; ! result = dt2local(timestamp, tz); } - else - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("time zone \"%s\" not recognized", lowzone))); PG_RETURN_NULL(); } --- 3964,3997 ---- Timestamp result; int tz; ! pg_tz *tzp; ! char tzname[TZ_STRLEN_MAX]; ! int len; ! struct pg_tm tm; ! fsec_t fsec = 0; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); ! /* Find the specified zone */ ! len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ); ! memcpy(tzname,VARDATA(zone),len); ! tzname[len] = 0; ! tzp = pg_tzset(tzname); ! if (!tzp) { ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" not recognized", tzname))); ! PG_RETURN_NULL(); } + if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0 || + tm2timestamp(&tm, fsec, NULL, &result)) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not to convert to time zone \"%s\"", tzname))); PG_RETURN_NULL(); } Index: src/include/pgtime.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/pgtime.h,v retrieving revision 1.7 diff -c -r1.7 pgtime.h *** src/include/pgtime.h 19 Apr 2005 03:13:59 -0000 1.7 --- src/include/pgtime.h 6 Jun 2005 17:30:30 -0000 *************** *** 57,60 **** --- 57,64 ---- extern const char *pg_get_timezone_name(pg_tz *tz); extern pg_tz *global_timezone; + + /* Maximum length of a timezone name */ + #define TZ_STRLEN_MAX 255 + #endif /* _PGTIME_H */ Index: src/include/utils/timestamp.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/utils/timestamp.h,v retrieving revision 1.43 diff -c -r1.43 timestamp.h *** src/include/utils/timestamp.h 25 May 2005 21:40:42 -0000 1.43 --- src/include/utils/timestamp.h 6 Jun 2005 17:30:32 -0000 *************** *** 260,266 **** extern int tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt); extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, ! fsec_t *fsec, char **tzn); extern void dt2time(Timestamp dt, int *hour, int *min, int *sec, fsec_t *fsec); extern int interval2tm(Interval span, struct pg_tm * tm, fsec_t *fsec); --- 260,266 ---- extern int tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt); extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, ! fsec_t *fsec, char **tzn, pg_tz *attimezone); extern void dt2time(Timestamp dt, int *hour, int *min, int *sec, fsec_t *fsec); extern int interval2tm(Interval span, struct pg_tm * tm, fsec_t *fsec); Index: src/timezone/pgtz.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/timezone/pgtz.h,v retrieving revision 1.11 diff -c -r1.11 pgtz.h *** src/timezone/pgtz.h 19 Apr 2005 03:13:59 -0000 1.11 --- src/timezone/pgtz.h 6 Jun 2005 17:30:33 -0000 *************** *** 18,25 **** #include "tzfile.h" - #define TZ_STRLEN_MAX 255 - extern char *pg_TZDIR(void); #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) --- 18,23 ----