mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Fix to_char(), to_date(), and to_timestamp() to handle negative/BC
century specifications just like positive/AD centuries. Previously the behavior was either wrong or inconsistent with positive/AD handling. Centuries without years now always assume the first year of the century, which is now documented.
This commit is contained in:
parent
fbcfa90bb8
commit
ac78c4178b
@ -5575,7 +5575,9 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
|||||||
if there is a <literal>YYY</literal>, <literal>YYYY</literal> or
|
if there is a <literal>YYY</literal>, <literal>YYYY</literal> or
|
||||||
<literal>Y,YYY</literal> field. If <literal>CC</literal> is used with
|
<literal>Y,YYY</literal> field. If <literal>CC</literal> is used with
|
||||||
<literal>YY</literal> or <literal>Y</literal> then the year is computed
|
<literal>YY</literal> or <literal>Y</literal> then the year is computed
|
||||||
as <literal>(CC-1)*100+YY</literal>.
|
as the year in the specified century. If the century is
|
||||||
|
specified but the year is not, the first year of the century
|
||||||
|
is assumed.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
@ -2640,8 +2640,15 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
|
|||||||
case DCH_CC:
|
case DCH_CC:
|
||||||
if (is_interval) /* straight calculation */
|
if (is_interval) /* straight calculation */
|
||||||
i = tm->tm_year / 100;
|
i = tm->tm_year / 100;
|
||||||
else /* century 21 starts in 2001 */
|
else
|
||||||
i = (tm->tm_year - 1) / 100 + 1;
|
{
|
||||||
|
if (tm->tm_year > 0)
|
||||||
|
/* Century 20 == 1901 - 2000 */
|
||||||
|
i = (tm->tm_year - 1) / 100 + 1;
|
||||||
|
else
|
||||||
|
/* Century 6BC == 600BC - 501BC */
|
||||||
|
i = tm->tm_year / 100 - 1;
|
||||||
|
}
|
||||||
if (i <= 99 && i >= -99)
|
if (i <= 99 && i >= -99)
|
||||||
sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, i);
|
sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, i);
|
||||||
else
|
else
|
||||||
@ -3465,33 +3472,41 @@ do_to_timestamp(text *date_txt, text *fmt,
|
|||||||
/*
|
/*
|
||||||
* If CC and YY (or Y) are provided, use YY as 2 low-order digits for
|
* 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
|
* the year in the given century. Keep in mind that the 21st century
|
||||||
* runs from 2001-2100, not 2000-2099.
|
* AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
|
||||||
*
|
* 600BC to 501BC.
|
||||||
* If a 4-digit year is provided, we use that and ignore CC.
|
|
||||||
*/
|
*/
|
||||||
if (tmfc.cc && tmfc.yysz <= 2)
|
if (tmfc.cc && tmfc.yysz <= 2)
|
||||||
{
|
{
|
||||||
|
if (tmfc.bc)
|
||||||
|
tmfc.cc = -tmfc.cc;
|
||||||
tm->tm_year = tmfc.year % 100;
|
tm->tm_year = tmfc.year % 100;
|
||||||
if (tm->tm_year)
|
if (tm->tm_year)
|
||||||
tm->tm_year += (tmfc.cc - 1) * 100;
|
{
|
||||||
|
if (tmfc.cc >= 0)
|
||||||
|
tm->tm_year += (tmfc.cc - 1) * 100;
|
||||||
|
else
|
||||||
|
tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
tm->tm_year = tmfc.cc * 100;
|
/* find century year for dates ending in "00" */
|
||||||
|
tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
/* If a 4-digit year is provided, we use that and ignore CC. */
|
||||||
|
{
|
||||||
tm->tm_year = tmfc.year;
|
tm->tm_year = tmfc.year;
|
||||||
|
if (tmfc.bc && tm->tm_year > 0)
|
||||||
|
tm->tm_year = -(tm->tm_year - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (tmfc.cc) /* use first year of century */
|
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)
|
if (tmfc.bc)
|
||||||
tm->tm_year = -(tm->tm_year - 1);
|
tmfc.cc = -tmfc.cc;
|
||||||
|
if (tmfc.cc >= 0)
|
||||||
|
tm->tm_year = (tmfc.cc - 1) * 100 + 1;
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
tm->tm_year = tmfc.cc * 100 + 1;
|
||||||
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
|
||||||
errmsg("inconsistent use of year %04d and \"BC\"",
|
|
||||||
tm->tm_year)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmfc.j)
|
if (tmfc.j)
|
||||||
|
@ -992,7 +992,7 @@ 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 07 045 14 6 2450494
|
| 1,997 1997 997 97 7 20 1 02 07 045 14 6 2450494
|
||||||
| 1,997 1997 997 97 7 20 1 02 07 046 15 7 2450495
|
| 1,997 1997 997 97 7 20 1 02 07 046 15 7 2450495
|
||||||
| 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496
|
| 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496
|
||||||
| 0,097 0097 097 97 7 01 1 02 07 047 16 3 1686042
|
| 0,097 0097 097 97 7 -1 1 02 07 047 16 3 1686042
|
||||||
| 0,097 0097 097 97 7 01 1 02 07 047 16 7 1756536
|
| 0,097 0097 097 97 7 01 1 02 07 047 16 7 1756536
|
||||||
| 0,597 0597 597 97 7 06 1 02 07 047 16 5 1939157
|
| 0,597 0597 597 97 7 06 1 02 07 047 16 5 1939157
|
||||||
| 1,097 1097 097 97 7 11 1 02 07 047 16 3 2121778
|
| 1,097 1097 097 97 7 11 1 02 07 047 16 3 2121778
|
||||||
@ -1063,7 +1063,7 @@ 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 7 45 14 6 2450494
|
| 1,997 1997 997 97 7 20 1 2 7 45 14 6 2450494
|
||||||
| 1,997 1997 997 97 7 20 1 2 7 46 15 7 2450495
|
| 1,997 1997 997 97 7 20 1 2 7 46 15 7 2450495
|
||||||
| 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496
|
| 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496
|
||||||
| 0,097 97 97 97 7 1 1 2 7 47 16 3 1686042
|
| 0,097 97 97 97 7 -1 1 2 7 47 16 3 1686042
|
||||||
| 0,097 97 97 97 7 1 1 2 7 47 16 7 1756536
|
| 0,097 97 97 97 7 1 1 2 7 47 16 7 1756536
|
||||||
| 0,597 597 597 97 7 6 1 2 7 47 16 5 1939157
|
| 0,597 597 597 97 7 6 1 2 7 47 16 5 1939157
|
||||||
| 1,097 1097 97 97 7 11 1 2 7 47 16 3 2121778
|
| 1,097 1097 97 97 7 11 1 2 7 47 16 3 2121778
|
||||||
|
@ -1074,7 +1074,7 @@ 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 07 045 14 6 2450494
|
| 1,997 1997 997 97 7 20 1 02 07 045 14 6 2450494
|
||||||
| 1,997 1997 997 97 7 20 1 02 07 046 15 7 2450495
|
| 1,997 1997 997 97 7 20 1 02 07 046 15 7 2450495
|
||||||
| 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496
|
| 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496
|
||||||
| 0,097 0097 097 97 7 01 1 02 07 047 16 3 1686042
|
| 0,097 0097 097 97 7 -1 1 02 07 047 16 3 1686042
|
||||||
| 0,097 0097 097 97 7 01 1 02 07 047 16 7 1756536
|
| 0,097 0097 097 97 7 01 1 02 07 047 16 7 1756536
|
||||||
| 0,597 0597 597 97 7 06 1 02 07 047 16 5 1939157
|
| 0,597 0597 597 97 7 06 1 02 07 047 16 5 1939157
|
||||||
| 1,097 1097 097 97 7 11 1 02 07 047 16 3 2121778
|
| 1,097 1097 097 97 7 11 1 02 07 047 16 3 2121778
|
||||||
@ -1146,7 +1146,7 @@ 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 7 45 14 6 2450494
|
| 1,997 1997 997 97 7 20 1 2 7 45 14 6 2450494
|
||||||
| 1,997 1997 997 97 7 20 1 2 7 46 15 7 2450495
|
| 1,997 1997 997 97 7 20 1 2 7 46 15 7 2450495
|
||||||
| 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496
|
| 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496
|
||||||
| 0,097 97 97 97 7 1 1 2 7 47 16 3 1686042
|
| 0,097 97 97 97 7 -1 1 2 7 47 16 3 1686042
|
||||||
| 0,097 97 97 97 7 1 1 2 7 47 16 7 1756536
|
| 0,097 97 97 97 7 1 1 2 7 47 16 7 1756536
|
||||||
| 0,597 597 597 97 7 6 1 2 7 47 16 5 1939157
|
| 0,597 597 597 97 7 6 1 2 7 47 16 5 1939157
|
||||||
| 1,097 1097 97 97 7 11 1 2 7 47 16 3 2121778
|
| 1,097 1097 97 97 7 11 1 2 7 47 16 3 2121778
|
||||||
|
Loading…
Reference in New Issue
Block a user