Add two new format fields for use with to_char(), to_date() and
authorBruce Momjian <bruce@momjian.us>
Fri, 16 Feb 2007 03:39:46 +0000 (03:39 +0000)
committerBruce Momjian <bruce@momjian.us>
Fri, 16 Feb 2007 03:39:46 +0000 (03:39 +0000)
to_timestamp():
    - ID for day-of-week
    - IDDD for day-of-year

This makes it possible to convert ISO week dates to and from text
fully represented in either week ('IYYY-IW-ID') or day-of-year
('IYYY-IDDD') format.

I have also added an 'isoyear' field for use with extract / date_part.

Brendan Jurd

12 files changed:
doc/src/sgml/func.sgml
src/backend/utils/adt/date.c
src/backend/utils/adt/datetime.c
src/backend/utils/adt/formatting.c
src/backend/utils/adt/timestamp.c
src/include/utils/datetime.h
src/include/utils/timestamp.h
src/interfaces/ecpg/pgtypeslib/dt.h
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out
src/test/regress/sql/timestamp.sql
src/test/regress/sql/timestamptz.sql

index ae9e9ec105896475b418007ec840073efe383ef3..76b150a9d226a0aade8b9526c99744239553e9e6 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.358 2007/02/14 18:46:08 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.359 2007/02/16 03:39:44 momjian Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -4539,7 +4539,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
        </row>
        <row>
         <entry><literal>I</literal></entry>
-        <entry>last digits of ISO year</entry>
+        <entry>last digit of ISO year</entry>
        </row>
        <row>
         <entry><literal>BC</literal> or <literal>B.C.</literal> or
@@ -4607,6 +4607,10 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
         <entry><literal>DDD</literal></entry>
         <entry>day of year (001-366)</entry>
        </row>
+       <row>
+        <entry><literal>IDDD</literal></entry>
+        <entry>ISO day of year (001-371; day 1 of the year is Monday of the first ISO week.)</entry>
+       </row>
        <row>
         <entry><literal>DD</literal></entry>
         <entry>day of month (01-31)</entry>
@@ -4615,6 +4619,10 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
         <entry><literal>D</literal></entry>
         <entry>day of week (1-7; Sunday is 1)</entry>
        </row>
+       <row>
+        <entry><literal>ID</literal></entry>
+        <entry>ISO day of week (1-7; Monday is 1)</entry>
+       </row>
        <row>
         <entry><literal>W</literal></entry>
         <entry>week of month (1-5) (The first week starts on the first day of the month.)</entry>
@@ -4625,7 +4633,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
        </row>
        <row>
         <entry><literal>IW</literal></entry>
-        <entry>ISO week number of year (The first Thursday of the new year is in week 1.)</entry>
+        <entry>ISO week number of year (1 - 53; the first Thursday of the new year is in week 1.)</entry>
        </row>
        <row>
         <entry><literal>CC</literal></entry>
@@ -4791,6 +4799,27 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
       </para>
      </listitem>
 
+     <listitem>
+      <para>
+       An ISO week date (as distinct from a Gregorian date) can be specified to <function>to_timestamp</function> and <function>to_date</function> in one of two ways:
+       <itemizedlist>
+        <listitem>
+        <para>
+         Year, week and weekday, for example <literal>to_date('2006-42-4', 'IYYY-IW-ID')</literal> returns the date <literal>2006-10-19</literal>.  If you omit the weekday it is assumed to be 1 (Monday).
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         Year and day of year, for example <literal>to_date('2006-291', 'IYYY-IDDD')</literal> also returns <literal>2006-10-19</literal>.
+        </para>
+       </listitem>
+       </itemizedlist>
+      </para>
+      <para>
+       Attempting to construct a date using a mixture of ISO week and Gregorian date fields is nonsensical, and could yield unexpected results.  In the context of an ISO year, the concept of a 'month' or 'day of month' has no meaning.  In the context of a Gregorian year, the ISO week has no meaning.  Users should take care to keep Gregorian and ISO date specifications separate.
+      </para>
+     </listitem>
+
      <listitem>
       <para>
        Millisecond (<literal>MS</literal>) and microsecond (<literal>US</literal>)
@@ -5776,6 +5805,29 @@ SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><literal>isoyear</literal></term>
+      <listitem>
+       <para>
+        The <acronym>ISO</acronym> 8601 year that the date falls in (not applicable to intervals).
+       </para>
+
+<screen>
+SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01');
+<lineannotation>Result: </lineannotation><computeroutput>2005</computeroutput>
+SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02');
+<lineannotation>Result: </lineannotation><computeroutput>2006</computeroutput>
+</screen>
+
+       <para>
+        Each <acronym>ISO</acronym> year begins with the Monday of the week containing the 4th of January, so in early January or late December the <acronym>ISO</acronym> year may be different from the Gregorian year.  See the <literal>week</literal> field for more information.
+       </para>
+       <para>
+        This field is not available in PostgreSQL releases prior to 8.3.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><literal>microseconds</literal></term>
       <listitem>
index 2360419bb77718ba2383c748b41ac3128606ed97..c3a6415634bf7e68f17619cb70755bfeade2ca98 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.127 2007/01/05 22:19:40 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.128 2007/02/16 03:39:44 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1748,6 +1748,7 @@ time_part(PG_FUNCTION_ARGS)
                        case DTK_DECADE:
                        case DTK_CENTURY:
                        case DTK_MILLENNIUM:
+                       case DTK_ISOYEAR:
                        default:
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
index 10fdf66ac87730e4d9596d6f37f1d4168cf6b024..18226b55082744481ca179c5fb65166a7047bc6b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.175 2007/01/05 22:19:40 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.176 2007/02/16 03:39:45 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 */
+       {"isoyear", UNITS, DTK_ISOYEAR},        /* year in terms of the ISO week date */
        {"j", UNITS, DTK_JULIAN},
        {"jan", MONTH, 1},
        {"january", MONTH, 1},
index 80de2f20e4c1770b5bdf4f83e98b060567ab9015..eff890c59b38c470869ead7ed160d5fe1a62e87f 100644 (file)
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.124 2007/02/14 05:10:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.125 2007/02/16 03:39:45 momjian Exp $
  *
  *
  *      Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
@@ -379,6 +379,7 @@ typedef struct
                                ddd,
                                mm,
                                ms,
+                               iyear,
                                year,
                                bc,
                                iw,
@@ -528,7 +529,7 @@ static KeySuffix DCH_suff[] = {
  * position or -1 if char is not used in the KeyWord. Search example for
  * string "MM":
  *     1)      see in index to index['M' - 32],
- *     2)      take keywords position (enum DCH_MM) from index
+ *     2)      take keywords position (enum DCH_MI) from index
  *     3)      run sequential search in keywords[] from this position
  *
  * ----------
@@ -554,6 +555,8 @@ typedef enum
        DCH_HH24,
        DCH_HH12,
        DCH_HH,
+       DCH_IDDD,
+       DCH_ID,
        DCH_IW,
        DCH_IYYY,
        DCH_IYY,
@@ -598,6 +601,8 @@ typedef enum
        DCH_hh24,
        DCH_hh12,
        DCH_hh,
+       DCH_iddd,
+       DCH_id,
        DCH_iw,
        DCH_iyyy,
        DCH_iyy,
@@ -696,13 +701,15 @@ static const KeyWord DCH_keywords[] = {
        {"HH24", 4, dch_time, DCH_HH24, TRUE},          /* H */
        {"HH12", 4, dch_time, DCH_HH12, TRUE},
        {"HH", 2, dch_time, DCH_HH, TRUE},
-       {"IW", 2, dch_date, DCH_IW, TRUE},      /* I */
+       {"IDDD", 4, dch_date, DCH_IDDD, TRUE},  /* I */
+       {"ID", 2, dch_date, DCH_ID, TRUE},
+       {"IW", 2, dch_date, DCH_IW, TRUE},
        {"IYYY", 4, dch_date, DCH_IYYY, TRUE},
        {"IYY", 3, dch_date, DCH_IYY, TRUE},
        {"IY", 2, dch_date, DCH_IY, TRUE},
        {"I", 1, dch_date, DCH_I, TRUE},
        {"J", 1, dch_date, DCH_J, TRUE},        /* J */
-       {"MI", 2, dch_time, DCH_MI, TRUE},
+       {"MI", 2, dch_time, DCH_MI, TRUE},      /* M */
        {"MM", 2, dch_date, DCH_MM, TRUE},
        {"MONTH", 5, dch_date, DCH_MONTH, FALSE},
        {"MON", 3, dch_date, DCH_MON, FALSE},
@@ -740,7 +747,9 @@ static const KeyWord DCH_keywords[] = {
        {"hh24", 4, dch_time, DCH_HH24, TRUE},          /* h */
        {"hh12", 4, dch_time, DCH_HH12, TRUE},
        {"hh", 2, dch_time, DCH_HH, TRUE},
-       {"iw", 2, dch_date, DCH_IW, TRUE},      /* i */
+       {"iddd", 4, dch_date, DCH_IDDD, TRUE},  /* i */
+       {"id", 2, dch_date, DCH_ID, TRUE},
+       {"iw", 2, dch_date, DCH_IW, TRUE},
        {"iyyy", 4, dch_date, DCH_IYYY, TRUE},
        {"iyy", 3, dch_date, DCH_IYY, TRUE},
        {"iy", 2, dch_date, DCH_IY, TRUE},
@@ -830,10 +839,10 @@ static const int DCH_index[KeyWord_INDEX_SIZE] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
-       DCH_FX, -1, DCH_HH24, DCH_IW, DCH_J, -1, -1, DCH_MI, -1, -1,
+       DCH_FX, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, -1,
        DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZ, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
        -1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
-       DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iw, DCH_j, -1, -1, DCH_mi,
+       DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
        -1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, DCH_us, -1, DCH_ww,
        -1, DCH_y_yyy, -1, -1, -1, -1
 
@@ -2429,9 +2438,13 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        return strlen(p_inout);
 
                case DCH_DDD:
+               case DCH_IDDD:
                        if (is_to_char)
                        {
-                               sprintf(inout, "%0*d", S_FM(suf) ? 0 : 3, tm->tm_yday);
+                               sprintf(inout, "%0*d", S_FM(suf) ? 0 : 3, 
+                                       (arg == DCH_DDD) ? 
+                                       tm->tm_yday :
+                                       date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
                                if (S_THth(suf))
                                        str_numth(p_inout, inout, S_TH_TYPE(suf));
                                return strlen(p_inout);
@@ -2473,10 +2486,14 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        }
                        break;
                case DCH_D:
+               case DCH_ID:
                        INVALID_FOR_INTERVAL;
                        if (is_to_char)
                        {
-                               sprintf(inout, "%d", tm->tm_wday + 1);
+                               if (arg == DCH_D)
+                                       sprintf(inout, "%d", tm->tm_wday + 1);
+                               else
+                                       sprintf(inout, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
                                if (S_THth(suf))
                                        str_numth(p_inout, inout, S_TH_TYPE(suf));
                                return strlen(p_inout);
@@ -2484,7 +2501,8 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        else
                        {
                                sscanf(inout, "%1d", &tmfc->d);
-                               tmfc->d--;
+                               if (arg == DCH_D)
+                                       tmfc->d--;
                                return strspace_len(inout) + 1 + SKIP_THth(suf);
                        }
                        break;
@@ -2625,15 +2643,18 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        }
                        else
                        {
+                               int *field;
+                               field = (arg == DCH_YYYY) ? &tmfc->year : &tmfc->iyear;
+
                                if (S_FM(suf) || is_next_separator(node))
                                {
-                                       sscanf(inout, "%d", &tmfc->year);
+                                       sscanf(inout, "%d", field);
                                        tmfc->yysz = 4;
                                        return strdigits_len(inout) + SKIP_THth(suf);
                                }
                                else
                                {
-                                       sscanf(inout, "%04d", &tmfc->year);
+                                       sscanf(inout, "%04d", field);
                                        tmfc->yysz = 4;
                                        return strspace_len(inout) + 4 + SKIP_THth(suf);
                                }
@@ -2657,16 +2678,19 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        }
                        else
                        {
-                               sscanf(inout, "%03d", &tmfc->year);
+                               int *field;
+                               field = (arg == DCH_YYY) ? &tmfc->year : &tmfc->iyear;
+
+                               sscanf(inout, "%03d", field);
 
                                /*
                                 * 3-digit year: '100' ... '999' = 1100 ... 1999 '000' ...
                                 * '099' = 2000 ... 2099
                                 */
-                               if (tmfc->year >= 100)
-                                       tmfc->year += 1000;
+                               if (*field >= 100)
+                                       *field += 1000;
                                else
-                                       tmfc->year += 2000;
+                                       *field += 2000;
                                tmfc->yysz = 3;
                                return strspace_len(inout) + 3 + SKIP_THth(suf);
                        }
@@ -2689,16 +2713,19 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        }
                        else
                        {
-                               sscanf(inout, "%02d", &tmfc->year);
+                               int *field;
+                               field = (arg == DCH_YY) ? &tmfc->year : &tmfc->iyear;
+
+                               sscanf(inout, "%02d", field);
 
                                /*
                                 * 2-digit year: '00' ... '69'  = 2000 ... 2069 '70' ... '99'
                                 * = 1970 ... 1999
                                 */
-                               if (tmfc->year < 70)
-                                       tmfc->year += 2000;
+                               if (*field < 70)
+                                       *field += 2000;
                                else
-                                       tmfc->year += 1900;
+                                       *field += 1900;
                                tmfc->yysz = 2;
                                return strspace_len(inout) + 2 + SKIP_THth(suf);
                        }
@@ -2721,12 +2748,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                        }
                        else
                        {
-                               sscanf(inout, "%1d", &tmfc->year);
+                               int *field;
+                               field = (arg == DCH_Y) ? &tmfc->year : &tmfc->iyear;
+
+                               sscanf(inout, "%1d", field);
 
                                /*
                                 * 1-digit year: always +2000
                                 */
-                               tmfc->year += 2000;
+                               *field += 2000;
                                tmfc->yysz = 1;
                                return strspace_len(inout) + 1 + SKIP_THth(suf);
                        }
@@ -3297,7 +3327,8 @@ do_to_timestamp(text *date_txt, text *fmt,
 {
        FormatNode *format;
        TmFromChar      tmfc;
-       int                     fmt_len;
+       int                     fmt_len,
+                               year;
 
        ZERO_tm(tm);
        *fsec = 0;
@@ -3447,7 +3478,13 @@ do_to_timestamp(text *date_txt, text *fmt,
                        break;
        }
 
-       if (tmfc.year)
+       /*
+        * Only one year value is used.  If iyear (the ISO year) is defined, it takes precedence.  
+        * Otherwise year (the Gregorian year) is used.
+        */
+       year = (tmfc.iyear) ? tmfc.iyear : tmfc.year;
+
+       if (year)
        {
                /*
                 * If CC and YY (or Y) are provided, use YY as 2 low-order digits
@@ -3458,14 +3495,14 @@ do_to_timestamp(text *date_txt, text *fmt,
                 */
                if (tmfc.cc && tmfc.yysz <= 2)
                {
-                       tm->tm_year = tmfc.year % 100;
+                       tm->tm_year = year % 100;
                        if (tm->tm_year)
                                tm->tm_year += (tmfc.cc - 1) * 100;
                        else
                                tm->tm_year = tmfc.cc * 100;
                }
                else
-                       tm->tm_year = tmfc.year;
+                       tm->tm_year = year;
        }
        else if (tmfc.cc)                       /* use first year of century */
                tm->tm_year = (tmfc.cc - 1) * 100 + 1;
@@ -3485,48 +3522,78 @@ do_to_timestamp(text *date_txt, text *fmt,
                j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
 
        if (tmfc.iw)
-               isoweek2date(tmfc.iw, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+       {
+               /* 
+                * Since the user has employed the IW field, it is assumed that the value in tmfc.d 
+                * is in ISO day-of-week form (1 = Monday), as set by the ID field.  Mixing IW and D 
+                * will yield weird results.
+                *
+                * tmfc.iyear must have been set (e.g., with IYYY) for this to work properly (an ISO week
+                * without an ISO year is meaningless).
+                *
+                * If tmfc.d is not set, then the date is left at the beginning of the ISO week (Monday).
+                */
+               if (tmfc.d)
+               {
+                       isoweekdate2date(tmfc.iw, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+               }
+               else
+                       isoweek2date(tmfc.iw, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+       }
+
 
        if (tmfc.d)
                tm->tm_wday = tmfc.d;
        if (tmfc.dd)
                tm->tm_mday = tmfc.dd;
-       if (tmfc.ddd)
+       if (tmfc.ddd && !tmfc.iyear)
                tm->tm_yday = tmfc.ddd;
        if (tmfc.mm)
                tm->tm_mon = tmfc.mm;
 
-       /*
-        * we don't ignore DDD
-        */
        if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
        {
-               /* count mday and mon from yday */
-               int                *y,
-                                       i;
+               /*
+                * If the iyear field is set, the value of ddd is taken to be an ISO day-of-year.
+                * Otherwise, it is a Gregorian day-of-year.
+                * Either way, since the month and day fields have not been set by some other means,
+                * the value of ddd will be used to compute them.
+                */
+               if (tmfc.iyear)
+               {
+                       int j0;         // zeroth day of the ISO year, in Julian
+                       j0 = isoweek2j(tmfc.iyear, 1) - 1;
 
-               int                     ysum[2][13] = {
-                       {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 0},
-               {31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366, 0}};
+                       j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+               }
+               else
+               {
+                       int                *y,
+                                               i;
 
-               if (!tm->tm_year)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
-                       errmsg("cannot calculate day of year without year information")));
+                       int                     ysum[2][13] = {
+                               {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 0},
+                       {31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366, 0}};
 
-               y = ysum[isleap(tm->tm_year)];
+                       if (!tm->tm_year)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
+                               errmsg("cannot calculate day of year without year information")));
 
-               for (i = 0; i <= 11; i++)
-               {
-                       if (tm->tm_yday < y[i])
-                               break;
-               }
-               if (tm->tm_mon <= 1)
-                       tm->tm_mon = i + 1;
+                       y = ysum[isleap(tm->tm_year)];
 
-               if (tm->tm_mday <= 1)
-                       tm->tm_mday = i == 0 ? tm->tm_yday :
-                               tm->tm_yday - y[i - 1];
+                       for (i = 0; i <= 11; i++)
+                       {
+                               if (tm->tm_yday < y[i])
+                                       break;
+                       }
+                       if (tm->tm_mon <= 1)
+                               tm->tm_mon = i + 1;
+
+                       if (tm->tm_mday <= 1)
+                               tm->tm_mday = i == 0 ? tm->tm_yday :
+                                       tm->tm_yday - y[i - 1];
+               }
        }
 
 #ifdef HAVE_INT64_TIMESTAMP
index 13dba7cb5c6d99eedc17e8df1c55ba3ca13e2015..7632e1b8961a544a124de30adc590b45285c722c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.171 2007/01/05 22:19:42 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.172 2007/02/16 03:39:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3749,32 +3749,57 @@ interval_trunc(PG_FUNCTION_ARGS)
        PG_RETURN_INTERVAL_P(result);
 }
 
-/* isoweek2date()
- * Convert ISO week of year number to date.
- * The year field must be specified with the ISO year!
- * karel 2000/08/07
+/* isoweek2j()
+ *
+ *     Return the Julian day which corresponds to the first day (Monday) of the given ISO 8601 year and week.
+ *     Julian days are used to convert between ISO week dates and Gregorian dates.
  */
-void
-isoweek2date(int woy, int *year, int *mon, int *mday)
+int
+isoweek2j(int year, int week)
 {
        int                     day0,
-                               day4,
-                               dayn;
+                               day4;
 
-       if (!*year)
+       if (!year)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                   errmsg("cannot calculate week number without year information")));
 
        /* fourth day of current year */
-       day4 = date2j(*year, 1, 4);
+       day4 = date2j(year, 1, 4);
 
        /* day0 == offset to first day of week (Monday) */
        day0 = j2day(day4 - 1);
 
-       dayn = ((woy - 1) * 7) + (day4 - day0);
+       return ((week - 1) * 7) + (day4 - day0);
+}
+
+/* isoweek2date()
+ * Convert ISO week of year number to date.
+ * The year field must be specified with the ISO year!
+ * karel 2000/08/07
+ */
+void
+isoweek2date(int woy, int *year, int *mon, int *mday)
+{
+       j2date(isoweek2j(*year, woy), year, mon, mday);
+}
+
+/* isoweekdate2date()
+ *
+ *     Convert an ISO 8601 week date (ISO year, ISO week and day of week) into a Gregorian date.
+ *     Populates year, mon, and mday with the correct Gregorian values.
+ *     year must be passed in as the ISO year.
+ */
+void
+isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday)
+{
+       int jday;
+
+       jday = isoweek2j(*year, isoweek);
+       jday += isowday - 1;
 
-       j2date(dayn, year, mon, mday);
+       j2date(jday, year, mon, mday);
 }
 
 /* date2isoweek()
@@ -3887,6 +3912,17 @@ date2isoyear(int year, int mon, int mday)
 }
 
 
+/* date2isoyearday()
+ *
+ *     Returns the ISO 8601 day-of-year, given a Gregorian year, month and day.
+ *     Possible return values are 1 through 371 (364 in non-leap years).
+ */
+int
+date2isoyearday(int year, int mon, int mday)
+{
+       return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1;
+}
+
 /* timestamp_part()
  * Extract specified field from timestamp.
  */
@@ -4029,6 +4065,10 @@ timestamp_part(PG_FUNCTION_ARGS)
 #endif
                                break;
 
+                       case DTK_ISOYEAR:
+                               result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
+                               break;
+
                        case DTK_TZ:
                        case DTK_TZ_MINUTE:
                        case DTK_TZ_HOUR:
@@ -4256,6 +4296,10 @@ timestamptz_part(PG_FUNCTION_ARGS)
 #endif
                                break;
 
+                       case DTK_ISOYEAR:
+                               result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
+                               break;
+
                        default:
                                ereport(ERROR,
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
index 0b19143c286e47162b6e1803db55cb9f6ac5c8ea..fc7b16fdb47bb124d68f6b5114eeb8b0f15736e7 100644 (file)
@@ -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.63 2007/01/05 22:19:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.64 2007/02/16 03:39:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define DTK_DOY                        33
 #define DTK_TZ_HOUR            34
 #define DTK_TZ_MINUTE  35
+#define DTK_ISOYEAR            36
 
 
 /*
index 4ff1ffe869e9bd4c435f57fd3ff47d61592e93b9..0d31cc02940c47d670508f090926b8ae3cf8710a 100644 (file)
@@ -6,7 +6,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/timestamp.h,v 1.66 2007/01/05 22:19:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.67 2007/02/16 03:39:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -331,8 +331,11 @@ extern int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
 /* timestamp comparison works for timestamptz also */
 #define timestamptz_cmp_internal(dt1,dt2)      timestamp_cmp_internal(dt1, dt2)
 
-extern void isoweek2date(int woy, int *year, int *mon, int *mday);
+extern int     isoweek2j(int year, int week);
+extern void    isoweek2date(int woy, int *year, int *mon, int *mday);
+extern void    isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday);
 extern int     date2isoweek(int year, int mon, int mday);
 extern int     date2isoyear(int year, int mon, int mday);
+extern int     date2isoyearday(int year, int mon, int mday);
 
 #endif   /* TIMESTAMP_H */
index 95793aabc304e914fd6130a16079ed845f6743a1..d0bfc00bbdd97e9d3956ac5f1b417a3020d9f8a0 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt.h,v 1.34 2006/03/11 04:38:39 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt.h,v 1.35 2007/02/16 03:39:45 momjian Exp $ */
 
 #ifndef DT_H
 #define DT_H
@@ -157,6 +157,7 @@ typedef double fsec_t;
 #define DTK_DOY                        33
 #define DTK_TZ_HOUR            34
 #define DTK_TZ_MINUTE  35
+#define DTK_ISOYEAR            36
 
 
 /*
index c26cb9ec99382fc266228ef6ad2b995e9eb6b43e..9f585b68f6b2df97009c1b4b28f5f30c3b541936 100644 (file)
@@ -703,6 +703,69 @@ SELECT '' AS "54", d1 as "timestamp",
     | Mon Jan 01 17:32:01 2001    |       1 |  1000 |  1000000
 (55 rows)
 
+SELECT '' AS "54", d1 as "timestamp",
+   date_part( 'isoyear', d1) AS isoyear, date_part( 'week', d1) AS week,
+   date_part( 'dow', d1) AS dow
+   FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
+ 54 |          timestamp          | isoyear | week | dow 
+----+-----------------------------+---------+------+-----
+    | Thu Jan 01 00:00:00 1970    |    1970 |    1 |   4
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:02 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01.40 1997 |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01.50 1997 |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01.60 1997 |    1997 |    7 |   1
+    | Thu Jan 02 00:00:00 1997    |    1997 |    1 |   4
+    | Thu Jan 02 03:04:05 1997    |    1997 |    1 |   4
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Tue Jun 10 17:32:01 1997    |    1997 |   24 |   2
+    | Sat Sep 22 18:19:20 2001    |    2001 |   38 |   6
+    | Wed Mar 15 08:14:01 2000    |    2000 |   11 |   3
+    | Wed Mar 15 13:14:02 2000    |    2000 |   11 |   3
+    | Wed Mar 15 12:14:03 2000    |    2000 |   11 |   3
+    | Wed Mar 15 03:14:04 2000    |    2000 |   11 |   3
+    | Wed Mar 15 02:14:05 2000    |    2000 |   11 |   3
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:00 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Tue Jun 10 18:32:01 1997    |    1997 |   24 |   2
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Tue Feb 11 17:32:01 1997    |    1997 |    7 |   2
+    | Wed Feb 12 17:32:01 1997    |    1997 |    7 |   3
+    | Thu Feb 13 17:32:01 1997    |    1997 |    7 |   4
+    | Fri Feb 14 17:32:01 1997    |    1997 |    7 |   5
+    | Sat Feb 15 17:32:01 1997    |    1997 |    7 |   6
+    | Sun Feb 16 17:32:01 1997    |    1997 |    7 |   0
+    | Sun Feb 16 17:32:01 1997    |    1997 |    7 |   0
+    | Wed Feb 28 17:32:01 1996    |    1996 |    9 |   3
+    | Thu Feb 29 17:32:01 1996    |    1996 |    9 |   4
+    | Fri Mar 01 17:32:01 1996    |    1996 |    9 |   5
+    | Mon Dec 30 17:32:01 1996    |    1997 |    1 |   1
+    | Tue Dec 31 17:32:01 1996    |    1997 |    1 |   2
+    | Wed Jan 01 17:32:01 1997    |    1997 |    1 |   3
+    | Fri Feb 28 17:32:01 1997    |    1997 |    9 |   5
+    | Sat Mar 01 17:32:01 1997    |    1997 |    9 |   6
+    | Tue Dec 30 17:32:01 1997    |    1998 |    1 |   2
+    | Wed Dec 31 17:32:01 1997    |    1998 |    1 |   3
+    | Fri Dec 31 17:32:01 1999    |    1999 |   52 |   5
+    | Sat Jan 01 17:32:01 2000    |    1999 |   52 |   6
+    | Sun Dec 31 17:32:01 2000    |    2000 |   52 |   0
+    | Mon Jan 01 17:32:01 2001    |    2001 |    1 |   1
+(55 rows)
+
 -- TO_CHAR()
 SELECT '' AS to_char_1, to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') 
    FROM TIMESTAMP_TBL;
@@ -1344,6 +1407,148 @@ SELECT '' AS to_char_9, to_char(d1, 'YYYY A.D. YYYY a.d. YYYY bc HH:MI:SS P.M. H
            | 2001 A.D. 2001 a.d. 2001 ad 05:32:01 P.M. 05:32:01 p.m. 05:32:01 pm
 (65 rows)
 
+SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
+   FROM TIMESTAMP_TBL;
+ to_char_10 |        to_char         
+------------+------------------------
+            | 
+            | 
+            | 1970 970 70 0 01 004 4
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 01 004 4
+            | 1997 997 97 7 01 004 4
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 24 163 2
+            | 2001 001 01 1 38 265 6
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 24 163 2
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 044 2
+            | 1997 997 97 7 07 045 3
+            | 1997 997 97 7 07 046 4
+            | 1997 997 97 7 07 047 5
+            | 1997 997 97 7 07 048 6
+            | 1997 997 97 7 07 049 7
+            | 0097 097 97 7 07 044 2
+            | 0097 097 97 7 07 048 6
+            | 0597 597 97 7 07 046 4
+            | 1097 097 97 7 07 044 2
+            | 1697 697 97 7 07 048 6
+            | 1797 797 97 7 07 046 4
+            | 1897 897 97 7 07 044 2
+            | 1997 997 97 7 07 049 7
+            | 2097 097 97 7 07 048 6
+            | 1996 996 96 6 09 059 3
+            | 1996 996 96 6 09 060 4
+            | 1996 996 96 6 09 061 5
+            | 1997 997 97 7 01 001 1
+            | 1997 997 97 7 01 002 2
+            | 1997 997 97 7 01 003 3
+            | 1997 997 97 7 09 061 5
+            | 1997 997 97 7 09 062 6
+            | 1998 998 98 8 01 002 2
+            | 1998 998 98 8 01 003 3
+            | 1999 999 99 9 52 362 5
+            | 1999 999 99 9 52 363 6
+            | 2000 000 00 0 52 364 7
+            | 2001 001 01 1 01 001 1
+(65 rows)
+
+SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
+   FROM TIMESTAMP_TBL;
+ to_char_11 |        to_char         
+------------+------------------------
+            | 
+            | 
+            | 1970 970 70 0 1 4 4
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 1 4 4
+            | 1997 997 97 7 1 4 4
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 24 163 2
+            | 2001 001 01 1 38 265 6
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 24 163 2
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 44 2
+            | 1997 997 97 7 7 45 3
+            | 1997 997 97 7 7 46 4
+            | 1997 997 97 7 7 47 5
+            | 1997 997 97 7 7 48 6
+            | 1997 997 97 7 7 49 7
+            | 97 097 97 7 7 44 2
+            | 97 097 97 7 7 48 6
+            | 597 597 97 7 7 46 4
+            | 1097 097 97 7 7 44 2
+            | 1697 697 97 7 7 48 6
+            | 1797 797 97 7 7 46 4
+            | 1897 897 97 7 7 44 2
+            | 1997 997 97 7 7 49 7
+            | 2097 097 97 7 7 48 6
+            | 1996 996 96 6 9 59 3
+            | 1996 996 96 6 9 60 4
+            | 1996 996 96 6 9 61 5
+            | 1997 997 97 7 1 1 1
+            | 1997 997 97 7 1 2 2
+            | 1997 997 97 7 1 3 3
+            | 1997 997 97 7 9 61 5
+            | 1997 997 97 7 9 62 6
+            | 1998 998 98 8 1 2 2
+            | 1998 998 98 8 1 3 3
+            | 1999 999 99 9 52 362 5
+            | 1999 999 99 9 52 363 6
+            | 2000 000 00 0 52 364 7
+            | 2001 001 01 1 1 1 1
+(65 rows)
+
 -- TO_TIMESTAMP()
 SELECT '' AS to_timestamp_1, to_timestamp('0097/Feb/16 --> 08:14:30', 'YYYY/Mon/DD --> HH:MI:SS');
  to_timestamp_1 |         to_timestamp         
@@ -1428,4 +1633,46 @@ SELECT '' AS to_timestamp_14, to_timestamp('995-1116', 'YYY-MMDD');
                  | Thu Nov 16 00:00:00 1995 PST
 (1 row)
 
+SELECT '' AS to_timestamp_15, to_timestamp('2005426', 'YYYYWWD');
+ to_timestamp_15 |         to_timestamp         
+-----------------+------------------------------
+                 | Sat Oct 15 00:00:00 2005 PDT
+(1 row)
+
+SELECT '' AS to_timestamp_16, to_timestamp('2005300', 'YYYYDDD');
+ to_timestamp_16 |         to_timestamp         
+-----------------+------------------------------
+                 | Thu Oct 27 00:00:00 2005 PDT
+(1 row)
+
+SELECT '' AS to_timestamp_17, to_timestamp('2005527', 'IYYYIWID');
+ to_timestamp_17 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_18, to_timestamp('005527', 'IYYIWID');
+ to_timestamp_18 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_19, to_timestamp('05527', 'IYIWID');
+ to_timestamp_19 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_20, to_timestamp('5527', 'IIWID');
+ to_timestamp_20 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_21, to_timestamp('2005364', 'IYYYIDDD');
+ to_timestamp_21 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
 SET DateStyle TO DEFAULT;
index be3d7bed5d1edc949765eb0c95ab5676eb6f9f2d..e875c90d5d1803fb4f1a574dff3998c7bb9fb7a7 100644 (file)
@@ -720,6 +720,69 @@ SELECT '' AS "54", d1 as timestamptz,
     | Mon Jan 01 17:32:01 2001 PST    |       1 |  1000 |  1000000
 (56 rows)
 
+SELECT '' AS "54", d1 as "timestamp",
+   date_part( 'isoyear', d1) AS isoyear, date_part( 'week', d1) AS week,
+   date_part( 'dow', d1) AS dow
+   FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
+ 54 |          timestamp          | isoyear | week | dow 
+----+-----------------------------+---------+------+-----
+    | Thu Jan 01 00:00:00 1970    |    1970 |    1 |   4
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:02 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01.40 1997 |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01.50 1997 |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01.60 1997 |    1997 |    7 |   1
+    | Thu Jan 02 00:00:00 1997    |    1997 |    1 |   4
+    | Thu Jan 02 03:04:05 1997    |    1997 |    1 |   4
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Tue Jun 10 17:32:01 1997    |    1997 |   24 |   2
+    | Sat Sep 22 18:19:20 2001    |    2001 |   38 |   6
+    | Wed Mar 15 08:14:01 2000    |    2000 |   11 |   3
+    | Wed Mar 15 13:14:02 2000    |    2000 |   11 |   3
+    | Wed Mar 15 12:14:03 2000    |    2000 |   11 |   3
+    | Wed Mar 15 03:14:04 2000    |    2000 |   11 |   3
+    | Wed Mar 15 02:14:05 2000    |    2000 |   11 |   3
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:00 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Tue Jun 10 18:32:01 1997    |    1997 |   24 |   2
+    | Mon Feb 10 17:32:01 1997    |    1997 |    7 |   1
+    | Tue Feb 11 17:32:01 1997    |    1997 |    7 |   2
+    | Wed Feb 12 17:32:01 1997    |    1997 |    7 |   3
+    | Thu Feb 13 17:32:01 1997    |    1997 |    7 |   4
+    | Fri Feb 14 17:32:01 1997    |    1997 |    7 |   5
+    | Sat Feb 15 17:32:01 1997    |    1997 |    7 |   6
+    | Sun Feb 16 17:32:01 1997    |    1997 |    7 |   0
+    | Sun Feb 16 17:32:01 1997    |    1997 |    7 |   0
+    | Wed Feb 28 17:32:01 1996    |    1996 |    9 |   3
+    | Thu Feb 29 17:32:01 1996    |    1996 |    9 |   4
+    | Fri Mar 01 17:32:01 1996    |    1996 |    9 |   5
+    | Mon Dec 30 17:32:01 1996    |    1997 |    1 |   1
+    | Tue Dec 31 17:32:01 1996    |    1997 |    1 |   2
+    | Wed Jan 01 17:32:01 1997    |    1997 |    1 |   3
+    | Fri Feb 28 17:32:01 1997    |    1997 |    9 |   5
+    | Sat Mar 01 17:32:01 1997    |    1997 |    9 |   6
+    | Tue Dec 30 17:32:01 1997    |    1998 |    1 |   2
+    | Wed Dec 31 17:32:01 1997    |    1998 |    1 |   3
+    | Fri Dec 31 17:32:01 1999    |    1999 |   52 |   5
+    | Sat Jan 01 17:32:01 2000    |    1999 |   52 |   6
+    | Sun Dec 31 17:32:01 2000    |    2000 |   52 |   0
+    | Mon Jan 01 17:32:01 2001    |    2001 |    1 |   1
+(55 rows)
+
 -- TO_CHAR()
 SELECT '' AS to_char_1, to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') 
    FROM TIMESTAMPTZ_TBL;
@@ -1374,77 +1437,147 @@ SELECT '' AS to_char_9, to_char(d1, 'YYYY A.D. YYYY a.d. YYYY bc HH:MI:SS P.M. H
            | 2001 A.D. 2001 a.d. 2001 ad 05:32:01 P.M. 05:32:01 p.m. 05:32:01 pm
 (66 rows)
 
-SELECT '' AS to_char_10, to_char(d1, 'YYYY WW IYYY IYY IY I IW') 
-   FROM TIMESTAMPTZ_TBL;
- to_char_10 |         to_char          
-------------+--------------------------
+SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
+   FROM TIMESTAMP_TBL;
+ to_char_10 |        to_char         
+------------+------------------------
             | 
             | 
-            | 1969 53 1970 970 70 0 01
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 01 1997 997 97 7 01
-            | 1997 01 1997 997 97 7 01
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 23 1997 997 97 7 24
-            | 2001 38 2001 001 01 1 38
-            | 2000 11 2000 000 00 0 11
-            | 2000 11 2000 000 00 0 11
-            | 2000 11 2000 000 00 0 11
-            | 2000 11 2000 000 00 0 11
-            | 2000 11 2000 000 00 0 11
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 28 1997 997 97 7 28
-            | 1997 23 1997 997 97 7 24
-            | 1997 06 1997 997 97 7 07
-            | 1997 06 1997 997 97 7 07
-            | 1997 07 1997 997 97 7 07
-            | 1997 07 1997 997 97 7 07
-            | 1997 07 1997 997 97 7 07
-            | 1997 07 1997 997 97 7 07
-            | 1997 07 1997 997 97 7 07
-            | 0097 07 0097 097 97 7 07
-            | 0097 07 0097 097 97 7 07
-            | 0597 07 0597 597 97 7 07
-            | 1097 07 1097 097 97 7 07
-            | 1697 07 1697 697 97 7 07
-            | 1797 07 1797 797 97 7 07
-            | 1897 07 1897 897 97 7 07
-            | 1997 07 1997 997 97 7 07
-            | 2097 07 2097 097 97 7 07
-            | 1996 09 1996 996 96 6 09
-            | 1996 09 1996 996 96 6 09
-            | 1996 09 1996 996 96 6 09
-            | 1996 53 1997 997 97 7 01
-            | 1996 53 1997 997 97 7 01
-            | 1997 01 1997 997 97 7 01
-            | 1997 09 1997 997 97 7 09
-            | 1997 09 1997 997 97 7 09
-            | 1997 52 1998 998 98 8 01
-            | 1997 53 1998 998 98 8 01
-            | 1999 53 1999 999 99 9 52
-            | 2000 01 1999 999 99 9 52
-            | 2000 53 2000 000 00 0 52
-            | 2001 01 2001 001 01 1 01
-(66 rows)
+            | 1970 970 70 0 01 004 4
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 01 004 4
+            | 1997 997 97 7 01 004 4
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 24 163 2
+            | 2001 001 01 1 38 265 6
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 2000 000 00 0 11 073 3
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 24 163 2
+            | 1997 997 97 7 07 043 1
+            | 1997 997 97 7 07 044 2
+            | 1997 997 97 7 07 045 3
+            | 1997 997 97 7 07 046 4
+            | 1997 997 97 7 07 047 5
+            | 1997 997 97 7 07 048 6
+            | 1997 997 97 7 07 049 7
+            | 0097 097 97 7 07 044 2
+            | 0097 097 97 7 07 048 6
+            | 0597 597 97 7 07 046 4
+            | 1097 097 97 7 07 044 2
+            | 1697 697 97 7 07 048 6
+            | 1797 797 97 7 07 046 4
+            | 1897 897 97 7 07 044 2
+            | 1997 997 97 7 07 049 7
+            | 2097 097 97 7 07 048 6
+            | 1996 996 96 6 09 059 3
+            | 1996 996 96 6 09 060 4
+            | 1996 996 96 6 09 061 5
+            | 1997 997 97 7 01 001 1
+            | 1997 997 97 7 01 002 2
+            | 1997 997 97 7 01 003 3
+            | 1997 997 97 7 09 061 5
+            | 1997 997 97 7 09 062 6
+            | 1998 998 98 8 01 002 2
+            | 1998 998 98 8 01 003 3
+            | 1999 999 99 9 52 362 5
+            | 1999 999 99 9 52 363 6
+            | 2000 000 00 0 52 364 7
+            | 2001 001 01 1 01 001 1
+(65 rows)
+
+SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
+   FROM TIMESTAMP_TBL;
+ to_char_11 |        to_char         
+------------+------------------------
+            | 
+            | 
+            | 1970 970 70 0 1 4 4
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 1 4 4
+            | 1997 997 97 7 1 4 4
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 24 163 2
+            | 2001 001 01 1 38 265 6
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 2000 000 00 0 11 73 3
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 24 163 2
+            | 1997 997 97 7 7 43 1
+            | 1997 997 97 7 7 44 2
+            | 1997 997 97 7 7 45 3
+            | 1997 997 97 7 7 46 4
+            | 1997 997 97 7 7 47 5
+            | 1997 997 97 7 7 48 6
+            | 1997 997 97 7 7 49 7
+            | 97 097 97 7 7 44 2
+            | 97 097 97 7 7 48 6
+            | 597 597 97 7 7 46 4
+            | 1097 097 97 7 7 44 2
+            | 1697 697 97 7 7 48 6
+            | 1797 797 97 7 7 46 4
+            | 1897 897 97 7 7 44 2
+            | 1997 997 97 7 7 49 7
+            | 2097 097 97 7 7 48 6
+            | 1996 996 96 6 9 59 3
+            | 1996 996 96 6 9 60 4
+            | 1996 996 96 6 9 61 5
+            | 1997 997 97 7 1 1 1
+            | 1997 997 97 7 1 2 2
+            | 1997 997 97 7 1 3 3
+            | 1997 997 97 7 9 61 5
+            | 1997 997 97 7 9 62 6
+            | 1998 998 98 8 1 2 2
+            | 1998 998 98 8 1 3 3
+            | 1999 999 99 9 52 362 5
+            | 1999 999 99 9 52 363 6
+            | 2000 000 00 0 52 364 7
+            | 2001 001 01 1 1 1 1
+(65 rows)
 
 -- TO_TIMESTAMP()
 SELECT '' AS to_timestamp_1, to_timestamp('0097/Feb/16 --> 08:14:30', 'YYYY/Mon/DD --> HH:MI:SS');
@@ -1531,16 +1664,46 @@ SELECT '' AS to_timestamp_14, to_timestamp('995-1116', 'YYY-MMDD');
                  | Thu Nov 16 00:00:00 1995 PST
 (1 row)
 
-SELECT '' AS to_timestamp_15, to_timestamp('200401', 'IYYYIW');
+SELECT '' AS to_timestamp_15, to_timestamp('2005426', 'YYYYWWD');
  to_timestamp_15 |         to_timestamp         
 -----------------+------------------------------
-                 | Mon Dec 29 00:00:00 2003 PST
+                 | Sat Oct 15 00:00:00 2005 PDT
 (1 row)
 
-SELECT '' AS to_timestamp_16, to_timestamp('200401', 'YYYYWW');
+SELECT '' AS to_timestamp_16, to_timestamp('2005300', 'YYYYDDD');
  to_timestamp_16 |         to_timestamp         
 -----------------+------------------------------
-                 | Thu Jan 01 00:00:00 2004 PST
+                 | Thu Oct 27 00:00:00 2005 PDT
+(1 row)
+
+SELECT '' AS to_timestamp_17, to_timestamp('2005527', 'IYYYIWID');
+ to_timestamp_17 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_18, to_timestamp('005527', 'IYYIWID');
+ to_timestamp_18 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_19, to_timestamp('05527', 'IYIWID');
+ to_timestamp_19 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_20, to_timestamp('5527', 'IIWID');
+ to_timestamp_20 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
+(1 row)
+
+SELECT '' AS to_timestamp_21, to_timestamp('2005364', 'IYYYIDDD');
+ to_timestamp_21 |         to_timestamp         
+-----------------+------------------------------
+                 | Sun Jan 01 00:00:00 2006 PST
 (1 row)
 
 SET DateStyle TO DEFAULT;
index 34689564daec969df82b72371b2a8bd00cbc8303..81be5b8f33f11664bf993081bc3b2fa047f98dad 100644 (file)
@@ -171,6 +171,11 @@ SELECT '' AS "54", d1 as "timestamp",
    date_part( 'usec', d1) AS usec
    FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
 
+SELECT '' AS "54", d1 as "timestamp",
+   date_part( 'isoyear', d1) AS isoyear, date_part( 'week', d1) AS week,
+   date_part( 'dow', d1) AS dow
+   FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
+
 -- TO_CHAR()
 SELECT '' AS to_char_1, to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') 
    FROM TIMESTAMP_TBL;
@@ -199,6 +204,12 @@ SELECT '' AS to_char_8, to_char(d1, 'YYYYTH YYYYth Jth')
 SELECT '' AS to_char_9, to_char(d1, 'YYYY A.D. YYYY a.d. YYYY bc HH:MI:SS P.M. HH:MI:SS p.m. HH:MI:SS pm') 
    FROM TIMESTAMP_TBL;   
 
+SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
+   FROM TIMESTAMP_TBL;
+
+SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
+   FROM TIMESTAMP_TBL;
+
 -- TO_TIMESTAMP()
 SELECT '' AS to_timestamp_1, to_timestamp('0097/Feb/16 --> 08:14:30', 'YYYY/Mon/DD --> HH:MI:SS');
 
@@ -230,4 +241,18 @@ SELECT '' AS to_timestamp_13, to_timestamp('95-1116', 'YY-MMDD');
 
 SELECT '' AS to_timestamp_14, to_timestamp('995-1116', 'YYY-MMDD');
 
+SELECT '' AS to_timestamp_15, to_timestamp('2005426', 'YYYYWWD');
+
+SELECT '' AS to_timestamp_16, to_timestamp('2005300', 'YYYYDDD');
+
+SELECT '' AS to_timestamp_17, to_timestamp('2005527', 'IYYYIWID');
+
+SELECT '' AS to_timestamp_18, to_timestamp('005527', 'IYYIWID');
+
+SELECT '' AS to_timestamp_19, to_timestamp('05527', 'IYIWID');
+
+SELECT '' AS to_timestamp_20, to_timestamp('5527', 'IIWID');
+
+SELECT '' AS to_timestamp_21, to_timestamp('2005364', 'IYYYIDDD');
+
 SET DateStyle TO DEFAULT;
index fc597a6b2cf477da44d86c11282dd7833e378937..6ef216a53a28224635f1b6fb9e8d3f4eeb3676e2 100644 (file)
@@ -169,6 +169,11 @@ SELECT '' AS "54", d1 as timestamptz,
    date_part( 'usec', d1) AS usec
    FROM TIMESTAMPTZ_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
 
+SELECT '' AS "54", d1 as "timestamp",
+   date_part( 'isoyear', d1) AS isoyear, date_part( 'week', d1) AS week,
+   date_part( 'dow', d1) AS dow
+   FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
+
 -- TO_CHAR()
 SELECT '' AS to_char_1, to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') 
    FROM TIMESTAMPTZ_TBL;
@@ -197,8 +202,11 @@ SELECT '' AS to_char_8, to_char(d1, 'YYYYTH YYYYth Jth')
 SELECT '' AS to_char_9, to_char(d1, 'YYYY A.D. YYYY a.d. YYYY bc HH:MI:SS P.M. HH:MI:SS p.m. HH:MI:SS pm') 
    FROM TIMESTAMPTZ_TBL;   
 
-SELECT '' AS to_char_10, to_char(d1, 'YYYY WW IYYY IYY IY I IW') 
-   FROM TIMESTAMPTZ_TBL;
+SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
+   FROM TIMESTAMP_TBL;
+
+SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
+   FROM TIMESTAMP_TBL;
 
 -- TO_TIMESTAMP()
 SELECT '' AS to_timestamp_1, to_timestamp('0097/Feb/16 --> 08:14:30', 'YYYY/Mon/DD --> HH:MI:SS');
@@ -231,9 +239,18 @@ SELECT '' AS to_timestamp_13, to_timestamp('95-1116', 'YY-MMDD');
 
 SELECT '' AS to_timestamp_14, to_timestamp('995-1116', 'YYY-MMDD');
 
-SELECT '' AS to_timestamp_15, to_timestamp('200401', 'IYYYIW');
+SELECT '' AS to_timestamp_15, to_timestamp('2005426', 'YYYYWWD');
+
+SELECT '' AS to_timestamp_16, to_timestamp('2005300', 'YYYYDDD');
+
+SELECT '' AS to_timestamp_17, to_timestamp('2005527', 'IYYYIWID');
+
+SELECT '' AS to_timestamp_18, to_timestamp('005527', 'IYYIWID');
+
+SELECT '' AS to_timestamp_19, to_timestamp('05527', 'IYIWID');
 
-SELECT '' AS to_timestamp_16, to_timestamp('200401', 'YYYYWW');
+SELECT '' AS to_timestamp_20, to_timestamp('5527', 'IIWID');
 
+SELECT '' AS to_timestamp_21, to_timestamp('2005364', 'IYYYIDDD');
 
 SET DateStyle TO DEFAULT;