Fix to_date to behave reasonably when CC and YY fields are both used.
Karel Zak
This commit is contained in:
parent
c90578a1d6
commit
6e26c00297
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.241 2005/03/14 18:31:19 momjian Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.242 2005/03/25 16:08:39 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@ -4470,6 +4470,17 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
In conversions from string to <type>timestamp</type> or
|
||||||
|
<type>date</type>, the <literal>CC</literal> field is ignored if there
|
||||||
|
is a <literal>YYY</literal>, <literal>YYYY</literal> or
|
||||||
|
<literal>Y,YYY</literal> field. If <literal>CC</literal> is used with
|
||||||
|
<literal>YY</literal> or <literal>Y</literal> then the year is computed
|
||||||
|
as <literal>(CC-1)*100+YY</literal>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Millisecond (<literal>MS</literal>) and microsecond (<literal>US</literal>)
|
Millisecond (<literal>MS</literal>) and microsecond (<literal>US</literal>)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
* formatting.c
|
* formatting.c
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.84 2005/01/13 01:40:13 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.85 2005/03/25 16:08:40 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
|
||||||
|
@ -379,7 +379,8 @@ typedef struct
|
||||||
cc,
|
cc,
|
||||||
q,
|
q,
|
||||||
j,
|
j,
|
||||||
us;
|
us,
|
||||||
|
yysz; /* is it YY or YYYY ? */
|
||||||
} TmFromChar;
|
} TmFromChar;
|
||||||
|
|
||||||
#define ZERO_tmfc( _X ) memset(_X, 0, sizeof(TmFromChar))
|
#define ZERO_tmfc( _X ) memset(_X, 0, sizeof(TmFromChar))
|
||||||
|
@ -390,11 +391,11 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG_TO_FROM_CHAR
|
#ifdef DEBUG_TO_FROM_CHAR
|
||||||
#define DEBUG_TMFC( _X ) \
|
#define DEBUG_TMFC( _X ) \
|
||||||
elog(DEBUG_elog_output, "TMFC:\nhh %d\nam %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nms: %d\nyear %d\nbc %d\niw %d\nww %d\nw %d\ncc %d\nq %d\nj %d\nus: %d", \
|
elog(DEBUG_elog_output, "TMFC:\nhh %d\nam %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nms: %d\nyear %d\nbc %d\niw %d\nww %d\nw %d\ncc %d\nq %d\nj %d\nus: %d\nyysz: %d", \
|
||||||
(_X)->hh, (_X)->am, (_X)->pm, (_X)->mi, (_X)->ss, \
|
(_X)->hh, (_X)->am, (_X)->pm, (_X)->mi, (_X)->ss, \
|
||||||
(_X)->ssss, (_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, \
|
(_X)->ssss, (_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, \
|
||||||
(_X)->year, (_X)->bc, (_X)->iw, (_X)->ww, (_X)->w, \
|
(_X)->year, (_X)->bc, (_X)->iw, (_X)->ww, (_X)->w, \
|
||||||
(_X)->cc, (_X)->q, (_X)->j, (_X)->us);
|
(_X)->cc, (_X)->q, (_X)->j, (_X)->us, (_X)->yysz);
|
||||||
#define DEBUG_TM( _X ) \
|
#define DEBUG_TM( _X ) \
|
||||||
elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
|
elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
|
||||||
(_X)->tm_sec, (_X)->tm_year,\
|
(_X)->tm_sec, (_X)->tm_year,\
|
||||||
|
@ -2463,7 +2464,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
|
||||||
|
|
||||||
sscanf(inout, "%d,%03d", &cc, &tmfc->year);
|
sscanf(inout, "%d,%03d", &cc, &tmfc->year);
|
||||||
tmfc->year += (cc * 1000);
|
tmfc->year += (cc * 1000);
|
||||||
|
tmfc->yysz = 4;
|
||||||
return strdigits_len(inout) + 3 + SKIP_THth(suf);
|
return strdigits_len(inout) + 3 + SKIP_THth(suf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2497,11 +2498,13 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
|
||||||
if (S_FM(suf) || is_next_separator(node))
|
if (S_FM(suf) || is_next_separator(node))
|
||||||
{
|
{
|
||||||
sscanf(inout, "%d", &tmfc->year);
|
sscanf(inout, "%d", &tmfc->year);
|
||||||
|
tmfc->yysz = 4;
|
||||||
return strdigits_len(inout) - 1 + SKIP_THth(suf);
|
return strdigits_len(inout) - 1 + SKIP_THth(suf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sscanf(inout, "%04d", &tmfc->year);
|
sscanf(inout, "%04d", &tmfc->year);
|
||||||
|
tmfc->yysz = 4;
|
||||||
return 3 + SKIP_THth(suf);
|
return 3 + SKIP_THth(suf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2537,7 +2540,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
|
||||||
tmfc->year += 1000;
|
tmfc->year += 1000;
|
||||||
else
|
else
|
||||||
tmfc->year += 2000;
|
tmfc->year += 2000;
|
||||||
|
tmfc->yysz = 3;
|
||||||
return 2 + SKIP_THth(suf);
|
return 2 + SKIP_THth(suf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2572,7 +2575,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
|
||||||
tmfc->year += 2000;
|
tmfc->year += 2000;
|
||||||
else
|
else
|
||||||
tmfc->year += 1900;
|
tmfc->year += 1900;
|
||||||
|
tmfc->yysz = 2;
|
||||||
return 1 + SKIP_THth(suf);
|
return 1 + SKIP_THth(suf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2603,7 +2606,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
|
||||||
* 1-digit year: always +2000
|
* 1-digit year: always +2000
|
||||||
*/
|
*/
|
||||||
tmfc->year += 2000;
|
tmfc->year += 2000;
|
||||||
|
tmfc->yysz = 1;
|
||||||
return 0 + SKIP_THth(suf);
|
return 0 + SKIP_THth(suf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3171,8 +3174,24 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmfc.year)
|
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)
|
||||||
|
{
|
||||||
|
/* CC and Y defined
|
||||||
|
*/
|
||||||
|
tm->tm_year = (tmfc.cc-1)*100 + tmfc.year-2000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* set year (and ignore CC if defined) */
|
||||||
tm->tm_year = tmfc.year;
|
tm->tm_year = tmfc.year;
|
||||||
|
}
|
||||||
if (tmfc.bc)
|
if (tmfc.bc)
|
||||||
{
|
{
|
||||||
if (tm->tm_year > 0)
|
if (tm->tm_year > 0)
|
||||||
|
|
Loading…
Reference in New Issue