From d221e149b477451cec4756a0490af7a9bb66f345 Mon Sep 17 00:00:00 2001 From: "Thomas G. Lockhart" Date: Fri, 14 Apr 2000 15:22:10 +0000 Subject: [PATCH] Fix (well, add) support for ISO "week" in date_part(). Needed for ODBC. Fix spelling of "millennium". Thanks to Mika Nystrom for spotting this. --- src/backend/utils/adt/datetime.c | 15 ++++++----- src/backend/utils/adt/timestamp.c | 42 +++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 2f899d21e9..f252a42ddc 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.46 2000/04/12 17:15:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.47 2000/04/14 15:22:10 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -260,15 +260,14 @@ static datetkn deltatktbl[] = { {"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */ {"hr", UNITS, DTK_HOUR}, /* "hour" relative time units */ {"hrs", UNITS, DTK_HOUR}, /* "hours" relative time units */ - {INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid - * time */ + {INVALID, RESERV, DTK_INVALID}, /* reserved for invalid time */ {"m", UNITS, DTK_MINUTE}, /* "minute" relative time units */ {"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative * time units */ - {"mil", UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ - {"mils", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ - {"millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ - {DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ + {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative time units */ + {"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative time units */ + {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative time units */ + {DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative time units */ {"millisecon", UNITS, DTK_MILLISEC}, /* relative time units */ {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */ {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */ @@ -1794,7 +1793,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); break; - case DTK_MILLENIUM: + case DTK_MILLENNIUM: tm->tm_year += val * 1000; if (fval != 0) tm->tm_mon += (fval * 12000); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index a731ce3cef..56ab2f10bb 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.25 2000/04/12 17:15:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.26 2000/04/14 15:22:10 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -1621,7 +1621,7 @@ timestamp_trunc(text *units, Timestamp *timestamp) { switch (val) { - case DTK_MILLENIUM: + case DTK_MILLENNIUM: tm->tm_year = (tm->tm_year / 1000) * 1000; case DTK_CENTURY: tm->tm_year = (tm->tm_year / 100) * 100; @@ -1759,7 +1759,7 @@ interval_trunc(text *units, Interval *interval) { switch (val) { - case DTK_MILLENIUM: + case DTK_MILLENNIUM: tm->tm_year = (tm->tm_year / 1000) * 1000; case DTK_CENTURY: tm->tm_year = (tm->tm_year / 100) * 100; @@ -1927,6 +1927,38 @@ timestamp_part(text *units, Timestamp *timestamp) *result = (tm->tm_mon / 4) + 1; break; + case DTK_WEEK: + { + int day0, day4, dayn; + dayn = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); + day4 = date2j(tm->tm_year, 1, 4); + /* day0 == offset to first day of week (Monday) */ + day0 = (j2day(day4 - 1) % 7); + /* We need the first week containing a Thursday, + * otherwise this day falls into the previous year + * for purposes of counting weeks + */ + if (dayn < (day4 - day0)) + { + day4 = date2j((tm->tm_year - 1), 1, 4); + /* day0 == offset to first day of week (Monday) */ + day0 = (j2day(day4 - 1) % 7); + } + *result = (((dayn - (day4 - day0)) / 7) + 1); + /* Sometimes the last few days in a year will fall into + * the first week of the next year, so check for this. + */ + if (*result >= 53) + { + day4 = date2j((tm->tm_year + 1), 1, 4); + /* day0 == offset to first day of week (Monday) */ + day0 = (j2day(day4 - 1) % 7); + if (dayn >= (day4 - day0)) + *result = (((dayn - (day4 - day0)) / 7) + 1); + } + } + break; + case DTK_YEAR: *result = tm->tm_year; break; @@ -1939,7 +1971,7 @@ timestamp_part(text *units, Timestamp *timestamp) *result = (tm->tm_year / 100); break; - case DTK_MILLENIUM: + case DTK_MILLENNIUM: *result = (tm->tm_year / 1000); break; @@ -2082,7 +2114,7 @@ interval_part(text *units, Interval *interval) *result = (tm->tm_year / 100); break; - case DTK_MILLENIUM: + case DTK_MILLENNIUM: *result = (tm->tm_year / 1000); break;