From 3e803f72732f591a7913f5be212012ea1193705c Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 19 Feb 2007 17:41:39 +0000
Subject: [PATCH] Add "isodow" option to EXTRACT() and date_part() where Sunday
 = 7.

---
 doc/src/sgml/func.sgml                     | 35 +++++++++++++++++-----
 src/backend/utils/adt/datetime.c           |  3 +-
 src/backend/utils/adt/timestamp.c          |  8 ++++-
 src/include/utils/datetime.h               |  3 +-
 src/interfaces/ecpg/pgtypeslib/dt.h        |  3 +-
 src/interfaces/ecpg/pgtypeslib/dt_common.c |  3 +-
 6 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 4a44e669b1b..ac7a0d16389 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.361 2007/02/16 07:46:54 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.362 2007/02/19 17:41:38 momjian Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -5732,8 +5732,8 @@ SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
       <term><literal>dow</literal></term>
       <listitem>
        <para>
-        The day of the week (0 - 6; Sunday is 0) (for
-        <type>timestamp</type> values only)
+        The day of the week as Sunday(<literal>0</>) to
+        Saturday(<literal>6</>)
        </para>
 
 <screen>
@@ -5741,7 +5741,7 @@ SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
 <lineannotation>Result: </lineannotation><computeroutput>5</computeroutput>
 </screen>
        <para>
-        Note that <function>extract</function>'s day of the week numbering is 
+        Note that <function>extract</function>'s day of the week numbering is
         different from that of the <function>to_char</function> function.
        </para>
 
@@ -5752,7 +5752,7 @@ SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
       <term><literal>doy</literal></term>
       <listitem>
        <para>
-        The day of the year (1 - 365/366) (for <type>timestamp</type> values only)
+        The day of the year (1 - 365/366)
        </para>
 
 <screen>
@@ -5805,6 +5805,26 @@ SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><literal>isodow</literal></term>
+      <listitem>
+       <para>
+        The day of the week as Monday(<literal>1</>) to
+        Sunday(<literal>7</>)
+       </para>
+
+<screen>
+SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
+<lineannotation>Result: </lineannotation><computeroutput>7</computeroutput>
+</screen>
+       <para>
+        This is identical to <literal>dow</> except for Sunday.  This
+        matches the <acronym>ISO</> 8601 day of the week numbering.
+       </para>
+
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><literal>isoyear</literal></term>
       <listitem>
@@ -5923,8 +5943,7 @@ SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
       <term><literal>quarter</literal></term>
       <listitem>
        <para>
-        The quarter of the year (1 - 4) that the day is in (for
-        <type>timestamp</type> values only)
+        The quarter of the year (1 - 4) that the day is in
        </para>
 
 <screen>
@@ -5989,7 +6008,7 @@ SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
         (<acronym>ISO</acronym> 8601), the first week of a year
         contains January 4 of that year.  (The <acronym>ISO</acronym>-8601
         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)
+        a year is in week 1 of that year.
        </para>
        <para>
         Because of this, it is possible for early January dates to be part of the 
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 18226b55082..6154c96b9c2 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.176 2007/02/16 03:39:45 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.177 2007/02/19 17:41:39 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -125,6 +125,7 @@ static const datetkn datetktbl[] = {
 	{"h", UNITS, DTK_HOUR},		/* "hour" */
 	{LATE, RESERV, DTK_LATE},	/* "infinity" reserved for "late time" */
 	{INVALID, RESERV, DTK_INVALID},		/* "invalid" reserved for bad time */
+	{"isodow", RESERV, DTK_ISODOW},		/* ISO day of week, Sunday == 7 */
 	{"isoyear", UNITS, DTK_ISOYEAR},	/* year in terms of the ISO week date */
 	{"j", UNITS, DTK_JULIAN},
 	{"jan", MONTH, 1},
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 7632e1b8961..a842c1b02cf 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.172 2007/02/16 03:39:45 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.173 2007/02/19 17:41:39 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4112,11 +4112,14 @@ timestamp_part(PG_FUNCTION_ARGS)
 					break;
 				}
 			case DTK_DOW:
+			case DTK_ISODOW:
 				if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
 					ereport(ERROR,
 							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 							 errmsg("timestamp out of range")));
 				result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
+				if (val == DTK_ISODOW && result == 0)
+					result = 7;
 				break;
 
 			case DTK_DOY:
@@ -4322,11 +4325,14 @@ timestamptz_part(PG_FUNCTION_ARGS)
 				break;
 
 			case DTK_DOW:
+			case DTK_ISODOW:
 				if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0)
 					ereport(ERROR,
 							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 							 errmsg("timestamp out of range")));
 				result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
+				if (val == DTK_ISODOW && result == 0)
+					result = 7;
 				break;
 
 			case DTK_DOY:
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index fc7b16fdb47..df6cf5e4f30 100644
--- a/src/include/utils/datetime.h
+++ b/src/include/utils/datetime.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.64 2007/02/16 03:39:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.65 2007/02/19 17:41:39 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -166,6 +166,7 @@
 #define DTK_TZ_HOUR		34
 #define DTK_TZ_MINUTE	35
 #define DTK_ISOYEAR		36
+#define DTK_ISODOW		37
 
 
 /*
diff --git a/src/interfaces/ecpg/pgtypeslib/dt.h b/src/interfaces/ecpg/pgtypeslib/dt.h
index d0bfc00bbdd..b94bd5a73b9 100644
--- a/src/interfaces/ecpg/pgtypeslib/dt.h
+++ b/src/interfaces/ecpg/pgtypeslib/dt.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt.h,v 1.35 2007/02/16 03:39:45 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt.h,v 1.36 2007/02/19 17:41:39 momjian Exp $ */
 
 #ifndef DT_H
 #define DT_H
@@ -158,6 +158,7 @@ typedef double fsec_t;
 #define DTK_TZ_HOUR		34
 #define DTK_TZ_MINUTE	35
 #define DTK_ISOYEAR		36
+#define DTK_ISODOW		37
 
 
 /*
diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c
index d6ccf3310d2..8fb0818add4 100644
--- a/src/interfaces/ecpg/pgtypeslib/dt_common.c
+++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.36 2006/09/26 07:56:56 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.37 2007/02/19 17:41:39 momjian Exp $ */
 
 #include "postgres_fe.h"
 
@@ -214,6 +214,7 @@ static datetkn datetktbl[] = {
 	{"irkst", DTZ, POS(36)},	/* Irkutsk Summer Time */
 	{"irkt", TZ, POS(32)},		/* Irkutsk Time */
 	{"irt", TZ, POS(14)},		/* Iran Time */
+	{"isodow", RESERV, DTK_ISODOW},	/* ISO day of week, Sunday == 7 */
 #if 0
 	isst
 #endif
-- 
GitLab