Skip to content

Commit 8b60f8e

Browse files
committed
Fix rounding problem in interval_div by using rint(), and improve
interval_mul function.
1 parent c17abc1 commit 8b60f8e

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

src/backend/utils/adt/timestamp.c

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.145 2005/07/23 14:53:21 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.146 2005/07/24 04:37:07 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2244,38 +2244,37 @@ interval_mi(PG_FUNCTION_ARGS)
22442244
Datum
22452245
interval_mul(PG_FUNCTION_ARGS)
22462246
{
2247-
Interval *span1 = PG_GETARG_INTERVAL_P(0);
2247+
Interval *span = PG_GETARG_INTERVAL_P(0);
22482248
float8 factor = PG_GETARG_FLOAT8(1);
2249+
double month_remainder, day_remainder;
22492250
Interval *result;
22502251

2251-
#ifdef HAVE_INT64_TIMESTAMP
2252-
int64 months;
2253-
int64 days;
2254-
#else
2255-
double months;
2256-
double days;
2257-
#endif
2258-
22592252
result = (Interval *) palloc(sizeof(Interval));
22602253

2261-
months = span1->month * factor;
2262-
days = span1->day * factor;
2254+
result->month = span->month * factor;
2255+
result->day = span->day * factor;
2256+
2257+
/* Compute remainders */
2258+
month_remainder = span->month * factor - result->month;
2259+
day_remainder = span->day * factor - result->day;
2260+
2261+
/* Cascade fractions to lower units */
2262+
/* fractional months full days into days */
2263+
result->day += month_remainder * DAYS_PER_MONTH;
2264+
/* fractional months partial days into time */
2265+
day_remainder += (month_remainder * DAYS_PER_MONTH) -
2266+
(int)(month_remainder * DAYS_PER_MONTH);
2267+
22632268
#ifdef HAVE_INT64_TIMESTAMP
2264-
result->month = months;
2265-
result->day = days;
2266-
result->time = span1->time * factor;
2267-
result->time += (months - result->month) * INT64CONST(30) * USECS_PER_DAY;
2268-
result->time += (days - result->day) * INT64CONST(24) * USECS_PER_HOUR;
2269+
result->time = rint(span->time * factor +
2270+
day_remainder * USECS_PER_DAY);
22692271
#else
2270-
result->month = (int)months;
2271-
result->day = (int)days;
2272-
result->time = JROUND(span1->time * factor);
2273-
/* evaluate fractional months as 30 days */
2274-
result->time += JROUND((months - result->month) * DAYS_PER_MONTH * SECS_PER_DAY);
2275-
/* evaluate fractional days as 24 hours */
2276-
result->time += JROUND((days - result->day) * HOURS_PER_DAY * SECS_PER_HOUR);
2272+
result->time = JROUND(span->time * factor +
2273+
day_remainder * SECS_PER_DAY);
22772274
#endif
22782275

2276+
result = DatumGetIntervalP(DirectFunctionCall1(interval_justify_hours,
2277+
IntervalPGetDatum(result)));
22792278
PG_RETURN_INTERVAL_P(result);
22802279
}
22812280

@@ -2284,9 +2283,9 @@ mul_d_interval(PG_FUNCTION_ARGS)
22842283
{
22852284
/* Args are float8 and Interval *, but leave them as generic Datum */
22862285
Datum factor = PG_GETARG_DATUM(0);
2287-
Datum span1 = PG_GETARG_DATUM(1);
2286+
Datum span = PG_GETARG_DATUM(1);
22882287

2289-
return DirectFunctionCall2(interval_mul, span1, factor);
2288+
return DirectFunctionCall2(interval_mul, span, factor);
22902289
}
22912290

22922291
Datum
@@ -2316,10 +2315,11 @@ interval_div(PG_FUNCTION_ARGS)
23162315
/* fractional months full days into days */
23172316
result->day += month_remainder * DAYS_PER_MONTH;
23182317
/* fractional months partial days into time */
2319-
day_remainder += (month_remainder * DAYS_PER_MONTH) - (int)(month_remainder * DAYS_PER_MONTH);
2318+
day_remainder += (month_remainder * DAYS_PER_MONTH) -
2319+
(int)(month_remainder * DAYS_PER_MONTH);
23202320

23212321
#ifdef HAVE_INT64_TIMESTAMP
2322-
result->time += day_remainder * USECS_PER_DAY;
2322+
result->time += rint(day_remainder * USECS_PER_DAY);
23232323
#else
23242324
result->time += day_remainder * SECS_PER_DAY;
23252325
result->time = JROUND(result->time);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy