Обсуждение: BUG #1563: wrong week returnded by date_trunc('week', ...)

Поиск
Список
Период
Сортировка

BUG #1563: wrong week returnded by date_trunc('week', ...)

От
"Dirk Raetzel"
Дата:
The following bug has been logged online:

Bug reference:      1563
Logged by:          Dirk Raetzel
Email address:      d00273@spaetzle.de
PostgreSQL version: 8.0.1
Operating system:   i686-pc-mingw32, compiled by GCC gcc.exe (GCC) 3.4.2
(mingw-special)
Description:        wrong week returnded by date_trunc('week', ...)
Details:

date_trunc('week', ...) returns the wrong week for first days in January if
their calendar week belongs to the previous week.

Example:
select date_trunc('week', timestamp '2005-01-01');
gives: 2006-01-02 00:00:00 but 2004-12-27 00:00:00 would be right.

sample code:

create table weektest (
        date timestamp
);

copy weektest from STDIN;
'1999-01-01'
'2000-01-01'
'2001-01-01'
'2002-01-01'
'2003-01-01'
'2004-01-01'
'2005-01-01'
'2006-01-01'
'2007-01-01'
'2008-01-01'
'2009-01-01'
\.

        date         |       week_t        | week_p
---------------------+---------------------+--------
 1999-01-01 00:00:00 | 2000-01-03 00:00:00 |     53
 2000-01-01 00:00:00 | 2000-12-25 00:00:00 |     52
 2001-01-01 00:00:00 | 2001-01-01 00:00:00 |      1
 2002-01-01 00:00:00 | 2001-12-31 00:00:00 |      1
 2003-01-01 00:00:00 | 2002-12-30 00:00:00 |      1
 2004-01-01 00:00:00 | 2003-12-29 00:00:00 |      1
 2005-01-01 00:00:00 | 2006-01-02 00:00:00 |     53
 2006-01-01 00:00:00 | 2006-12-25 00:00:00 |     52
 2007-01-01 00:00:00 | 2007-01-01 00:00:00 |      1
 2008-01-01 00:00:00 | 2007-12-31 00:00:00 |      1
 2009-01-01 00:00:00 | 2008-12-29 00:00:00 |      1
(11 rows)

Re: BUG #1563: wrong week returnded by date_trunc('week',

От
Robert Creager
Дата:
When grilled further on (Fri, 25 Mar 2005 08:28:58 +0000 (GMT)),
"Dirk Raetzel" <d00273@spaetzle.de> confessed:

>
> The following bug has been logged online:
>
> Bug reference:      1563
> Logged by:          Dirk Raetzel
> Email address:      d00273@spaetzle.de
> PostgreSQL version: 8.0.1
> Operating system:   i686-pc-mingw32, compiled by GCC gcc.exe (GCC) 3.4.2
> (mingw-special)
> Description:        wrong week returnded by date_trunc('week', ...)
> Details:
> date_trunc('week', ...) returns the wrong week for first days in January if
> their calendar week belongs to the previous week.

I brought this up a couple of weeks ago in Hackers since I created this error
last year :-(  Never got feedback on whether the following function solved the
problem correctly or not.  If you would agree this works, then I'll see about
moving it into C.

CREATE OR REPLACE FUNCTION
date_trunc_week(timestamp without time zone)
RETURNS timestamp without time zone
    AS '
DECLARE
   reading_time ALIAS FOR $1;
   year timestamp;
   dow integer;
   temp interval;
   weeks text;
   adjust text;
BEGIN
   year := date_trunc( ''year''::text, reading_time );
   dow := date_part( ''dow'', year );
   IF dow >= 4 THEN
      adjust := 1 - dow || '' day'';
   ELSIF dow != 1 THEN
      adjust := dow - 6 || '' day'';
   ELSE
      adjust := ''0 day'';
   END IF;
   temp := reading_time - (year + adjust::interval);
   weeks := trunc(date_part( ''days'', temp ) / 7) || '' weeks'';
   RETURN year + adjust::interval + weeks::interval;
END;
' LANGUAGE plpgsql;


select date_trunc_week( '2004-01-01' ); -- 2003-12-29 00:00:00
select date_trunc_week( '2005-01-01' ); -- 2004-12-27 00:00:00
select date_trunc_week( '2005-06-01' ); -- 2005-05-30 00:00:00
select date_trunc_week( '2006-01-01' ); -- 2005-12-26 00:00:00
select date_trunc_week( '2007-01-01' ); -- 2007-01-01 00:00:00

--
 22:56:20 up 9 days,  2:46,  7 users,  load average: 4.72, 5.79, 4.76
Linux 2.6.5-02 #8 SMP Mon Jul 12 21:34:44 MDT 2004

Re: BUG #1563: wrong week returnded by date_trunc('week',

От
Tom Lane
Дата:
Robert Creager <Robert_Creager@LogicalChaos.org> writes:
> "Dirk Raetzel" <d00273@spaetzle.de> confessed:
>> date_trunc('week', ...) returns the wrong week for first days in January if
>> their calendar week belongs to the previous week.

> I brought this up a couple of weeks ago in Hackers since I created this error
> last year :-(

I don't recall seeing that ... anyway, the problem seems to be that
timestamp_trunc implements this as

        case DTK_WEEK:
            isoweek2date(date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday),
                         &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
            tm->tm_hour = 0;
            tm->tm_min = 0;
            tm->tm_sec = 0;
            fsec = 0;
            break;

which looks plausible on its face ... but given 2005-01-01, date2isoweek
returns 53 --- which represents the 53rd week of 2004, which is correct
--- and then isoweek2date thinks it is supposed to compute the 53rd week
of 2005, which is not what's wanted.

We need to change the function APIs so that date2isoweek passes back
some indication of which year it thought the week belongs to, and then
isoweek2date must use that instead of the original year number.

Each of these functions is used in several places, so the change is not
quite trivial, but still not a big deal.  Who wants to fix it?

            regards, tom lane

Re: BUG #1563: wrong week returnded by date_trunc('week',

От
Robert Creager
Дата:
When grilled further on (Sun, 27 Mar 2005 02:26:02 -0500),
Tom Lane <tgl@sss.pgh.pa.us> confessed:

>
> We need to change the function APIs so that date2isoweek passes back
> some indication of which year it thought the week belongs to, and then
> isoweek2date must use that instead of the original year number.
>
> Each of these functions is used in several places, so the change is not
> quite trivial, but still not a big deal.  Who wants to fix it?
>

I'll take a look at it next weekend (4/2 or 4/3) if it's still not done.

Cheers,
Rob

--
 20:43:32 up 14:07,  9 users,  load average: 3.15, 2.76, 2.00
Linux 2.6.5-02 #8 SMP Mon Jul 12 21:34:44 MDT 2004