From 313ed1ed9498f977262e180a080c7748197ced5c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 9 Oct 2005 17:21:47 +0000 Subject: Fix (hopefully for the last time) problems with datetime values displaying like '23:59:60' because of fractional-second roundoff problems. Trying to control this upstream of the actual display code was hopeless; the right way is to explicitly round fractional seconds in the display code and then refigure the results if the fraction rounds up to 1. Per bug #1927. --- src/backend/utils/adt/date.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/backend/utils/adt/date.c') diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index b36ee180929..ec1d808544b 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.120 2005/09/09 02:31:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.121 2005/10/09 17:21:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -944,10 +944,18 @@ time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec) #else double trem; +recalc: trem = time; TMODULO(trem, tm->tm_hour, (double)SECS_PER_HOUR); TMODULO(trem, tm->tm_min, (double)SECS_PER_MINUTE); TMODULO(trem, tm->tm_sec, 1.0); + trem = TIMEROUND(trem); + /* roundoff may need to propagate to higher-order fields */ + if (trem >= 1.0) + { + time = ceil(time); + goto recalc; + } *fsec = trem; #endif @@ -1837,9 +1845,17 @@ timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp) #else double trem = time->time; +recalc: TMODULO(trem, tm->tm_hour, (double)SECS_PER_HOUR); TMODULO(trem, tm->tm_min, (double)SECS_PER_MINUTE); TMODULO(trem, tm->tm_sec, 1.0); + trem = TIMEROUND(trem); + /* roundoff may need to propagate to higher-order fields */ + if (trem >= 1.0) + { + trem = ceil(time->time); + goto recalc; + } *fsec = trem; #endif -- cgit v1.2.3