]> granicus.if.org Git - postgresql/commitdiff
Fix handling of CC (century) format spec in to_date/to_char. According to
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 12 Jan 2007 23:34:55 +0000 (23:34 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 12 Jan 2007 23:34:55 +0000 (23:34 +0000)
standard convention the 21st century runs from 2001-2100, not 2000-2099,
so make it work like that.  Per bug #2885 from Akio Iwaasa.

Backpatch to 8.2, but no further, since this is really a definitional
change; users of older branches are probably more interested in stability.

doc/src/sgml/func.sgml
src/backend/utils/adt/formatting.c
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out

index 7617642f200a9d4afd3d7639b9f929257d84be71..b9cd00320b412205b3d2d78cbd67b2b00a4d984a 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.349 2007/01/12 20:06:10 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.350 2007/01/12 23:34:54 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -4617,7 +4617,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
        </row>
        <row>
         <entry><literal>CC</literal></entry>
-        <entry>century component of year (minimum 2 digits)</entry>
+        <entry>century (2 digits) (The twenty-first century starts on 2001-01-01.)</entry>
        </row>
        <row>
         <entry><literal>J</literal></entry>
index 664942ffdb93bfc7735a7c5663e18e5f19e829e7..66fc77e6a82e0f4d65409cc0d9f2f9d6cbcbd1d0 100644 (file)
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.117 2007/01/05 22:19:40 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.118 2007/01/12 23:34:54 tgl Exp $
  *
  *
  *      Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
@@ -2445,7 +2445,10 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
                case DCH_CC:
                        if (is_to_char)
                        {
-                               i = tm->tm_year / 100 + ((is_interval) ? 0 : 1);
+                               if (is_interval)                        /* straight calculation */
+                                       i = tm->tm_year / 100;
+                               else                                            /* century 21 starts in 2001 */
+                                       i = (tm->tm_year - 1) / 100 + 1;
                                if (i <= 99 && i >= -99)
                                        sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, i);
                                else
@@ -3295,9 +3298,6 @@ do_to_timestamp(text *date_txt, text *fmt,
                tm->tm_sec = x;
        }
 
-       if (tmfc.cc)
-               tm->tm_year = (tmfc.cc - 1) * 100;
-
        if (tmfc.ww)
                tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
 
@@ -3347,24 +3347,27 @@ do_to_timestamp(text *date_txt, text *fmt,
 
        if (tmfc.year)
        {
-               if (tmfc.yysz == 2 && tmfc.cc)
-               {
-                       /*
-                        * CC and YY defined why -[2000|1900]? See dch_date() DCH_YY code.
-                        */
-                       tm->tm_year = (tmfc.cc - 1) * 100 + (tmfc.year >= 2000 ? tmfc.year - 2000 : tmfc.year - 1900);
-               }
-               else if (tmfc.yysz == 1 && tmfc.cc)
+               /*
+                * If CC and YY (or Y) are provided, use YY as 2 low-order digits
+                * for the year in the given century.  Keep in mind that the 21st
+                * century runs from 2001-2100, not 2000-2099.
+                *
+                * If a 4-digit year is provided, we use that and ignore CC.
+                */
+               if (tmfc.cc && tmfc.yysz <= 2)
                {
-                       /*
-                        * CC and Y defined
-                        */
-                       tm->tm_year = (tmfc.cc - 1) * 100 + tmfc.year - 2000;
+                       tm->tm_year = tmfc.year % 100;
+                       if (tm->tm_year)
+                               tm->tm_year += (tmfc.cc - 1) * 100;
+                       else
+                               tm->tm_year = tmfc.cc * 100;
                }
                else
-                       /* set year (and ignore CC if defined) */
                        tm->tm_year = tmfc.year;
        }
+       else if (tmfc.cc)                       /* use first year of century */
+               tm->tm_year = (tmfc.cc - 1) * 100 + 1;
+
        if (tmfc.bc)
        {
                if (tm->tm_year > 0)
index c145279e73e9013ef267463cf0fc900fd385867f..c26cb9ec99382fc266228ef6ad2b995e9eb6b43e 100644 (file)
@@ -867,11 +867,11 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
            | 1,997 1997 997 97 7 20 2 06 23 161 10 3 2450610
            | 2,001 2001 001 01 1 21 3 09 38 265 22 7 2452175
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
@@ -912,8 +912,8 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
            | 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813
            | 1,997 1997 997 97 7 20 4 12 53 365 31 4 2450814
            | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544
-           | 2,000 2000 000 00 0 21 1 01 01 001 01 7 2451545
-           | 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910
+           | 2,000 2000 000 00 0 20 1 01 01 001 01 7 2451545
+           | 2,000 2000 000 00 0 20 4 12 53 366 31 1 2451910
            | 2,001 2001 001 01 1 21 1 01 01 001 01 2 2451911
 (65 rows)
 
@@ -938,11 +938,11 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
            | 1,997 1997 997 97 7 20 2 6 23 161 10 3 2450610
            | 2,001 2001 001 01 1 21 3 9 38 265 22 7 2452175
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
@@ -983,8 +983,8 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
            | 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813
            | 1,997 1997 997 97 7 20 4 12 53 365 31 4 2450814
            | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544
-           | 2,000 2000 000 00 0 21 1 1 1 1 1 7 2451545
-           | 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910
+           | 2,000 2000 000 00 0 20 1 1 1 1 1 7 2451545
+           | 2,000 2000 000 00 0 20 4 12 53 366 31 1 2451910
            | 2,001 2001 001 01 1 21 1 1 1 1 1 2 2451911
 (65 rows)
 
index 4a17503324d5f10c0eb8f815a60288e8dae24e19..be3d7bed5d1edc949765eb0c95ab5676eb6f9f2d 100644 (file)
@@ -887,11 +887,11 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
            | 1,997 1997 997 97 7 20 2 06 23 161 10 3 2450610
            | 2,001 2001 001 01 1 21 3 09 38 265 22 7 2452175
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 03 11 075 15 4 2451619
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
            | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
@@ -933,8 +933,8 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
            | 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813
            | 1,997 1997 997 97 7 20 4 12 53 365 31 4 2450814
            | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544
-           | 2,000 2000 000 00 0 21 1 01 01 001 01 7 2451545
-           | 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910
+           | 2,000 2000 000 00 0 20 1 01 01 001 01 7 2451545
+           | 2,000 2000 000 00 0 20 4 12 53 366 31 1 2451910
            | 2,001 2001 001 01 1 21 1 01 01 001 01 2 2451911
 (66 rows)
 
@@ -960,11 +960,11 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
            | 1,997 1997 997 97 7 20 2 6 23 161 10 3 2450610
            | 2,001 2001 001 01 1 21 3 9 38 265 22 7 2452175
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
-           | 2,000 2000 000 00 0 21 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
+           | 2,000 2000 000 00 0 20 1 3 11 75 15 4 2451619
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
            | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
@@ -1006,8 +1006,8 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
            | 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813
            | 1,997 1997 997 97 7 20 4 12 53 365 31 4 2450814
            | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544
-           | 2,000 2000 000 00 0 21 1 1 1 1 1 7 2451545
-           | 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910
+           | 2,000 2000 000 00 0 20 1 1 1 1 1 7 2451545
+           | 2,000 2000 000 00 0 20 4 12 53 366 31 1 2451910
            | 2,001 2001 001 01 1 21 1 1 1 1 1 2 2451911
 (66 rows)