Thread: extract (dow/week from date)

extract (dow/week from date)

From
Clodoaldo Pinto
Date:
The extract (dow from date) function returns 0 for Sunday (nice).

My problem is that Sunday is the last day of the week according to
extract (week from date). Is it the expected behavior?

teste=# create table dates (date timestamp);
CREATE TABLE
teste=# insert into dates values ('2005-08-08');
INSERT 0 1
teste=# insert into dates values ('2005-08-09');
INSERT 0 1
teste=# insert into dates values ('2005-08-10');
INSERT 0 1
teste=# insert into dates values ('2005-08-11');
INSERT 0 1
teste=# insert into dates values ('2005-08-12');
INSERT 0 1
teste=# insert into dates values ('2005-08-13');
INSERT 0 1
teste=# insert into dates values ('2005-08-14');
INSERT 0 1
teste=# select date, extract (week from date) as week, extract (dow
from date) as dow
teste-# from dates
teste-# order by date;
        date         | week | dow
---------------------+------+-----
 2005-08-08 00:00:00 |   32 |   1
 2005-08-09 00:00:00 |   32 |   2
 2005-08-10 00:00:00 |   32 |   3
 2005-08-11 00:00:00 |   32 |   4
 2005-08-12 00:00:00 |   32 |   5
 2005-08-13 00:00:00 |   32 |   6
 2005-08-14 00:00:00 |   32 |   0
(7 rows)

In mysql the date functions work as I need it:
order by yearweek(day, 2) desc, dayofweek(day);

Regards,
Clodoaldo Pinto

Attachment

Re: extract (dow/week from date)

From
Bruce Momjian
Date:
Uh, you are ordering by 'date', not column 3, try ORDER BY 3.

---------------------------------------------------------------------------

Clodoaldo Pinto wrote:
> The extract (dow from date) function returns 0 for Sunday (nice).
>
> My problem is that Sunday is the last day of the week according to
> extract (week from date). Is it the expected behavior?
>
> teste=# create table dates (date timestamp);
> CREATE TABLE
> teste=# insert into dates values ('2005-08-08');
> INSERT 0 1
> teste=# insert into dates values ('2005-08-09');
> INSERT 0 1
> teste=# insert into dates values ('2005-08-10');
> INSERT 0 1
> teste=# insert into dates values ('2005-08-11');
> INSERT 0 1
> teste=# insert into dates values ('2005-08-12');
> INSERT 0 1
> teste=# insert into dates values ('2005-08-13');
> INSERT 0 1
> teste=# insert into dates values ('2005-08-14');
> INSERT 0 1
> teste=# select date, extract (week from date) as week, extract (dow
> from date) as dow
> teste-# from dates
> teste-# order by date;
>         date         | week | dow
> ---------------------+------+-----
>  2005-08-08 00:00:00 |   32 |   1
>  2005-08-09 00:00:00 |   32 |   2
>  2005-08-10 00:00:00 |   32 |   3
>  2005-08-11 00:00:00 |   32 |   4
>  2005-08-12 00:00:00 |   32 |   5
>  2005-08-13 00:00:00 |   32 |   6
>  2005-08-14 00:00:00 |   32 |   0
> (7 rows)
>
> In mysql the date functions work as I need it:
> order by yearweek(day, 2) desc, dayofweek(day);
>
> Regards,
> Clodoaldo Pinto

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: Don't 'kill -9' the postmaster

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: extract (dow/week from date)

From
Clodoaldo Pinto
Date:
2005/8/20, Bruce Momjian <pgman@candle.pha.pa.us>:
>
> Uh, you are ordering by 'date', not column 3, try ORDER BY 3.
>

I'm ordering by date just to show that sunday, the 0th day of the
week, is the last day of a given week, which is not what I need.

I'm migrating a site from mysql to postgres and the logic of the table
at the page works for Sunday as the first day of the week. I will make
the pg query produce the same behavior as the mysql query but the pg
function behavior seems confusing.

Note how are the dates sorted at the table:
http://fahstats.com/tp.php?t=13802

Regards, Clodoaldo Pinto

2005/8/20, Bruce Momjian <pgman@candle.pha.pa.us>:
>
> Uh, you are ordering by 'date', not column 3, try ORDER BY 3.
>
> ---------------------------------------------------------------------------
>
> Clodoaldo Pinto wrote:
> > The extract (dow from date) function returns 0 for Sunday (nice).
> >
> > My problem is that Sunday is the last day of the week according to
> > extract (week from date). Is it the expected behavior?
> >
> > teste=# create table dates (date timestamp);
> > CREATE TABLE
> > teste=# insert into dates values ('2005-08-08');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-09');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-10');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-11');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-12');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-13');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-14');
> > INSERT 0 1
> > teste=# select date, extract (week from date) as week, extract (dow
> > from date) as dow
> > teste-# from dates
> > teste-# order by date;
> >         date         | week | dow
> > ---------------------+------+-----
> >  2005-08-08 00:00:00 |   32 |   1
> >  2005-08-09 00:00:00 |   32 |   2
> >  2005-08-10 00:00:00 |   32 |   3
> >  2005-08-11 00:00:00 |   32 |   4
> >  2005-08-12 00:00:00 |   32 |   5
> >  2005-08-13 00:00:00 |   32 |   6
> >  2005-08-14 00:00:00 |   32 |   0
> > (7 rows)
> >
> > In mysql the date functions work as I need it:
> > order by yearweek(day, 2) desc, dayofweek(day);
> >
> > Regards,
> > Clodoaldo Pinto
>
> [ Attachment, skipping... ]
>
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 2: Don't 'kill -9' the postmaster
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>

Re: extract (dow/week from date)

From
Alvaro Herrera
Date:
On Sat, Aug 20, 2005 at 09:03:32PM -0400, Bruce Momjian wrote:
>
> Uh, you are ordering by 'date', not column 3, try ORDER BY 3.

I think the point is that extract(week) is inconsistent with
extract(dow) with respect to what week a sunday is on.

> Clodoaldo Pinto wrote:
> > The extract (dow from date) function returns 0 for Sunday (nice).
> >
> > My problem is that Sunday is the last day of the week according to
> > extract (week from date). Is it the expected behavior?
> >
> > teste=# create table dates (date timestamp);
> > CREATE TABLE
> > teste=# insert into dates values ('2005-08-08');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-09');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-10');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-11');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-12');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-13');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-14');
> > INSERT 0 1
> > teste=# select date, extract (week from date) as week, extract (dow
> > from date) as dow
> > teste-# from dates
> > teste-# order by date;
> >         date         | week | dow
> > ---------------------+------+-----
> >  2005-08-08 00:00:00 |   32 |   1
> >  2005-08-09 00:00:00 |   32 |   2
> >  2005-08-10 00:00:00 |   32 |   3
> >  2005-08-11 00:00:00 |   32 |   4
> >  2005-08-12 00:00:00 |   32 |   5
> >  2005-08-13 00:00:00 |   32 |   6
> >  2005-08-14 00:00:00 |   32 |   0
> > (7 rows)
> >
> > In mysql the date functions work as I need it:
> > order by yearweek(day, 2) desc, dayofweek(day);


--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
<inflex> really, I see PHP as like a strange amalgamation of C, Perl, Shell
<crab> inflex: you know that "amalgam" means "mixture with mercury",
       more or less, right?
<crab> i.e., "deadly poison"

Re: extract (dow/week from date)

From
Stephan Szabo
Date:
On Sat, 20 Aug 2005, Bruce Momjian wrote:

> Uh, you are ordering by 'date', not column 3, try ORDER BY 3.

That's not really the issue.  The issue is that our definition of date of
week and week of year are somewhat inconsistent with each other. We appear
to be doing week of year per ISO-8601, but what the descriptions I've seen
of that use days 1-7 for Monday-Sunday, whereas we're apparently giving
0-6 for Sunday-Saturday. This means that sorting by (week of year, day of
week) will sort Sundays oddly (since it would for example below sort the
14th before the 8th).



> ---------------------------------------------------------------------------
>
> Clodoaldo Pinto wrote:
> > The extract (dow from date) function returns 0 for Sunday (nice).
> >
> > My problem is that Sunday is the last day of the week according to
> > extract (week from date). Is it the expected behavior?
> >
> > teste=# create table dates (date timestamp);
> > CREATE TABLE
> > teste=# insert into dates values ('2005-08-08');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-09');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-10');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-11');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-12');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-13');
> > INSERT 0 1
> > teste=# insert into dates values ('2005-08-14');
> > INSERT 0 1
> > teste=# select date, extract (week from date) as week, extract (dow
> > from date) as dow
> > teste-# from dates
> > teste-# order by date;
> >         date         | week | dow
> > ---------------------+------+-----
> >  2005-08-08 00:00:00 |   32 |   1
> >  2005-08-09 00:00:00 |   32 |   2
> >  2005-08-10 00:00:00 |   32 |   3
> >  2005-08-11 00:00:00 |   32 |   4
> >  2005-08-12 00:00:00 |   32 |   5
> >  2005-08-13 00:00:00 |   32 |   6
> >  2005-08-14 00:00:00 |   32 |   0
> > (7 rows)
> >
> > In mysql the date functions work as I need it:
> > order by yearweek(day, 2) desc, dayofweek(day);

Re: extract (dow/week from date)

From
Tom Lane
Date:
Clodoaldo Pinto <clodoaldo.pinto@gmail.com> writes:
> I'm ordering by date just to show that sunday, the 0th day of the
> week, is the last day of a given week, which is not what I need.

extract(week) follows the ISO definition of week, which is pretty
strange anyway, but in particular it says that weeks start on Monday.
extract(dow) follows a different convention.  There's not a lot we
can do about this --- we're certainly not going to change extract(week),
and I can't see changing extract(dow) either.

If you feel that weeks start on Sunday you should ignore extract(week).

            regards, tom lane

Re: extract (dow/week from date)

From
Stephan Szabo
Date:
On Sat, 20 Aug 2005, Tom Lane wrote:

> Clodoaldo Pinto <clodoaldo.pinto@gmail.com> writes:
> > I'm ordering by date just to show that sunday, the 0th day of the
> > week, is the last day of a given week, which is not what I need.
>
> extract(week) follows the ISO definition of week, which is pretty
> strange anyway, but in particular it says that weeks start on Monday.
> extract(dow) follows a different convention.  There's not a lot we
> can do about this --- we're certainly not going to change extract(week),
> and I can't see changing extract(dow) either.

Instead of change the existing ones, couldn't we add a new extract format
for "iso day of week" that returns 1-7 for monday-sunday that would be
consistent with the week definition?

Re: extract (dow/week from date)

From
Alvaro Herrera
Date:
On Sat, Aug 20, 2005 at 08:49:27PM -0700, Stephan Szabo wrote:
> On Sat, 20 Aug 2005, Tom Lane wrote:
>
> > Clodoaldo Pinto <clodoaldo.pinto@gmail.com> writes:
> > > I'm ordering by date just to show that sunday, the 0th day of the
> > > week, is the last day of a given week, which is not what I need.
> >
> > extract(week) follows the ISO definition of week, which is pretty
> > strange anyway, but in particular it says that weeks start on Monday.
> > extract(dow) follows a different convention.  There's not a lot we
> > can do about this --- we're certainly not going to change extract(week),
> > and I can't see changing extract(dow) either.
>
> Instead of change the existing ones, couldn't we add a new extract format
> for "iso day of week" that returns 1-7 for monday-sunday that would be
> consistent with the week definition?

AFAIR the to_char() function uses the 1-7 convention.

--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
"I personally became interested in Linux while I was dating an English major
who wouldn't know an operating system if it walked up and bit him."
(Val Henson)

Re: extract (dow/week from date)

From
Clodoaldo Pinto
Date:
2005/8/21, Stephan Szabo <sszabo@megazone.bigpanda.com>:
> On Sat, 20 Aug 2005, Tom Lane wrote:
>
> > Clodoaldo Pinto <clodoaldo.pinto@gmail.com> writes:
> > > I'm ordering by date just to show that sunday, the 0th day of the
> > > week, is the last day of a given week, which is not what I need.
> >
> > extract(week) follows the ISO definition of week, which is pretty
> > strange anyway, but in particular it says that weeks start on Monday.
> > extract(dow) follows a different convention.  There's not a lot we
> > can do about this --- we're certainly not going to change extract(week),
> > and I can't see changing extract(dow) either.
>
> Instead of change the existing ones, couldn't we add a new extract format
> for "iso day of week" that returns 1-7 for monday-sunday that would be
> consistent with the week definition?
>
It would work for me. The problem is not if is sunday or monday the
first day of the week, but to make all days of the week from extract
(dow) (or a new extract (isodow)) fit into the same week from extract
(week). It does not happen now:

drop table dates;
create table dates (date timestamp);
insert into dates values ('2004-12-31');
insert into dates values ('2005-01-01');
insert into dates values ('2005-01-02');
insert into dates values ('2005-01-03');
insert into dates values ('2005-01-04');
insert into dates values ('2005-01-05');
insert into dates values ('2005-01-06');
insert into dates values ('2005-01-07');
insert into dates values ('2005-01-08');
insert into dates values ('2005-01-09');
select date,
  to_char (date, 'Dy') as cday,
  extract (week from date) as eweek,
  extract (dow from date) as edow,
  to_char (date, 'WW')::int as cweek,
  to_char (date, 'D')::int as cdow
from dates
order by date;

        date         | cday | eweek | edow | cweek | cdow
---------------------+------+-------+------+-------+------
 2004-12-31 00:00:00 | Fri  |    53 |    5 |    53 |    6
 2005-01-01 00:00:00 | Sat  |    53 |    6 |     1 |    7
 2005-01-02 00:00:00 | Sun  |    53 |    0 |     1 |    1
 2005-01-03 00:00:00 | Mon  |     1 |    1 |     1 |    2
 2005-01-04 00:00:00 | Tue  |     1 |    2 |     1 |    3
 2005-01-05 00:00:00 | Wed  |     1 |    3 |     1 |    4
 2005-01-06 00:00:00 | Thu  |     1 |    4 |     1 |    5
 2005-01-07 00:00:00 | Fri  |     1 |    5 |     1 |    6
 2005-01-08 00:00:00 | Sat  |     1 |    6 |     2 |    7
 2005-01-09 00:00:00 | Sun  |     1 |    0 |     2 |    1
(10 rows)

There is the same mismatch in to_char ('WW') related to to_char ('D')

Of course it would be even better if we could pass parameters to the
functions changing its behavior such as sunday/monday as the first day
or 0-1 as the first day.

Regards, Clodoaldo Pinto

Re: extract (dow/week from date)

From
Stephan Szabo
Date:
On Sun, 21 Aug 2005, Clodoaldo Pinto wrote:

> 2005/8/21, Stephan Szabo <sszabo@megazone.bigpanda.com>:
> > On Sat, 20 Aug 2005, Tom Lane wrote:
> >
> > > Clodoaldo Pinto <clodoaldo.pinto@gmail.com> writes:
> > > > I'm ordering by date just to show that sunday, the 0th day of the
> > > > week, is the last day of a given week, which is not what I need.
> > >
> > > extract(week) follows the ISO definition of week, which is pretty
> > > strange anyway, but in particular it says that weeks start on Monday.
> > > extract(dow) follows a different convention.  There's not a lot we
> > > can do about this --- we're certainly not going to change extract(week),
> > > and I can't see changing extract(dow) either.
> >
> > Instead of change the existing ones, couldn't we add a new extract format
> > for "iso day of week" that returns 1-7 for monday-sunday that would be
> > consistent with the week definition?
> >
> It would work for me. The problem is not if is sunday or monday the
> first day of the week, but to make all days of the week from extract
> (dow) (or a new extract (isodow)) fit into the same week from extract
> (week).

I think something like:
(CASE WHEN extract(dow from date) = 0 THEN 7 else extract(dow from date))
would give consistent results right now, but that's terribly ugly
(although could be hidden in a function).  Of course, even if it were to
be added, it'd probably not make it until 8.2, so you'd probably need a
workaround in the meantime anyway.

> There is the same mismatch in to_char ('WW') related to to_char ('D')

I'd think you'd want to be comparing IW and D, but it'd presumably still
be broken since sunday is 1 rather than monday.  Since that function is
supposed to emulate Oracle in alot of places IIRC, so it'd be interesting
to see what Oracle does on those dates.

> Of course it would be even better if we could pass parameters to the
> functions changing its behavior such as sunday/monday as the first day
> or 0-1 as the first day.

I don't personally see that as better, really.

Re: extract (dow/week from date)

From
Tom Lane
Date:
Stephan Szabo <sszabo@megazone.bigpanda.com> writes:
> I think something like:
> (CASE WHEN extract(dow from date) = 0 THEN 7 else extract(dow from date))

It's really not that hard:

    (extract(dow from date) + 6) % 7

You can rotate to any week-start day you like by substituting different
things for "6".

            regards, tom lane

Re: extract (dow/week from date)

From
Stephan Szabo
Date:
On Sun, 21 Aug 2005, Tom Lane wrote:

> Stephan Szabo <sszabo@megazone.bigpanda.com> writes:
> > I think something like:
> > (CASE WHEN extract(dow from date) = 0 THEN 7 else extract(dow from date))
>
> It's really not that hard:
>
>     (extract(dow from date) + 6) % 7
>
> You can rotate to any week-start day you like by substituting different
> things for "6".

Yeah, mod is probably better and more general than case. It's still fairly
ugly to require a non-trivial expression to get something that's
consistent with the way that extract(week from date) works. ;)

For anyone who is considering using this, to get an actual iso day of
week, I think you'll need to add 1 at the end since that appears to use a
1-7 range. If you're just using it for sorting or the like, you can get
away with not bothering.

Re: extract (dow/week from date)

From
"Jim C. Nasby"
Date:
On Sun, Aug 21, 2005 at 08:00:45AM -0300, Clodoaldo Pinto wrote:
> Of course it would be even better if we could pass parameters to the
> functions changing its behavior such as sunday/monday as the first day
> or 0-1 as the first day.

FWIW, it seems most things that support changing first day of the week
to be something other than <default> do it through a global setting.
ISTM that would be much less error prone than having to make sure you
used it in all your function calls (not to mention a lot less typing...)
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software        http://pervasive.com        512-569-9461

Re: extract (dow/week from date)

From
Tom Lane
Date:
Stephan Szabo <sszabo@megazone.bigpanda.com> writes:
> Yeah, mod is probably better and more general than case. It's still fairly
> ugly to require a non-trivial expression to get something that's
> consistent with the way that extract(week from date) works. ;)

> For anyone who is considering using this, to get an actual iso day of
> week, I think you'll need to add 1 at the end since that appears to use a
> 1-7 range. If you're just using it for sorting or the like, you can get
> away with not bothering.

Yeah.  If we were to invent an extract(isodow) option, I'd be inclined
to make it return 1-7 Mon-Sun.  So it'd actually produce the same value
as extract(dow), except on Sundays.

            regards, tom lane

Re: extract (dow/week from date)

From
Clodoaldo Pinto
Date:
2005/8/21, Tom Lane <tgl@sss.pgh.pa.us>:
> Stephan Szabo <sszabo@megazone.bigpanda.com> writes:
> > I think something like:
> > (CASE WHEN extract(dow from date) = 0 THEN 7 else extract(dow from date))
>
> It's really not that hard:
>
>         (extract(dow from date) + 6) % 7
>
> You can rotate to any week-start day you like by substituting different
> things for "6".
>
>                         regards, tom lane
>
Not obvious as extract (isodow) but good enough for me. Thanks.

But then i also need to order by year-week the same way mysql's
yearweek (date, 3) so i did:

drop table dates;
create table dates (date timestamp);
insert into dates values ('1990-01-01');
insert into dates values ('1990-12-31');
insert into dates values ('1991-01-01');
insert into dates values ('1991-12-31');
insert into dates values ('1992-01-01');
insert into dates values ('1992-12-31');
insert into dates values ('1993-01-01');
insert into dates values ('1993-12-31');
insert into dates values ('1994-01-01');
insert into dates values ('1994-12-31');
insert into dates values ('1995-01-01');
insert into dates values ('1995-12-31');
insert into dates values ('1996-01-01');
insert into dates values ('1996-12-31');
insert into dates values ('1997-01-01');
insert into dates values ('1997-12-31');
insert into dates values ('1998-01-01');
insert into dates values ('1998-12-31');
insert into dates values ('1999-01-01');
insert into dates values ('1999-12-31');
insert into dates values ('2000-01-01');
insert into dates values ('2000-12-31');
insert into dates values ('2001-01-01');
insert into dates values ('2001-12-31');
insert into dates values ('2002-01-01');
insert into dates values ('2002-12-31');
insert into dates values ('2003-01-01');
insert into dates values ('2003-12-31');
insert into dates values ('2004-01-01');
insert into dates values ('2004-12-31');
insert into dates values ('2005-01-01');
insert into dates values ('2005-01-02');
insert into dates values ('2005-01-03');
insert into dates values ('2005-01-04');
insert into dates values ('2005-01-05');
insert into dates values ('2005-01-06');
insert into dates values ('2005-01-07');
insert into dates values ('2005-01-08');
insert into dates values ('2005-01-09');
select date,
  to_char (date, 'Dy') as cday,
  extract (year from date - cast (((extract (dow from date) +6)::int %
7 -3)::text || ' day' as interval)) as yearweek,
  extract (week from date) as eweek,
  (extract (dow from date) +6)::int % 7 as edow
from dates
order by date;
        date         | cday | yearweek | eweek | edow
---------------------+------+----------+-------+------
 1990-01-01 00:00:00 | Mon  |     1990 |     1 |    0
 1990-12-31 00:00:00 | Mon  |     1991 |     1 |    0
 1991-01-01 00:00:00 | Tue  |     1991 |     1 |    1
 1991-12-31 00:00:00 | Tue  |     1992 |     1 |    1
 1992-01-01 00:00:00 | Wed  |     1992 |     1 |    2
 1992-12-31 00:00:00 | Thu  |     1992 |    53 |    3
 1993-01-01 00:00:00 | Fri  |     1992 |    53 |    4
 1993-12-31 00:00:00 | Fri  |     1993 |    52 |    4
 1994-01-01 00:00:00 | Sat  |     1993 |    52 |    5
 1994-12-31 00:00:00 | Sat  |     1994 |    52 |    5
 1995-01-01 00:00:00 | Sun  |     1994 |    52 |    6
 1995-12-31 00:00:00 | Sun  |     1995 |    52 |    6
 1996-01-01 00:00:00 | Mon  |     1996 |     1 |    0
 1996-12-31 00:00:00 | Tue  |     1997 |     1 |    1
 1997-01-01 00:00:00 | Wed  |     1997 |     1 |    2
 1997-12-31 00:00:00 | Wed  |     1998 |     1 |    2
 1998-01-01 00:00:00 | Thu  |     1998 |     1 |    3
 1998-12-31 00:00:00 | Thu  |     1998 |    53 |    3
 1999-01-01 00:00:00 | Fri  |     1998 |    53 |    4
 1999-12-31 00:00:00 | Fri  |     1999 |    52 |    4
 2000-01-01 00:00:00 | Sat  |     1999 |    52 |    5
 2000-12-31 00:00:00 | Sun  |     2000 |    52 |    6
 2001-01-01 00:00:00 | Mon  |     2001 |     1 |    0
 2001-12-31 00:00:00 | Mon  |     2002 |     1 |    0
 2002-01-01 00:00:00 | Tue  |     2002 |     1 |    1
 2002-12-31 00:00:00 | Tue  |     2003 |     1 |    1
 2003-01-01 00:00:00 | Wed  |     2003 |     1 |    2
 2003-12-31 00:00:00 | Wed  |     2004 |     1 |    2
 2004-01-01 00:00:00 | Thu  |     2004 |     1 |    3
 2004-12-31 00:00:00 | Fri  |     2004 |    53 |    4
 2005-01-01 00:00:00 | Sat  |     2004 |    53 |    5
 2005-01-02 00:00:00 | Sun  |     2004 |    53 |    6
 2005-01-03 00:00:00 | Mon  |     2005 |     1 |    0
 2005-01-04 00:00:00 | Tue  |     2005 |     1 |    1
 2005-01-05 00:00:00 | Wed  |     2005 |     1 |    2
 2005-01-06 00:00:00 | Thu  |     2005 |     1 |    3
 2005-01-07 00:00:00 | Fri  |     2005 |     1 |    4
 2005-01-08 00:00:00 | Sat  |     2005 |     1 |    5
 2005-01-09 00:00:00 | Sun  |     2005 |     1 |    6
(39 rows)

I am not sure it is bullet proof.

If no one comes up with something simpler, it looks like extract
(yearweek) would be welcome.

Regards, Clodoaldo Pinto

Re: extract (dow/week from date)

From
Clodoaldo Pinto
Date:
2005/8/21, Jim C. Nasby <jnasby@pervasive.com>:
> On Sun, Aug 21, 2005 at 08:00:45AM -0300, Clodoaldo Pinto wrote:
> > Of course it would be even better if we could pass parameters to the
> > functions changing its behavior such as sunday/monday as the first day
> > or 0-1 as the first day.
>
> FWIW, it seems most things that support changing first day of the week
> to be something other than <default> do it through a global setting.
> ISTM that would be much less error prone than having to make sure you
> used it in all your function calls (not to mention a lot less typing...)
> --
> Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
> Pervasive Software        http://pervasive.com        512-569-9461
>

Yes, I think you are correct.

Regards, Clodoaldo Pinto

Re: extract (dow/week from date)

From
Clodoaldo Pinto
Date:
There were two hints by readers about this yearweek issue at the 7.4.8 manual:
http://www.postgresql.org/docs/7.4/interactive/functions-datetime.html

The first by Daniel Grace <graced AT monroe.wednet.edu> 21 May 2004 0:39:19

CREATE OR REPLACE FUNCTION yearweek(TIMESTAMP WITH TIME ZONE)
RETURNS INT LANGUAGE plpgsql IMMUTABLE STRICT
AS '
DECLARE
t TIMESTAMP;
BEGIN
t := $1::date - EXTRACT(dow FROM $1::date)::int;
RETURN EXTRACT(year FROM t)*100 + EXTRACT(week FROM t);
END;';

And the second by Wolfgang Diestelkamp <wolfgang AT dndata.de>
09 Mar 2005 15:44:05

CREATE OR REPLACE FUNCTION yearweek(TIMESTAMP)
RETURNS INT LANGUAGE plpgsql IMMUTABLE STRICT
AS '
DECLARE
t TIMESTAMP;
d INTEGER;
BEGIN
d := EXTRACT(dow FROM $1::date)::int;
t := $1::date -
CASE
WHEN d = 0 THEN 6
ELSE d - 1
END;
RETURN EXTRACT(year FROM t)*100 + EXTRACT(week FROM t);
END;';

While this second attempt improved on the iso day of the week it was
broken about the year.

Here is the comparison of my yearweek () function and the previous
two. The isodow () uses the construct suggested by Tom Lane.

create or replace function isodow (timestamp with time zone)
returns int language plpgsql immutable strict
as '
declare
begin
return (extract (dow from $1) +6)::int % 7;
end;';

create or replace function yearweek (timestamp with time zone)
returns int language plpgsql immutable strict
as '
declare
date timestamp with time zone = $1;
fyear integer;
begin
fyear :=  extract (year from date - ((isodow (date) -3)::text || \'
day\')::interval);
return fyear * 100 + extract (week from date);
end;';

drop table dates;
create table dates (date timestamp);
insert into dates values ('1990-01-01');
insert into dates values ('1990-12-31');
insert into dates values ('1991-01-01');
insert into dates values ('1991-12-31');
insert into dates values ('1992-01-01');
insert into dates values ('1992-12-31');
insert into dates values ('1993-01-01');
insert into dates values ('1993-12-31');
insert into dates values ('1994-01-01');
insert into dates values ('1994-12-31');
insert into dates values ('1995-01-01');
insert into dates values ('1995-12-31');
insert into dates values ('1996-01-01');
insert into dates values ('1996-12-31');
insert into dates values ('1997-01-01');
insert into dates values ('1997-12-31');
insert into dates values ('1998-01-01');
insert into dates values ('1998-12-31');
insert into dates values ('1999-01-01');
insert into dates values ('1999-12-31');
insert into dates values ('2000-01-01');
insert into dates values ('2000-12-31');
insert into dates values ('2001-01-01');
insert into dates values ('2001-12-31');
insert into dates values ('2002-01-01');
insert into dates values ('2002-12-31');
insert into dates values ('2003-01-01');
insert into dates values ('2003-12-31');
insert into dates values ('2004-01-01');
insert into dates values ('2004-12-31');
insert into dates values ('2005-01-01');
insert into dates values ('2005-01-02');
insert into dates values ('2005-01-03');
insert into dates values ('2005-01-04');
insert into dates values ('2005-01-05');
insert into dates values ('2005-01-06');
insert into dates values ('2005-01-07');
insert into dates values ('2005-01-08');
insert into dates values ('2005-01-09');
select date,
  to_char (date, 'Dy') as cday,
  isodow (date) as isod,
  yearweek (date) as yw_Clo,
  yearweek_Daniel (date) as yw_Dan,
  yearweek_Wolfgang (date) as yw_Wol
from dates
where yearweek (date) <> yearweek_Wolfgang (date)
order by date;

        date         | cday | isod | yw_clo | yw_dan | yw_wol
---------------------+------+------+--------+--------+--------
 1990-12-31 00:00:00 | Mon  |    0 | 199101 | 199052 | 199001
 1991-01-01 00:00:00 | Tue  |    1 | 199101 | 199052 | 199001
 1991-12-31 00:00:00 | Tue  |    1 | 199201 | 199152 | 199101
 1992-01-01 00:00:00 | Wed  |    2 | 199201 | 199152 | 199101
 1996-12-31 00:00:00 | Tue  |    1 | 199701 | 199652 | 199601
 1997-01-01 00:00:00 | Wed  |    2 | 199701 | 199652 | 199601
 1997-12-31 00:00:00 | Wed  |    2 | 199801 | 199752 | 199701
 1998-01-01 00:00:00 | Thu  |    3 | 199801 | 199752 | 199701
 2001-12-31 00:00:00 | Mon  |    0 | 200201 | 200152 | 200101
 2002-01-01 00:00:00 | Tue  |    1 | 200201 | 200152 | 200101
 2002-12-31 00:00:00 | Tue  |    1 | 200301 | 200252 | 200201
 2003-01-01 00:00:00 | Wed  |    2 | 200301 | 200252 | 200201
 2003-12-31 00:00:00 | Wed  |    2 | 200401 | 200352 | 200301
 2004-01-01 00:00:00 | Thu  |    3 | 200401 | 200352 | 200301
(14 rows)

Regards, Clodoaldo Pinto