Fix j2day() to behave sanely for negative Julian dates.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 17 Mar 2016 00:57:45 +0000 (20:57 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 17 Mar 2016 00:57:45 +0000 (20:57 -0400)
Somebody had apparently once figured that casting to unsigned int would
produce the right output for negative inputs, but that would only be
true if 2^32 were a multiple of 7, which of course it ain't.  We need
to use a signed division and then correct the sign of the remainder.

AFAICT, the only case where this would arise currently is when doing
ISO-week calculations for dates in 4714BC, where we'd compute a
negative Julian date representing 4714-01-04BC and then do some
arithmetic with it.  Since we don't even really document support for
such dates, this is not of much consequence.  But we may as well
get it right.

Per report from Vitaly Burovoy.

src/backend/utils/adt/datetime.c

index 2ea21b7028ab2b48544d4e41908d26b1b7f82ffc..46660cfe4a534a84286232efc7c248174e5b7213 100644 (file)
@@ -355,14 +355,13 @@ j2date(int jd, int *year, int *month, int *day)
 int
 j2day(int date)
 {
-   unsigned int day;
+   date += 1;
+   date %= 7;
+   /* Cope if division truncates towards zero, as it probably does */
+   if (date < 0)
+       date += 7;
 
-   day = date;
-
-   day += 1;
-   day %= 7;
-
-   return (int) day;
+   return date;
 }  /* j2day() */