aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/formatting.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2011-09-07 09:47:51 -0400
committerBruce Momjian <bruce@momjian.us>2011-09-07 09:47:51 -0400
commit029dfdf1157b6d837a7b7211cd35b00c6bcd767c (patch)
treefacdd79b00acf28c37c48762e56f3d4afc246b39 /src/backend/utils/adt/formatting.c
parent8eacb25cbe9100b9cf441d4cbca4cec8fa5e3f52 (diff)
downloadpostgresql-029dfdf1157b6d837a7b7211cd35b00c6bcd767c.tar.gz
postgresql-029dfdf1157b6d837a7b7211cd35b00c6bcd767c.zip
Fix to_date() and to_timestamp() to handle year masks of length < 4 so
they wrap toward year 2020, rather than the inconsistent behavior we had before.
Diffstat (limited to 'src/backend/utils/adt/formatting.c')
-rw-r--r--src/backend/utils/adt/formatting.c58
1 files changed, 32 insertions, 26 deletions
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 726a1f45523..7efd9883628 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -964,6 +964,7 @@ static void dump_node(FormatNode *node, int max);
static char *get_th(char *num, int type);
static char *str_numth(char *dest, char *num, int type);
+static int adjust_partial_year_to_2020(int year);
static int strspace_len(char *str);
static int strdigits_len(char *str);
static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode);
@@ -1968,6 +1969,31 @@ is_next_separator(FormatNode *n)
return TRUE; /* some non-digit input (separator) */
}
+
+static int
+adjust_partial_year_to_2020(int year)
+{
+ /*
+ * Adjust all dates toward 2020; this is effectively what happens
+ * when we assume '70' is 1970 and '69' is 2069.
+ */
+ /* Force 0-69 into the 2000's */
+ if (year < 70)
+ return year + 2000;
+ /* Force 70-99 into the 1900's */
+ else if (year >= 70 && year < 100)
+ return year + 1900;
+ /* Force 100-519 into the 2000's */
+ else if (year >= 100 && year < 519)
+ return year + 2000;
+ /* Force 520-999 into the 1000's */
+ else if (year >= 520 && year < 1000)
+ return year + 1000;
+ else
+ return year;
+}
+
+
static int
strspace_len(char *str)
{
@@ -2930,43 +2956,23 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
break;
case DCH_YYY:
case DCH_IYY:
- from_char_parse_int(&out->year, &s, n);
+ if (from_char_parse_int(&out->year, &s, n) < 4)
+ out->year = adjust_partial_year_to_2020(out->year);
out->yysz = 3;
-
- /*
- * 3-digit year: '100' ... '999' = 1100 ... 1999 '000' ...
- * '099' = 2000 ... 2099
- */
- if (out->year >= 100)
- out->year += 1000;
- else
- out->year += 2000;
s += SKIP_THth(n->suffix);
break;
case DCH_YY:
case DCH_IY:
- from_char_parse_int(&out->year, &s, n);
+ if (from_char_parse_int(&out->year, &s, n) < 4)
+ out->year = adjust_partial_year_to_2020(out->year);
out->yysz = 2;
-
- /*
- * 2-digit year: '00' ... '69' = 2000 ... 2069 '70' ... '99'
- * = 1970 ... 1999
- */
- if (out->year < 70)
- out->year += 2000;
- else
- out->year += 1900;
s += SKIP_THth(n->suffix);
break;
case DCH_Y:
case DCH_I:
- from_char_parse_int(&out->year, &s, n);
+ if (from_char_parse_int(&out->year, &s, n) < 4)
+ out->year = adjust_partial_year_to_2020(out->year);
out->yysz = 1;
-
- /*
- * 1-digit year: always +2000
- */
- out->year += 2000;
s += SKIP_THth(n->suffix);
break;
case DCH_RM: