diff options
author | Bruce Momjian <bruce@momjian.us> | 2005-07-24 04:37:07 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2005-07-24 04:37:07 +0000 |
commit | 8b60f8e6c938e9bf2f6fce489679cbac07110da4 (patch) | |
tree | 936c42da5e22d4ae436bf78e7bc4f3399e5eeed3 /src/backend/utils/adt/timestamp.c | |
parent | c17abc1c5463119803be73990c9aa570763fd0c1 (diff) | |
download | postgresql-8b60f8e6c938e9bf2f6fce489679cbac07110da4.tar.gz postgresql-8b60f8e6c938e9bf2f6fce489679cbac07110da4.zip |
Fix rounding problem in interval_div by using rint(), and improve
interval_mul function.
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 56 |
1 files changed, 28 insertions, 28 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index ac628453441..85c5bda35f4 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.145 2005/07/23 14:53:21 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.146 2005/07/24 04:37:07 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2244,38 +2244,37 @@ interval_mi(PG_FUNCTION_ARGS) Datum interval_mul(PG_FUNCTION_ARGS) { - Interval *span1 = PG_GETARG_INTERVAL_P(0); + Interval *span = PG_GETARG_INTERVAL_P(0); float8 factor = PG_GETARG_FLOAT8(1); + double month_remainder, day_remainder; Interval *result; -#ifdef HAVE_INT64_TIMESTAMP - int64 months; - int64 days; -#else - double months; - double days; -#endif - result = (Interval *) palloc(sizeof(Interval)); - months = span1->month * factor; - days = span1->day * factor; + result->month = span->month * factor; + result->day = span->day * factor; + + /* Compute remainders */ + month_remainder = span->month * factor - result->month; + day_remainder = span->day * factor - result->day; + + /* Cascade fractions to lower units */ + /* fractional months full days into days */ + result->day += month_remainder * DAYS_PER_MONTH; + /* fractional months partial days into time */ + day_remainder += (month_remainder * DAYS_PER_MONTH) - + (int)(month_remainder * DAYS_PER_MONTH); + #ifdef HAVE_INT64_TIMESTAMP - result->month = months; - result->day = days; - result->time = span1->time * factor; - result->time += (months - result->month) * INT64CONST(30) * USECS_PER_DAY; - result->time += (days - result->day) * INT64CONST(24) * USECS_PER_HOUR; + result->time = rint(span->time * factor + + day_remainder * USECS_PER_DAY); #else - result->month = (int)months; - result->day = (int)days; - result->time = JROUND(span1->time * factor); - /* evaluate fractional months as 30 days */ - result->time += JROUND((months - result->month) * DAYS_PER_MONTH * SECS_PER_DAY); - /* evaluate fractional days as 24 hours */ - result->time += JROUND((days - result->day) * HOURS_PER_DAY * SECS_PER_HOUR); + result->time = JROUND(span->time * factor + + day_remainder * SECS_PER_DAY); #endif + result = DatumGetIntervalP(DirectFunctionCall1(interval_justify_hours, + IntervalPGetDatum(result))); PG_RETURN_INTERVAL_P(result); } @@ -2284,9 +2283,9 @@ mul_d_interval(PG_FUNCTION_ARGS) { /* Args are float8 and Interval *, but leave them as generic Datum */ Datum factor = PG_GETARG_DATUM(0); - Datum span1 = PG_GETARG_DATUM(1); + Datum span = PG_GETARG_DATUM(1); - return DirectFunctionCall2(interval_mul, span1, factor); + return DirectFunctionCall2(interval_mul, span, factor); } Datum @@ -2316,10 +2315,11 @@ interval_div(PG_FUNCTION_ARGS) /* fractional months full days into days */ result->day += month_remainder * DAYS_PER_MONTH; /* fractional months partial days into time */ - day_remainder += (month_remainder * DAYS_PER_MONTH) - (int)(month_remainder * DAYS_PER_MONTH); + day_remainder += (month_remainder * DAYS_PER_MONTH) - + (int)(month_remainder * DAYS_PER_MONTH); #ifdef HAVE_INT64_TIMESTAMP - result->time += day_remainder * USECS_PER_DAY; + result->time += rint(day_remainder * USECS_PER_DAY); #else result->time += day_remainder * SECS_PER_DAY; result->time = JROUND(result->time); |