here is a patch for formatting.c (to_char/timestampt()), for 7.1

it fixing Y,YY,YYY,YYYY conversion, the docs and regress tests update
 are included too.

  During the patch testing I found small bug in miscadmin.h in
convertstr() declaration. Here it's fixed too.

 Thanks

        Karel
This commit is contained in:
Bruce Momjian 2000-11-25 05:00:33 +00:00
parent 91ba4cc761
commit 3f1998727d
5 changed files with 242 additions and 100 deletions

View File

@ -962,6 +962,20 @@
keyword (example: <literal>'"Hello Year: "YYYY'</literal>). keyword (example: <literal>'"Hello Year: "YYYY'</literal>).
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<literal>YYYY</literal> conversion from string to timestamp or
date is limited if you use year great than 4-digits. You must
use after <literal>YYYY</literal> some non-digit char or template
else year is always interpreted as 4-digits. For example (with year
20000):
<literal> to_date('200001131', 'YYYYMMDD') <literal> will bad
interpreded as 4-digits year, right is use after year non-digit
separator <literal> to_date('20000-1131', 'YYYY-MMDD')<literal> or
<literal> to_date('20000Nov31', 'YYYYMonDD')<literal>.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</para> </para>

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
* formatting.c * formatting.c
* *
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.23 2000/10/29 13:17:34 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.24 2000/11/25 05:00:29 momjian Exp $
* *
* *
* Portions Copyright (c) 1999-2000, PostgreSQL, Inc * Portions Copyright (c) 1999-2000, PostgreSQL, Inc
@ -127,6 +127,7 @@ typedef struct
int len, /* keyword length */ int len, /* keyword length */
(*action) (), (*action) (),
id; /* keyword id */ id; /* keyword id */
bool isdigit; /* is expected output/input digit */
} KeyWord; } KeyWord;
typedef struct typedef struct
@ -344,14 +345,16 @@ static int NUMCounter = 0;
* ---------- * ----------
*/ */
typedef struct { typedef struct {
int hh, am, pm, mi, ss, ssss, d, dd, ddd, mm, yyyy, bc, iw, ww, w, cc, q, j; int hh, am, pm, mi, ss, ssss, d, dd, ddd, mm, yyyy, yyy, yy, y,
bc, iw, ww, w, cc, q, j;
} TmFromChar; } TmFromChar;
#define ZERO_tmfc( _X ) \ #define ZERO_tmfc( _X ) \
do { \ do { \
(_X)->hh= (_X)->am= (_X)->pm= (_X)->mi= (_X)->ss= (_X)->ssss= \ (_X)->hh= (_X)->am= (_X)->pm= (_X)->mi= (_X)->ss= (_X)->ssss= \
(_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->bc= \ (_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->yyy= \
(_X)->iw= (_X)->ww= (_X)->w= (_X)->cc= (_X)->q= (_X)->j= 0; \ (_X)->yy= (_X)->y= (_X)->bc= (_X)->iw= (_X)->ww= (_X)->w= \
(_X)->cc= (_X)->q= (_X)->j= 0; \
} while(0) } while(0)
#ifdef DEBUG_TO_FROM_CHAR #ifdef DEBUG_TO_FROM_CHAR
@ -453,7 +456,7 @@ static KeySuffix DCH_suff[] = {
* it is not good. * it is not good.
* *
* (!) * (!)
* Position for the keyword is simular as position in the enum DCH/NUM_poz * - Position for the keyword is simular as position in the enum DCH/NUM_poz.
* (!) * (!)
* *
* For fast search is used the 'int index[]', index is ascii table from position * For fast search is used the 'int index[]', index is ascii table from position
@ -598,88 +601,88 @@ typedef enum
* ---------- * ----------
*/ */
static KeyWord DCH_keywords[] = { static KeyWord DCH_keywords[] = {
/* keyword,len,func.type is in Index */ /* keyword, len, func, type, isdigit is in Index */
{"A.D.", 4, dch_date, DCH_A_D}, /* A */ {"A.D.", 4, dch_date, DCH_A_D, FALSE}, /* A */
{"A.M.", 4, dch_time, DCH_A_M}, {"A.M.", 4, dch_time, DCH_A_M, FALSE},
{"AD", 2, dch_date, DCH_AD}, {"AD", 2, dch_date, DCH_AD, FALSE},
{"AM", 2, dch_time, DCH_AM}, {"AM", 2, dch_time, DCH_AM, FALSE},
{"B.C.", 4, dch_date, DCH_B_C}, /* B */ {"B.C.", 4, dch_date, DCH_B_C, FALSE}, /* B */
{"BC", 2, dch_date, DCH_BC}, {"BC", 2, dch_date, DCH_BC, FALSE},
{"CC", 2, dch_date, DCH_CC}, /* C */ {"CC", 2, dch_date, DCH_CC, TRUE}, /* C */
{"DAY", 3, dch_date, DCH_DAY}, /* D */ {"DAY", 3, dch_date, DCH_DAY, FALSE}, /* D */
{"DDD", 3, dch_date, DCH_DDD}, {"DDD", 3, dch_date, DCH_DDD, TRUE},
{"DD", 2, dch_date, DCH_DD}, {"DD", 2, dch_date, DCH_DD, TRUE},
{"DY", 2, dch_date, DCH_DY}, {"DY", 2, dch_date, DCH_DY, FALSE},
{"Day", 3, dch_date, DCH_Day}, {"Day", 3, dch_date, DCH_Day, FALSE},
{"Dy", 2, dch_date, DCH_Dy}, {"Dy", 2, dch_date, DCH_Dy, FALSE},
{"D", 1, dch_date, DCH_D}, {"D", 1, dch_date, DCH_D, TRUE},
{"FX", 2, dch_global, DCH_FX}, /* F */ {"FX", 2, dch_global, DCH_FX, FALSE}, /* F */
{"HH24", 4, dch_time, DCH_HH24}, /* H */ {"HH24", 4, dch_time, DCH_HH24, TRUE}, /* H */
{"HH12", 4, dch_time, DCH_HH12}, {"HH12", 4, dch_time, DCH_HH12, TRUE},
{"HH", 2, dch_time, DCH_HH}, {"HH", 2, dch_time, DCH_HH, TRUE},
{"IW", 2, dch_date, DCH_IW}, /* I */ {"IW", 2, dch_date, DCH_IW, TRUE}, /* I */
{"J", 1, dch_date, DCH_J}, /* J */ {"J", 1, dch_date, DCH_J, TRUE}, /* J */
{"MI", 2, dch_time, DCH_MI}, {"MI", 2, dch_time, DCH_MI, TRUE},
{"MM", 2, dch_date, DCH_MM}, {"MM", 2, dch_date, DCH_MM, TRUE},
{"MONTH", 5, dch_date, DCH_MONTH}, {"MONTH", 5, dch_date, DCH_MONTH, FALSE},
{"MON", 3, dch_date, DCH_MON}, {"MON", 3, dch_date, DCH_MON, FALSE},
{"Month", 5, dch_date, DCH_Month}, {"Month", 5, dch_date, DCH_Month, FALSE},
{"Mon", 3, dch_date, DCH_Mon}, {"Mon", 3, dch_date, DCH_Mon, FALSE},
{"P.M.", 4, dch_time, DCH_P_M}, /* P */ {"P.M.", 4, dch_time, DCH_P_M, FALSE}, /* P */
{"PM", 2, dch_time, DCH_PM}, {"PM", 2, dch_time, DCH_PM, FALSE},
{"Q", 1, dch_date, DCH_Q}, /* Q */ {"Q", 1, dch_date, DCH_Q, TRUE}, /* Q */
{"RM", 2, dch_date, DCH_RM}, /* R */ {"RM", 2, dch_date, DCH_RM, FALSE}, /* R */
{"SSSS", 4, dch_time, DCH_SSSS}, /* S */ {"SSSS", 4, dch_time, DCH_SSSS, TRUE}, /* S */
{"SS", 2, dch_time, DCH_SS}, {"SS", 2, dch_time, DCH_SS, TRUE},
{"TZ", 2, dch_time, DCH_TZ}, /* T */ {"TZ", 2, dch_time, DCH_TZ, FALSE}, /* T */
{"WW", 2, dch_date, DCH_WW}, /* W */ {"WW", 2, dch_date, DCH_WW, TRUE}, /* W */
{"W", 1, dch_date, DCH_W}, {"W", 1, dch_date, DCH_W, TRUE},
{"Y,YYY", 5, dch_date, DCH_Y_YYY}, /* Y */ {"Y,YYY", 5, dch_date, DCH_Y_YYY, TRUE}, /* Y */
{"YYYY", 4, dch_date, DCH_YYYY}, {"YYYY", 4, dch_date, DCH_YYYY, TRUE},
{"YYY", 3, dch_date, DCH_YYY}, {"YYY", 3, dch_date, DCH_YYY, TRUE},
{"YY", 2, dch_date, DCH_YY}, {"YY", 2, dch_date, DCH_YY, TRUE},
{"Y", 1, dch_date, DCH_Y}, {"Y", 1, dch_date, DCH_Y, TRUE},
{"a.d.", 4, dch_date, DCH_a_d}, /* a */ {"a.d.", 4, dch_date, DCH_a_d, FALSE}, /* a */
{"a.m.", 4, dch_time, DCH_a_m}, {"a.m.", 4, dch_time, DCH_a_m, FALSE},
{"ad", 2, dch_date, DCH_ad}, {"ad", 2, dch_date, DCH_ad, FALSE},
{"am", 2, dch_time, DCH_am}, {"am", 2, dch_time, DCH_am, FALSE},
{"b.c.", 4, dch_date, DCH_b_c}, /* b */ {"b.c.", 4, dch_date, DCH_b_c, FALSE}, /* b */
{"bc", 2, dch_date, DCH_bc}, {"bc", 2, dch_date, DCH_bc, FALSE},
{"cc", 2, dch_date, DCH_CC}, /* c */ {"cc", 2, dch_date, DCH_CC, TRUE}, /* c */
{"day", 3, dch_date, DCH_day}, /* d */ {"day", 3, dch_date, DCH_day, FALSE}, /* d */
{"ddd", 3, dch_date, DCH_DDD}, {"ddd", 3, dch_date, DCH_DDD, TRUE},
{"dd", 2, dch_date, DCH_DD}, {"dd", 2, dch_date, DCH_DD, TRUE},
{"dy", 2, dch_date, DCH_dy}, {"dy", 2, dch_date, DCH_dy, FALSE},
{"d", 1, dch_date, DCH_D}, {"d", 1, dch_date, DCH_D, TRUE},
{"fx", 2, dch_global, DCH_FX}, /* f */ {"fx", 2, dch_global, DCH_FX, FALSE}, /* f */
{"hh24", 4, dch_time, DCH_HH24}, /* h */ {"hh24", 4, dch_time, DCH_HH24, TRUE}, /* h */
{"hh12", 4, dch_time, DCH_HH12}, {"hh12", 4, dch_time, DCH_HH12, TRUE},
{"hh", 2, dch_time, DCH_HH}, {"hh", 2, dch_time, DCH_HH, TRUE},
{"iw", 2, dch_date, DCH_IW}, /* i */ {"iw", 2, dch_date, DCH_IW, TRUE}, /* i */
{"j", 1, dch_time, DCH_J}, /* j */ {"j", 1, dch_time, DCH_J, TRUE}, /* j */
{"mi", 2, dch_time, DCH_MI}, /* m */ {"mi", 2, dch_time, DCH_MI, TRUE}, /* m */
{"mm", 2, dch_date, DCH_MM}, {"mm", 2, dch_date, DCH_MM, TRUE},
{"month", 5, dch_date, DCH_month}, {"month", 5, dch_date, DCH_month, FALSE},
{"mon", 3, dch_date, DCH_mon}, {"mon", 3, dch_date, DCH_mon, FALSE},
{"p.m.", 4, dch_time, DCH_p_m}, /* p */ {"p.m.", 4, dch_time, DCH_p_m, FALSE}, /* p */
{"pm", 2, dch_time, DCH_pm}, {"pm", 2, dch_time, DCH_pm, FALSE},
{"q", 1, dch_date, DCH_Q}, /* q */ {"q", 1, dch_date, DCH_Q, TRUE}, /* q */
{"rm", 2, dch_date, DCH_rm}, /* r */ {"rm", 2, dch_date, DCH_rm, FALSE}, /* r */
{"ssss", 4, dch_time, DCH_SSSS}, /* s */ {"ssss", 4, dch_time, DCH_SSSS, TRUE}, /* s */
{"ss", 2, dch_time, DCH_SS}, {"ss", 2, dch_time, DCH_SS, TRUE},
{"tz", 2, dch_time, DCH_tz}, /* t */ {"tz", 2, dch_time, DCH_tz, FALSE}, /* t */
{"ww", 2, dch_date, DCH_WW}, /* w */ {"ww", 2, dch_date, DCH_WW, TRUE}, /* w */
{"w", 1, dch_date, DCH_W}, {"w", 1, dch_date, DCH_W, TRUE},
{"y,yyy", 5, dch_date, DCH_Y_YYY}, /* y */ {"y,yyy", 5, dch_date, DCH_Y_YYY, TRUE}, /* y */
{"yyyy", 4, dch_date, DCH_YYYY}, {"yyyy", 4, dch_date, DCH_YYYY, TRUE},
{"yyy", 3, dch_date, DCH_YYY}, {"yyy", 3, dch_date, DCH_YYY, TRUE},
{"yy", 2, dch_date, DCH_YY}, {"yy", 2, dch_date, DCH_YY, TRUE},
{"y", 1, dch_date, DCH_Y}, {"y", 1, dch_date, DCH_Y, TRUE},
/* last */ /* last */
{NULL, 0, NULL, 0}}; {NULL, 0, NULL, 0}};
/* ---------- /* ----------
* KeyWords for NUMBER version * KeyWords for NUMBER version (now, isdigit info is not needful here..)
* ---------- * ----------
*/ */
static KeyWord NUM_keywords[] = { static KeyWord NUM_keywords[] = {
@ -1230,7 +1233,7 @@ DCH_processor(FormatNode *node, char *inout, int flag)
* Skip blank space in FROM_CHAR's input * Skip blank space in FROM_CHAR's input
* ---------- * ----------
*/ */
if (isspace(n->character) && IS_FX == 0) if (isspace(n->character) && IS_FX == 0)
{ {
while (*s != '\0' && isspace((int) *(s + 1))) while (*s != '\0' && isspace((int) *(s + 1)))
++s; ++s;
@ -1526,6 +1529,40 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
return -1; return -1;
} }
/* ----------
* Return TRUE if next format picture is not digit value
* ----------
*/
static bool
is_next_separator(FormatNode *n)
{
if (n->type == NODE_TYPE_END)
return FALSE;
if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
return TRUE;
/*
* Next node
*/
n++;
if (n->type == NODE_TYPE_END)
return FALSE;
if (n->type == NODE_TYPE_ACTION)
{
if (n->key->isdigit)
return FALSE;
return TRUE;
}
else if (isdigit(n->character))
return FALSE;
return TRUE; /* some non-digit input (separator) */
}
#define AMPM_ERROR elog(ERROR, "to_timestamp(): bad AM/PM string") #define AMPM_ERROR elog(ERROR, "to_timestamp(): bad AM/PM string")
/* ---------- /* ----------
@ -1736,7 +1773,10 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
sscanf(inout, "%d", &tmfc->ssss); if (is_next_separator(node))
sscanf(inout, "%d", &tmfc->ssss);
else
sscanf(inout, "%05d", &tmfc->ssss);
return int4len((int4) tmfc->ssss) - 1 + SKIP_THth(suf); return int4len((int4) tmfc->ssss) - 1 + SKIP_THth(suf);
} }
break; break;
@ -2192,7 +2232,11 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
sscanf(inout, "%d", &tmfc->yyyy); if (is_next_separator(node))
sscanf(inout, "%d", &tmfc->yyyy);
else
sscanf(inout, "%04d", &tmfc->yyyy);
if (!S_FM(suf) && tmfc->yyyy <= 9999 && tmfc->yyyy >= -9999) if (!S_FM(suf) && tmfc->yyyy <= 9999 && tmfc->yyyy >= -9999)
len = 4; len = 4;
else else
@ -2217,7 +2261,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
sscanf(inout, "%03d", &tmfc->yyyy); sscanf(inout, "%03d", &tmfc->yyy);
return 2 + SKIP_THth(suf); return 2 + SKIP_THth(suf);
} }
break; break;
@ -2237,7 +2281,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
sscanf(inout, "%02d", &tmfc->yyyy); sscanf(inout, "%02d", &tmfc->yy);
return 1 + SKIP_THth(suf); return 1 + SKIP_THth(suf);
} }
break; break;
@ -2257,7 +2301,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
sscanf(inout, "%1d", &tmfc->yyyy); sscanf(inout, "%1d", &tmfc->y);
return 0 + SKIP_THth(suf); return 0 + SKIP_THth(suf);
} }
break; break;
@ -2725,16 +2769,56 @@ to_timestamp(PG_FUNCTION_ARGS)
if (tmfc->yyyy) if (tmfc->yyyy)
tm->tm_year = tmfc->yyyy; tm->tm_year = tmfc->yyyy;
else if (tmfc->y)
{
/*
* 1-digit year:
* always +2000
*/
tm->tm_year = tmfc->y + 2000;
}
else if (tmfc->yy)
{
/*
* 2-digit year:
* '00' ... '69' = 2000 ... 2069
* '70' ... '99' = 1970 ... 1999
*/
tm->tm_year = tmfc->yy;
if (tm->tm_year < 70)
tm->tm_year += 2000;
else
tm->tm_year += 1900;
}
else if (tmfc->yyy)
{
/*
* 3-digit year:
* '100' ... '999' = 1100 ... 1999
* '000' ... '099' = 2000 ... 2099
*/
tm->tm_year = tmfc->yyy;
if (tm->tm_year >= 100)
tm->tm_year += 1000;
else
tm->tm_year += 2000;
}
if (tmfc->bc)
{
if (tm->tm_year > 0)
tm->tm_year = -(tm->tm_year - 1);
else
elog(ERROR, "Inconsistant use of year %04d and 'BC'", tm->tm_year);
}
if (tmfc->j) if (tmfc->j)
j2date(tmfc->j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); j2date(tmfc->j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
if (tmfc->bc && tm->tm_year > 0)
tm->tm_year = -(tm->tm_year);
if (tm->tm_year < 0)
tm->tm_year = tm->tm_year + 1;
if (tmfc->iw) if (tmfc->iw)
isoweek2date(tmfc->iw, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); isoweek2date(tmfc->iw, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: miscadmin.h,v 1.72 2000/11/21 21:16:04 petere Exp $ * $Id: miscadmin.h,v 1.73 2000/11/25 05:00:30 momjian Exp $
* *
* NOTES * NOTES
* some of the information in this file will be moved to * some of the information in this file will be moved to
@ -142,7 +142,7 @@ extern int FindExec(char *full_path, const char *argv0, const char *binary_name)
extern int CheckPathAccess(char *path, char *name, int open_mode); extern int CheckPathAccess(char *path, char *name, int open_mode);
#ifdef CYR_RECODE #ifdef CYR_RECODE
extern char *convertstr(char *, int, int); extern char *convertstr(unsigned char *buff, int len, int dest);
#endif #endif
/***************************************************************************** /*****************************************************************************

View File

@ -1560,9 +1560,9 @@ SELECT '' AS to_timestamp_5, to_timestamp('1,582nd VIII 21', 'Y,YYYth FMRM DD');
SELECT '' AS to_timestamp_6, to_timestamp('15 "text bettween quote marks" 98 54 45', SELECT '' AS to_timestamp_6, to_timestamp('15 "text bettween quote marks" 98 54 45',
'HH "\\text bettween quote marks\\"" YY MI SS'); 'HH "\\text bettween quote marks\\"" YY MI SS');
to_timestamp_6 | to_timestamp to_timestamp_6 | to_timestamp
----------------+-------------------------- ----------------+------------------------------
| Wed Jan 01 15:54:45 0098 | Thu Jan 01 15:54:45 1998 PST
(1 row) (1 row)
@ -1578,4 +1578,36 @@ SELECT '' AS to_timestamp_8, to_timestamp('2000January09Sunday', 'YYYYFMMonthDDF
| Sun Jan 09 00:00:00 2000 PST | Sun Jan 09 00:00:00 2000 PST
(1 row) (1 row)
SELECT '' AS to_timestamp_9, to_timestamp('97/Feb/16', 'YYMonDD');
ERROR: to_timestamp(): bad value for MON/Mon/mon
SELECT '' AS to_timestamp_10, to_timestamp('19971116', 'YYYYMMDD');
to_timestamp_10 | to_timestamp
-----------------+------------------------------
| Sun Nov 16 00:00:00 1997 PST
(1 row)
SELECT '' AS to_timestamp_11, to_timestamp('20000-1116', 'YYYY-MMDD');
to_timestamp_11 | to_timestamp
-----------------+---------------------------
| Thu Nov 16 00:00:00 20000
(1 row)
SELECT '' AS to_timestamp_12, to_timestamp('9-1116', 'Y-MMDD');
to_timestamp_12 | to_timestamp
-----------------+------------------------------
| Mon Nov 16 00:00:00 2009 PST
(1 row)
SELECT '' AS to_timestamp_13, to_timestamp('95-1116', 'YY-MMDD');
to_timestamp_13 | to_timestamp
-----------------+------------------------------
| Thu Nov 16 00:00:00 1995 PST
(1 row)
SELECT '' AS to_timestamp_14, to_timestamp('995-1116', 'YYY-MMDD');
to_timestamp_14 | to_timestamp
-----------------+------------------------------
| Thu Nov 16 00:00:00 1995 PST
(1 row)
SET DateStyle TO DEFAULT; SET DateStyle TO DEFAULT;

View File

@ -223,4 +223,16 @@ SELECT '' AS to_timestamp_7, to_timestamp('05121445482000', 'MMDDHHMISSYYYY');
SELECT '' AS to_timestamp_8, to_timestamp('2000January09Sunday', 'YYYYFMMonthDDFMDay'); SELECT '' AS to_timestamp_8, to_timestamp('2000January09Sunday', 'YYYYFMMonthDDFMDay');
SELECT '' AS to_timestamp_9, to_timestamp('97/Feb/16', 'YYMonDD');
SELECT '' AS to_timestamp_10, to_timestamp('19971116', 'YYYYMMDD');
SELECT '' AS to_timestamp_11, to_timestamp('20000-1116', 'YYYY-MMDD');
SELECT '' AS to_timestamp_12, to_timestamp('9-1116', 'Y-MMDD');
SELECT '' AS to_timestamp_13, to_timestamp('95-1116', 'YY-MMDD');
SELECT '' AS to_timestamp_14, to_timestamp('995-1116', 'YYY-MMDD');
SET DateStyle TO DEFAULT; SET DateStyle TO DEFAULT;