summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-01-12 23:35:04 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-01-12 23:35:04 +0000
commit65fe39ee0a72c898d09097196654c53b77b2080d (patch)
tree47f5e50578f6561e40bb6a9776f71ae740270267
parentc483632d25c4788eecf7d99fc4297864e72d19aa (diff)
downloadpostgresql-65fe39ee0a72c898d09097196654c53b77b2080d.tar.gz
Fix handling of CC (century) format spec in to_date/to_char. According to
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.
-rw-r--r--doc/src/sgml/func.sgml4
-rw-r--r--src/backend/utils/adt/formatting.c39
-rw-r--r--src/test/regress/expected/timestamp.out28
-rw-r--r--src/test/regress/expected/timestamptz.out28
4 files changed, 51 insertions, 48 deletions
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 1e092c4ce7..5f7a8322f7 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.347 2006/11/25 00:38:53 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.347.2.1 2007/01/12 23:35:03 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 (2 digits)</entry>
+ <entry>century (2 digits) (The twenty-first century starts on 2001-01-01.)</entry>
</row>
<row>
<entry><literal>J</literal></entry>
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 2e1a5ac3eb..cb6a109bf4 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
* formatting.c
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.116 2006/11/28 12:53:44 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.116.2.1 2007/01/12 23:35:03 tgl Exp $
*
*
* Portions Copyright (c) 1999-2006, 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)
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index c145279e73..c26cb9ec99 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -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)
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 4a17503324..be3d7bed5d 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -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)