1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

The following patches eliminate the overflows in the j2date() and date2j()

functions which limited the maximum date for a timestamp to AD 1465001.
The new limit is AD 5874897.
The files affected are:

doc/src/sgml/datatype.sgml:
    Documentation change due to patch. Included is a notice about
    the reduced range when using an eight-byte integer for timestamps.

src/backend/utils/adt/datetime.c:
    Replacement functions for j2date() and date2j() functions.

src/include/utils/datetime.h:
    Corrected a bug with the limit on the earliest possible date,
    Nov 23,-4713 has a Julian day count of -1. The earliest possible
    date should be Nov 24, -4713 with a day count of 0.

src/test/regress/expected/horology-no-DST-before-1970.out:
src/test/regress/expected/horology-solaris-1947.out:
src/test/regress/expected/horology.out:
    Copies of expected output for regression testing.
    Note: Only horology.out has been physically tested. I do not have access
    to a Solaris box and I don't know how to provoke the "pre-1970" test.

src/test/regress/sql/horology.sql:
    Added some test cases to check extended range.

John Cochran
This commit is contained in:
Bruce Momjian
2003-02-19 03:48:11 +00:00
parent 4efbbd7318
commit a286f73210
7 changed files with 131 additions and 43 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.99 2003/01/29 01:08:42 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.100 2003/02/19 03:48:10 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -587,66 +587,77 @@ static datetkn *deltacache[MAXDATEFIELDS] = {NULL};
* since it is numerically accurate and computationally simple.
* The algorithms here will accurately convert between Julian day
* and calendar date for all non-negative Julian days
* (i.e. from Nov 23, -4713 on).
*
* Ref: Explanatory Supplement to the Astronomical Almanac, 1992.
* University Science Books, 20 Edgehill Rd. Mill Valley CA 94941.
*
* Use the algorithm by Henry Fliegel, a former NASA/JPL colleague
* now at Aerospace Corp. (hi, Henry!)
* (i.e. from Nov 24, -4713 on).
*
* These routines will be used by other date/time packages
* - thomas 97/02/25
*
* Rewritten to eliminate overflow problems. This now allows the
* routines to work correctly for all Julian day counts from
* 0 to 2147483647 (Nov 24, -4713 to Jun 3, 5874898) assuming
* a 32-bit integer. Longer types should also work to the limits
* of their precision.
*/
int
date2j(int y, int m, int d)
{
int m12 = (m - 14) / 12;
int julian;
int century;
return ((1461 * (y + 4800 + m12)) / 4
+ (367 * (m - 2 - 12 * (m12))) / 12
- (3 * ((y + 4900 + m12) / 100)) / 4
+ d - 32075);
if (m > 2) {
m += 1;
y += 4800;
} else {
m += 13;
y += 4799;
}
century = y/100;
julian = y*365 - 32167;
julian += y/4 - century + century/4;
julian += 7834*m/256 + d;
return julian;
} /* date2j() */
void
j2date(int jd, int *year, int *month, int *day)
{
int j,
y,
m,
d;
unsigned int julian;
unsigned int quad;
unsigned int extra;
int y;
int i,
l,
n;
julian = jd;
julian += 32044;
quad = julian/146097;
extra = (julian - quad*146097)*4 + 3;
julian += 60 + quad*3 + extra/146097;
quad = julian/1461;
julian -= quad*1461;
y = julian * 4 / 1461;
julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
+ 123;
y += quad*4;
*year = y - 4800;
quad = julian * 2141 / 65536;
*day = julian - 7834*quad/256;
*month = (quad + 10) % 12 + 1;
l = jd + 68569;
n = (4 * l) / 146097;
l -= (146097 * n + 3) / 4;
i = (4000 * (l + 1)) / 1461001;
l += 31 - (1461 * i) / 4;
j = (80 * l) / 2447;
d = l - (2447 * j) / 80;
l = j / 11;
m = (j + 2) - (12 * l);
y = 100 * (n - 49) + i + l;
*year = y;
*month = m;
*day = d;
return;
} /* j2date() */
int
j2day(int date)
{
int day;
unsigned int day;
day = (date + 1) % 7;
day = date;
day += 1;
day %= 7;
return day;
return (int) day;
} /* j2day() */