BUG #15696: year field of interval type is not rounded to nearest integer - Mailing list pgsql-bugs

From PG Bug reporting form
Subject BUG #15696: year field of interval type is not rounded to nearest integer
Date
Msg-id 15696-50cd52decb98f630@postgresql.org
Whole thread Raw
Responses Re: BUG #15696: year field of interval type is not rounded to nearest integer  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-bugs
The following bug has been logged on the website:

Bug reference:      15696
Logged by:          zhou xiaowei
Email address:      110876189@qq.com
PostgreSQL version: 11.2
Operating system:   Linux x86_64
Description:

all fields of interval type use rule of rounding to nearest integer(by
rint() function), except for year field.
details:
postgres=# select '0.9999999999999999 year'::interval month;
 interval
----------
 11 mons
(1 row)

postgres=# select '0.9999999999999999 dec'::interval year;
 interval
----------
 9 years
(1 row)

postgres=# select '0.9999999999999999 cent'::interval year;
 interval
----------
 99 years
(1 row)

postgres=# select '0.9999999999999999 mil'::interval year;
 interval
-----------
 999 years
(1 row)

the reason is that assign double value to int value in function
DecodeInterval() :
int DecodeInterval(char **field, int *ftype, int nf, int range,
               int *dtype, struct pg_tm *tm, fsec_t *fsec)
{
    double        fval;
    .......
        switch (ftype[i])
                    case DTK_YEAR:
                        tm->tm_year += val;
                        if (fval != 0)
                            tm->tm_mon += fval * MONTHS_PER_YEAR;
                        tmask = DTK_M(YEAR);
                        break;
                    case DTK_DECADE:
                        tm->tm_year += val * 10;
                        if (fval != 0)
                            tm->tm_mon += fval * MONTHS_PER_YEAR * 10;
                        tmask = DTK_M(DECADE);
                        break;

                    case DTK_CENTURY:
                        tm->tm_year += val * 100;
                        if (fval != 0)
                            tm->tm_mon += fval * MONTHS_PER_YEAR * 100;
                        tmask = DTK_M(CENTURY);
                        break;

                    case DTK_MILLENNIUM:
                        tm->tm_year += val * 1000;
                        if (fval != 0)
                            tm->tm_mon += fval * MONTHS_PER_YEAR * 1000;
                        tmask = DTK_M(MILLENNIUM);
                        break;
    ......
}
The code 'tm->tm_mon' is int type.I think this is a bug,need use rint() to
adjust it’s result,like:
tm->tm_mon += rint(fval * MONTHS_PER_YEAR * 1000);


pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: pg_restore: [archiver (db)] could not execute query: ERROR: operator does not exist: public.hstore = public.hstore
Next
From: PG Bug reporting form
Date:
Subject: BUG #15697: Restarting the server because of the error checkpointer