Skip to content

Commit bb2bff4

Browse files
committed
Fix to_timestamp/to_date so that zero year input for Y, YY, or YYY
formats will be taken as 2000, not year zero. Per bug report from Aasmund Midttun Godal. Fix from Karel Zak.
1 parent e274325 commit bb2bff4

File tree

1 file changed

+41
-56
lines changed

1 file changed

+41
-56
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 41 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.47 2001/12/10 15:34:05 tgl Exp $
4+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.48 2002/01/02 22:09:23 tgl Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
@@ -371,10 +371,7 @@ typedef struct
371371
ddd,
372372
mm,
373373
ms,
374-
yyyy,
375-
yyy,
376-
yy,
377-
y,
374+
year,
378375
bc,
379376
iw,
380377
ww,
@@ -393,10 +390,10 @@ typedef struct
393390
*/
394391
#ifdef DEBUG_TO_FROM_CHAR
395392
#define DEBUG_TMFC( _X ) \
396-
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\nyyyy %d\nbc %d\niw %d\nww %d\nw %d\ncc %d\nq %d\nj %d\nus: %d", \
393+
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", \
397394
(_X)->hh, (_X)->am, (_X)->pm, (_X)->mi, (_X)->ss, \
398395
(_X)->ssss, (_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, \
399-
(_X)->yyyy, (_X)->bc, (_X)->iw, (_X)->ww, (_X)->w, \
396+
(_X)->year, (_X)->bc, (_X)->iw, (_X)->ww, (_X)->w, \
400397
(_X)->cc, (_X)->q, (_X)->j, (_X)->us);
401398
#define DEBUG_TM( _X ) \
402399
elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
@@ -2396,8 +2393,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
23962393
{
23972394
int cc;
23982395

2399-
sscanf(inout, "%d,%03d", &cc, &tmfc->yyyy);
2400-
tmfc->yyyy += (cc * 1000);
2396+
sscanf(inout, "%d,%03d", &cc, &tmfc->year);
2397+
tmfc->year += (cc * 1000);
24012398

24022399
return strdigits_len(inout) + 3 + SKIP_THth(suf);
24032400
}
@@ -2417,12 +2414,12 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
24172414
{
24182415
if (S_FM(suf) || is_next_separator(node))
24192416
{
2420-
sscanf(inout, "%d", &tmfc->yyyy);
2417+
sscanf(inout, "%d", &tmfc->year);
24212418
return strdigits_len(inout) - 1 + SKIP_THth(suf);
24222419
}
24232420
else
24242421
{
2425-
sscanf(inout, "%04d", &tmfc->yyyy);
2422+
sscanf(inout, "%04d", &tmfc->year);
24262423
return 3 + SKIP_THth(suf);
24272424
}
24282425
}
@@ -2443,7 +2440,18 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
24432440
}
24442441
else if (flag == FROM_CHAR)
24452442
{
2446-
sscanf(inout, "%03d", &tmfc->yyy);
2443+
sscanf(inout, "%03d", &tmfc->year);
2444+
2445+
/*
2446+
* 3-digit year:
2447+
* '100' ... '999' = 1100 ... 1999
2448+
* '000' ... '099' = 2000 ... 2099
2449+
*/
2450+
if (tmfc->year >= 100)
2451+
tmfc->year += 1000;
2452+
else
2453+
tmfc->year += 2000;
2454+
24472455
return 2 + SKIP_THth(suf);
24482456
}
24492457
break;
@@ -2463,7 +2471,18 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
24632471
}
24642472
else if (flag == FROM_CHAR)
24652473
{
2466-
sscanf(inout, "%02d", &tmfc->yy);
2474+
sscanf(inout, "%02d", &tmfc->year);
2475+
2476+
/*
2477+
* 2-digit year:
2478+
* '00' ... '69' = 2000 ... 2069
2479+
* '70' ... '99' = 1970 ... 1999
2480+
*/
2481+
if (tmfc->year < 70)
2482+
tmfc->year += 2000;
2483+
else
2484+
tmfc->year += 1900;
2485+
24672486
return 1 + SKIP_THth(suf);
24682487
}
24692488
break;
@@ -2483,7 +2502,13 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
24832502
}
24842503
else if (flag == FROM_CHAR)
24852504
{
2486-
sscanf(inout, "%1d", &tmfc->y);
2505+
sscanf(inout, "%1d", &tmfc->year);
2506+
2507+
/*
2508+
* 1-digit year: always +2000
2509+
*/
2510+
tmfc->year += 2000;
2511+
24872512
return 0 + SKIP_THth(suf);
24882513
}
24892514
break;
@@ -3002,48 +3027,8 @@ to_timestamp(PG_FUNCTION_ARGS)
30023027
break;
30033028
}
30043029

3005-
if (tmfc.yyyy)
3006-
tm.tm_year = tmfc.yyyy;
3007-
3008-
else if (tmfc.y)
3009-
{
3010-
/*
3011-
* 1-digit year: always +2000
3012-
*/
3013-
tm.tm_year = tmfc.y + 2000;
3014-
}
3015-
else if (tmfc.yy)
3016-
{
3017-
3018-
/*---------
3019-
* 2-digit year:
3020-
* '00' ... '69' = 2000 ... 2069
3021-
* '70' ... '99' = 1970 ... 1999
3022-
*---------
3023-
*/
3024-
tm.tm_year = tmfc.yy;
3025-
3026-
if (tm.tm_year < 70)
3027-
tm.tm_year += 2000;
3028-
else
3029-
tm.tm_year += 1900;
3030-
}
3031-
else if (tmfc.yyy)
3032-
{
3033-
3034-
/*---------
3035-
* 3-digit year:
3036-
* '100' ... '999' = 1100 ... 1999
3037-
* '000' ... '099' = 2000 ... 2099
3038-
*---------
3039-
*/
3040-
tm.tm_year = tmfc.yyy;
3041-
3042-
if (tm.tm_year >= 100)
3043-
tm.tm_year += 1000;
3044-
else
3045-
tm.tm_year += 2000;
3046-
}
3030+
if (tmfc.year)
3031+
tm.tm_year = tmfc.year;
30473032

30483033
if (tmfc.bc)
30493034
{

0 commit comments

Comments
 (0)