diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 7617642f20..b9cd00320b 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,4 +1,4 @@ - + Functions and Operators @@ -4617,7 +4617,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); CC - century component of year (minimum 2 digits) + century (2 digits) (The twenty-first century starts on 2001-01-01.) J diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 664942ffdb..66fc77e6a8 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.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) + /* + * 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 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) - { - /* - * 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)