diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 4fee01c6d8..f879664a9e 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.243 2005/03/30 04:52:49 neilc Exp $ +$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.244 2005/04/01 14:25:22 momjian Exp $ PostgreSQL documentation --> @@ -5472,6 +5472,12 @@ SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); week starts on Monday.) In other words, the first Thursday of a year is in week 1 of that year. (for <type>timestamp</type> values only) </para> + <para> + Because of this, it is possible for early January dates to be part of the + 52nd or 53rd week of the previous year. For example, <literal>2005-01-01</> + is part of the 53rd week of year 2004, and <literal>2006-01-01</> is part of + the 52nd week of year 2005. + </para> <screen> SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index e788c7b162..1f82b2fec9 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.117 2004/12/31 22:01:22 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.118 2005/04/01 14:25:23 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2754,12 +2754,23 @@ timestamp_trunc(PG_FUNCTION_ARGS) switch (val) { case DTK_WEEK: - isoweek2date(date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + { + int woy; + + woy = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday); + /* + * If it is week 52/53 and the month is January, + * then the week must belong to the previous year. + */ + if (woy >= 52 && tm->tm_mon == 1) + --tm->tm_year; + isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; fsec = 0; break; + } case DTK_MILLENNIUM: /* see comments in timestamptz_trunc */ if (tm->tm_year > 0) @@ -2874,13 +2885,24 @@ timestamptz_trunc(PG_FUNCTION_ARGS) switch (val) { case DTK_WEEK: - isoweek2date(date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + { + int woy; + + woy = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday); + /* + * If it is week 52/53 and the month is January, + * then the week must belong to the previous year. + */ + if (woy >= 52 && tm->tm_mon == 1) + --tm->tm_year; + isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; fsec = 0; redotz = true; break; + } /* one may consider DTK_THOUSAND and DTK_HUNDRED... */ case DTK_MILLENNIUM: @@ -3142,7 +3164,7 @@ date2isoweek(int year, int mon, int mday) * 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) + if (result >= 52) { day4 = date2j(year + 1, 1, 4); @@ -3198,7 +3220,7 @@ date2isoyear(int year, int mon, int mday) * 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) + if (result >= 52) { day4 = date2j(year + 1, 1, 4);