From 6acdebbd3a6e516e26b9d5ff7c51e51802e7345b Mon Sep 17 00:00:00 2001 From: "Thomas G. Lockhart" <lockhart@fourpalms.org> Date: Thu, 18 Jan 2001 07:22:43 +0000 Subject: [PATCH] Fix up "Postgres-style" time interval representation when fields have mixed-signs. Previous effort left way too many minus signs, and was at least as broken as the one before that :( Clean up "ISO-style" time interval representation to omit zero fields if there is at least one non-zero field. Supress some leading plus signs when not necessary for clarity. Replace every #ifdef __CYGWIN__ block with a cleaner TIMEZONE_GLOBAL macro defined in datetime.h. --- src/backend/utils/adt/datetime.c | 50 ++++--- src/backend/utils/adt/formatting.c | 10 +- src/backend/utils/adt/nabstime.c | 16 +- src/backend/utils/adt/timestamp.c | 27 +--- src/include/utils/datetime.h | 7 +- src/test/regress/expected/interval.out | 196 ++++++++++++------------- 6 files changed, 146 insertions(+), 160 deletions(-) diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 659cc584ba3..4dbd05eb8fd 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.58 2001/01/17 16:46:56 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.59 2001/01/18 07:22:35 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -880,11 +880,7 @@ DecodeDateTime(char **field, int *ftype, int nf, *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is * Sun/DEC-ism */ # elif defined(HAVE_INT_TIMEZONE) -# ifdef __CYGWIN__ - *tzp = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif /* __CYGWIN__ */ + *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); # endif /* HAVE_INT_TIMEZONE */ #else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */ @@ -1128,11 +1124,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf, # if defined(HAVE_TM_ZONE) *tzp = -(tmp->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ # elif defined(HAVE_INT_TIMEZONE) -# ifdef __CYGWIN__ - *tzp = ((tmp->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - *tzp = ((tmp->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif + *tzp = ((tmp->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); # endif #else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */ @@ -2252,12 +2244,14 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) is_before = (tm->tm_mday < 0); is_nonzero = TRUE; } + if ((!is_nonzero) || (tm->tm_hour != 0) || (tm->tm_min != 0) + || (tm->tm_sec != 0) || (fsec != 0)) { int minus = ((tm->tm_hour < 0) || (tm->tm_min < 0) || (tm->tm_sec < 0) || (fsec < 0)); sprintf(cp, "%s%s%02d:%02d", (is_nonzero ? " " : ""), - (minus ? "-" : (is_nonzero ? "+" : "")), + (minus ? "-" : (is_before ? "+" : "")), abs(tm->tm_hour), abs(tm->tm_min)); cp += strlen(cp); /* Mark as "non-zero" since the fields are now filled in */ @@ -2289,7 +2283,9 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) if (tm->tm_year != 0) { - int year = ((tm->tm_year < 0) ? -(tm->tm_year) : tm->tm_year); + int year = tm->tm_year; + if (tm->tm_year < 0) + year = -year; sprintf(cp, "%d year%s", year, ((year != 1) ? "s" : "")); @@ -2300,7 +2296,9 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) if (tm->tm_mon != 0) { - int mon = ((is_before && (tm->tm_mon > 0)) ? -(tm->tm_mon) : tm->tm_mon); + int mon = tm->tm_mon; + if (is_before || ((!is_nonzero) && (tm->tm_mon < 0))) + mon = -mon; sprintf(cp, "%s%d mon%s", (is_nonzero ? " " : ""), mon, ((mon != 1) ? "s" : "")); @@ -2312,7 +2310,9 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) if (tm->tm_mday != 0) { - int day = ((is_before && (tm->tm_mday > 0)) ? -(tm->tm_mday) : tm->tm_mday); + int day = tm->tm_mday; + if (is_before || ((!is_nonzero) && (tm->tm_mday < 0))) + day = -day; sprintf(cp, "%s%d day%s", (is_nonzero ? " " : ""), day, ((day != 1) ? "s" : "")); @@ -2323,7 +2323,9 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) } if (tm->tm_hour != 0) { - int hour = ((is_before && (tm->tm_hour > 0)) ? -(tm->tm_hour) : tm->tm_hour); + int hour = tm->tm_hour; + if (is_before || ((!is_nonzero) && (tm->tm_hour < 0))) + hour = -hour; sprintf(cp, "%s%d hour%s", (is_nonzero ? " " : ""), hour, ((hour != 1) ? "s" : "")); @@ -2335,7 +2337,9 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) if (tm->tm_min != 0) { - int min = ((is_before && (tm->tm_min > 0)) ? -(tm->tm_min) : tm->tm_min); + int min = tm->tm_min; + if (is_before || ((!is_nonzero) && (tm->tm_min < 0))) + min = -min; sprintf(cp, "%s%d min%s", (is_nonzero ? " " : ""), min, ((min != 1) ? "s" : "")); @@ -2348,9 +2352,13 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) /* fractional seconds? */ if (fsec != 0) { + double sec; fsec += tm->tm_sec; - sprintf(cp, "%s%.2f secs", (is_nonzero ? " " : ""), - ((is_before && (fsec > 0)) ? -(fsec) : fsec)); + sec = fsec; + if (is_before || ((!is_nonzero) && (fsec < 0))) + sec = -sec; + + sprintf(cp, "%s%.2f secs", (is_nonzero ? " " : ""), sec); cp += strlen(cp); if (! is_nonzero) is_before = (fsec < 0); @@ -2360,7 +2368,9 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) } else if (tm->tm_sec != 0) { - int sec = ((is_before && (tm->tm_sec > 0)) ? -(tm->tm_sec) : tm->tm_sec); + int sec = tm->tm_sec; + if (is_before || ((!is_nonzero) && (tm->tm_sec < 0))) + sec = -sec; sprintf(cp, "%s%d sec%s", (is_nonzero ? " " : ""), sec, ((sec != 1) ? "s" : "")); diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 7996c47f58f..79699839c33 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * formatting.c * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.29 2001/01/17 16:46:56 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.30 2001/01/18 07:22:36 thomas Exp $ * * * Portions Copyright (c) 1999-2000, PostgreSQL, Inc @@ -2931,13 +2931,7 @@ to_timestamp(PG_FUNCTION_ARGS) # if defined(HAVE_TM_ZONE) tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ # elif defined(HAVE_INT_TIMEZONE) - -# ifdef __CYGWIN__ - tz = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - tz = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif - + tz = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); # endif #else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */ diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 19c2068fe94..972f5e98a6b 100644 --- a/src/backend/utils/adt/nabstime.c +++ b/src/backend/utils/adt/nabstime.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.78 2001/01/17 16:46:56 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.79 2001/01/18 07:22:36 thomas Exp $ * * NOTES * @@ -160,12 +160,7 @@ GetCurrentAbsoluteTime(void) tm = localtime(&now); CDayLight = tm->tm_isdst; - CTimeZone = -# ifdef __CYGWIN__ - ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif + CTimeZone = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); strcpy(CTZName, tzname[tm->tm_isdst]); #else /* neither HAVE_TM_ZONE nor HAVE_INT_TIMEZONE */ CTimeZone = tb.timezone * 60; @@ -244,11 +239,8 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char *tzn) } # elif defined(HAVE_INT_TIMEZONE) if (tzp != NULL) -# ifdef __CYGWIN__ - *tzp = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif + *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); + if (tzn != NULL) { diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 144aec0cbe7..dd3a5f47e15 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.42 2001/01/17 16:46:56 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.43 2001/01/18 07:22:36 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -324,9 +324,10 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn) /* XXX HACK * Argh! My Linux box puts in a 1 second offset for dates less than 1970 * but only if the seconds field was non-zero. So, don't copy the seconds - * field and instead carry forward from the original - tgl 97/06/18 + * field and instead carry forward from the original - thomas 97/06/18 * Note that GNU/Linux uses the standard freeware zic package as do * many other platforms so this may not be GNU/Linux/ix86-specific. + * Still shows a problem on my up to date Linux box - thomas 2001-01-17 */ tm->tm_sec = tx->tm_sec; #endif @@ -340,11 +341,7 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn) if (tzn != NULL) *tzn = (char *) tm->tm_zone; # elif defined(HAVE_INT_TIMEZONE) -# ifdef __CYGWIN__ - *tzp = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif + *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); if (tzn != NULL) *tzn = tzname[(tm->tm_isdst > 0)]; # endif @@ -1084,13 +1081,7 @@ timestamp_pl_span(PG_FUNCTION_ARGS) # if defined(HAVE_TM_ZONE) tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ # elif defined(HAVE_INT_TIMEZONE) - -# ifdef __CYGWIN__ - tz = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - tz = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif - + tz = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); # endif #else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */ @@ -1733,13 +1724,7 @@ timestamp_trunc(PG_FUNCTION_ARGS) # if defined(HAVE_TM_ZONE) tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ # elif defined(HAVE_INT_TIMEZONE) - -# ifdef __CYGWIN__ - tz = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone); -# else - tz = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -# endif - + tz = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL); # endif #else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */ diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 15d8ab92842..9e28436a31b 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: datetime.h,v 1.15 2000/06/08 22:37:58 momjian Exp $ + * $Id: datetime.h,v 1.16 2001/01/18 07:22:42 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -193,6 +193,11 @@ do { \ t -= rint(q * u); \ } while(0) +#ifdef __CYGWIN__ +#define TIMEZONE_GLOBAL _timezone +#else +#define TIMEZONE_GLOBAL timezone +#endif /* * Date/time validation diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index d76c922a141..8a4eb275906 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -6,13 +6,13 @@ SET DATESTYLE = DEFAULT; SELECT INTERVAL '01:00' AS "One hour"; One hour ---------- - +01:00 + 01:00 (1 row) SELECT INTERVAL '+02:00' AS "Two hours"; Two hours ----------- - +02:00 + 02:00 (1 row) SELECT INTERVAL '-08:00' AS "Eight hours"; @@ -40,9 +40,9 @@ SELECT INTERVAL '-1 days +02:03' AS "22 hours ago..."; (1 row) SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years..."; - 9 years... --------------------------- - 9 years 1 mon -11 -10:46 + 9 years... +------------------------------- + 9 years 1 mon -11 days -10:46 (1 row) CREATE TABLE INTERVAL_TBL (f1 interval); @@ -63,41 +63,41 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago'); ERROR: Bad interval external representation '@ 30 eons ago' -- test interval operators SELECT '' AS ten, INTERVAL_TBL.*; - ten | f1 ------+----------------- - | +00:01 - | +05:00 - | 10 +00:00 - | 34 years +00:00 - | 3 mons +00:00 + ten | f1 +-----+---------------- + | 00:01 + | 05:00 + | 10 days + | 34 years + | 3 mons | -00:00:14 - | 1 +02:03:04 - | 6 years +00:00 - | 5 mons +00:00 - | 5 mons +12:00 + | 1 day 02:03:04 + | 6 years + | 5 mons + | 5 mons 12:00 (10 rows) SELECT '' AS nine, INTERVAL_TBL.* WHERE INTERVAL_TBL.f1 <> interval '@ 10 days'; - nine | f1 -------+----------------- - | +00:01 - | +05:00 - | 34 years +00:00 - | 3 mons +00:00 + nine | f1 +------+---------------- + | 00:01 + | 05:00 + | 34 years + | 3 mons | -00:00:14 - | 1 +02:03:04 - | 6 years +00:00 - | 5 mons +00:00 - | 5 mons +12:00 + | 1 day 02:03:04 + | 6 years + | 5 mons + | 5 mons 12:00 (9 rows) SELECT '' AS three, INTERVAL_TBL.* WHERE INTERVAL_TBL.f1 <= interval '@ 5 hours'; three | f1 -------+----------- - | +00:01 - | +05:00 + | 00:01 + | 05:00 | -00:00:14 (3 rows) @@ -105,95 +105,95 @@ SELECT '' AS three, INTERVAL_TBL.* WHERE INTERVAL_TBL.f1 < interval '@ 1 day'; three | f1 -------+----------- - | +00:01 - | +05:00 + | 00:01 + | 05:00 | -00:00:14 (3 rows) SELECT '' AS one, INTERVAL_TBL.* WHERE INTERVAL_TBL.f1 = interval '@ 34 years'; - one | f1 ------+----------------- - | 34 years +00:00 + one | f1 +-----+---------- + | 34 years (1 row) SELECT '' AS five, INTERVAL_TBL.* WHERE INTERVAL_TBL.f1 >= interval '@ 1 month'; - five | f1 -------+----------------- - | 34 years +00:00 - | 3 mons +00:00 - | 6 years +00:00 - | 5 mons +00:00 - | 5 mons +12:00 + five | f1 +------+-------------- + | 34 years + | 3 mons + | 6 years + | 5 mons + | 5 mons 12:00 (5 rows) SELECT '' AS nine, INTERVAL_TBL.* WHERE INTERVAL_TBL.f1 > interval '@ 3 seconds ago'; - nine | f1 -------+----------------- - | +00:01 - | +05:00 - | 10 +00:00 - | 34 years +00:00 - | 3 mons +00:00 - | 1 +02:03:04 - | 6 years +00:00 - | 5 mons +00:00 - | 5 mons +12:00 + nine | f1 +------+---------------- + | 00:01 + | 05:00 + | 10 days + | 34 years + | 3 mons + | 1 day 02:03:04 + | 6 years + | 5 mons + | 5 mons 12:00 (9 rows) SELECT '' AS fortyfive, r1.*, r2.* FROM INTERVAL_TBL r1, INTERVAL_TBL r2 WHERE r1.f1 > r2.f1 ORDER BY r1.f1, r2.f1; - fortyfive | f1 | f1 ------------+-----------------+---------------- - | +00:01 | -00:00:14 - | +05:00 | -00:00:14 - | +05:00 | +00:01 - | 1 +02:03:04 | -00:00:14 - | 1 +02:03:04 | +00:01 - | 1 +02:03:04 | +05:00 - | 10 +00:00 | -00:00:14 - | 10 +00:00 | +00:01 - | 10 +00:00 | +05:00 - | 10 +00:00 | 1 +02:03:04 - | 3 mons +00:00 | -00:00:14 - | 3 mons +00:00 | +00:01 - | 3 mons +00:00 | +05:00 - | 3 mons +00:00 | 1 +02:03:04 - | 3 mons +00:00 | 10 +00:00 - | 5 mons +00:00 | -00:00:14 - | 5 mons +00:00 | +00:01 - | 5 mons +00:00 | +05:00 - | 5 mons +00:00 | 1 +02:03:04 - | 5 mons +00:00 | 10 +00:00 - | 5 mons +00:00 | 3 mons +00:00 - | 5 mons +12:00 | -00:00:14 - | 5 mons +12:00 | +00:01 - | 5 mons +12:00 | +05:00 - | 5 mons +12:00 | 1 +02:03:04 - | 5 mons +12:00 | 10 +00:00 - | 5 mons +12:00 | 3 mons +00:00 - | 5 mons +12:00 | 5 mons +00:00 - | 6 years +00:00 | -00:00:14 - | 6 years +00:00 | +00:01 - | 6 years +00:00 | +05:00 - | 6 years +00:00 | 1 +02:03:04 - | 6 years +00:00 | 10 +00:00 - | 6 years +00:00 | 3 mons +00:00 - | 6 years +00:00 | 5 mons +00:00 - | 6 years +00:00 | 5 mons +12:00 - | 34 years +00:00 | -00:00:14 - | 34 years +00:00 | +00:01 - | 34 years +00:00 | +05:00 - | 34 years +00:00 | 1 +02:03:04 - | 34 years +00:00 | 10 +00:00 - | 34 years +00:00 | 3 mons +00:00 - | 34 years +00:00 | 5 mons +00:00 - | 34 years +00:00 | 5 mons +12:00 - | 34 years +00:00 | 6 years +00:00 + fortyfive | f1 | f1 +-----------+----------------+---------------- + | 00:01 | -00:00:14 + | 05:00 | -00:00:14 + | 05:00 | 00:01 + | 1 day 02:03:04 | -00:00:14 + | 1 day 02:03:04 | 00:01 + | 1 day 02:03:04 | 05:00 + | 10 days | -00:00:14 + | 10 days | 00:01 + | 10 days | 05:00 + | 10 days | 1 day 02:03:04 + | 3 mons | -00:00:14 + | 3 mons | 00:01 + | 3 mons | 05:00 + | 3 mons | 1 day 02:03:04 + | 3 mons | 10 days + | 5 mons | -00:00:14 + | 5 mons | 00:01 + | 5 mons | 05:00 + | 5 mons | 1 day 02:03:04 + | 5 mons | 10 days + | 5 mons | 3 mons + | 5 mons 12:00 | -00:00:14 + | 5 mons 12:00 | 00:01 + | 5 mons 12:00 | 05:00 + | 5 mons 12:00 | 1 day 02:03:04 + | 5 mons 12:00 | 10 days + | 5 mons 12:00 | 3 mons + | 5 mons 12:00 | 5 mons + | 6 years | -00:00:14 + | 6 years | 00:01 + | 6 years | 05:00 + | 6 years | 1 day 02:03:04 + | 6 years | 10 days + | 6 years | 3 mons + | 6 years | 5 mons + | 6 years | 5 mons 12:00 + | 34 years | -00:00:14 + | 34 years | 00:01 + | 34 years | 05:00 + | 34 years | 1 day 02:03:04 + | 34 years | 10 days + | 34 years | 3 mons + | 34 years | 5 mons + | 34 years | 5 mons 12:00 + | 34 years | 6 years (45 rows) SET DATESTYLE = 'postgres'; -- GitLab