Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7778ddc

Browse files
committed
Allow 5+ digit years for non-ISO timestamp/date strings, where appropriate
Report from Haribabu Kommi
1 parent d41ab71 commit 7778ddc

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

src/backend/utils/adt/datetime.c

+25-24
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,17 @@ DecodeDateTime(char **field, int *ftype, int nf,
11611161
if (dterr < 0)
11621162
return dterr;
11631163
}
1164-
else if (flen > 4)
1164+
/*
1165+
* Is this a YMD or HMS specification, or a year number?
1166+
* YMD and HMS are required to be six digits or more, so
1167+
* if it is 5 digits, it is a year. If it is six or more
1168+
* more digits, we assume it is YMD or HMS unless no date
1169+
* and no time values have been specified. This forces
1170+
* 6+ digit years to be at the end of the string, or to use
1171+
* the ISO date specification.
1172+
*/
1173+
else if (flen >= 6 && (!(fmask & DTK_DATE_M) ||
1174+
!(fmask & DTK_TIME_M)))
11651175
{
11661176
dterr = DecodeNumberField(flen, field[i], fmask,
11671177
&tmask, tm,
@@ -2647,29 +2657,20 @@ DecodeNumberField(int len, char *str, int fmask,
26472657
/* No decimal point and no complete date yet? */
26482658
else if ((fmask & DTK_DATE_M) != DTK_DATE_M)
26492659
{
2650-
/* yyyymmdd? */
2651-
if (len == 8)
2652-
{
2653-
*tmask = DTK_DATE_M;
2654-
2655-
tm->tm_mday = atoi(str + 6);
2656-
*(str + 6) = '\0';
2657-
tm->tm_mon = atoi(str + 4);
2658-
*(str + 4) = '\0';
2659-
tm->tm_year = atoi(str + 0);
2660-
2661-
return DTK_DATE;
2662-
}
2663-
/* yymmdd? */
2664-
else if (len == 6)
2660+
if (len >= 6)
26652661
{
26662662
*tmask = DTK_DATE_M;
2667-
tm->tm_mday = atoi(str + 4);
2668-
*(str + 4) = '\0';
2669-
tm->tm_mon = atoi(str + 2);
2670-
*(str + 2) = '\0';
2671-
tm->tm_year = atoi(str + 0);
2672-
*is2digits = TRUE;
2663+
/*
2664+
* Start from end and consider first 2 as Day, next 2 as Month,
2665+
* and the rest as Year.
2666+
*/
2667+
tm->tm_mday = atoi(str + (len - 2));
2668+
*(str + (len - 2)) = '\0';
2669+
tm->tm_mon = atoi(str + (len - 4));
2670+
*(str + (len - 4)) = '\0';
2671+
tm->tm_year = atoi(str);
2672+
if ((len - 4) == 2)
2673+
*is2digits = TRUE;
26732674

26742675
return DTK_DATE;
26752676
}
@@ -2686,7 +2687,7 @@ DecodeNumberField(int len, char *str, int fmask,
26862687
*(str + 4) = '\0';
26872688
tm->tm_min = atoi(str + 2);
26882689
*(str + 2) = '\0';
2689-
tm->tm_hour = atoi(str + 0);
2690+
tm->tm_hour = atoi(str);
26902691

26912692
return DTK_TIME;
26922693
}
@@ -2697,7 +2698,7 @@ DecodeNumberField(int len, char *str, int fmask,
26972698
tm->tm_sec = 0;
26982699
tm->tm_min = atoi(str + 2);
26992700
*(str + 2) = '\0';
2700-
tm->tm_hour = atoi(str + 0);
2701+
tm->tm_hour = atoi(str);
27012702

27022703
return DTK_TIME;
27032704
}

src/test/regress/expected/timestamptz.out

+22
Original file line numberDiff line numberDiff line change
@@ -1675,3 +1675,25 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
16751675
| 2001 1 1 1 1 1 1
16761676
(66 rows)
16771677

1678+
CREATE TABLE TIMESTAMPTZ_TST (a int , b timestamptz);
1679+
-- Test year field value with len > 4
1680+
INSERT INTO TIMESTAMPTZ_TST VALUES(1, 'Sat Mar 12 23:58:48 1000 IST');
1681+
INSERT INTO TIMESTAMPTZ_TST VALUES(2, 'Sat Mar 12 23:58:48 10000 IST');
1682+
INSERT INTO TIMESTAMPTZ_TST VALUES(3, 'Sat Mar 12 23:58:48 100000 IST');
1683+
INSERT INTO TIMESTAMPTZ_TST VALUES(3, '10000 Mar 12 23:58:48 IST');
1684+
INSERT INTO TIMESTAMPTZ_TST VALUES(4, '100000312 23:58:48 IST');
1685+
INSERT INTO TIMESTAMPTZ_TST VALUES(4, '1000000312 23:58:48 IST');
1686+
--Verify data
1687+
SELECT * FROM TIMESTAMPTZ_TST ORDER BY a;
1688+
a | b
1689+
---+--------------------------------
1690+
1 | Wed Mar 12 13:58:48 1000 PST
1691+
2 | Sun Mar 12 14:58:48 10000 PDT
1692+
3 | Sun Mar 12 14:58:48 100000 PDT
1693+
3 | Sun Mar 12 14:58:48 10000 PDT
1694+
4 | Sun Mar 12 14:58:48 10000 PDT
1695+
4 | Sun Mar 12 14:58:48 100000 PDT
1696+
(6 rows)
1697+
1698+
--Cleanup
1699+
DROP TABLE TIMESTAMPTZ_TST;

src/test/regress/sql/timestamptz.sql

+14
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,17 @@ SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
240240

241241
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
242242
FROM TIMESTAMPTZ_TBL;
243+
244+
CREATE TABLE TIMESTAMPTZ_TST (a int , b timestamptz);
245+
246+
-- Test year field value with len > 4
247+
INSERT INTO TIMESTAMPTZ_TST VALUES(1, 'Sat Mar 12 23:58:48 1000 IST');
248+
INSERT INTO TIMESTAMPTZ_TST VALUES(2, 'Sat Mar 12 23:58:48 10000 IST');
249+
INSERT INTO TIMESTAMPTZ_TST VALUES(3, 'Sat Mar 12 23:58:48 100000 IST');
250+
INSERT INTO TIMESTAMPTZ_TST VALUES(3, '10000 Mar 12 23:58:48 IST');
251+
INSERT INTO TIMESTAMPTZ_TST VALUES(4, '100000312 23:58:48 IST');
252+
INSERT INTO TIMESTAMPTZ_TST VALUES(4, '1000000312 23:58:48 IST');
253+
--Verify data
254+
SELECT * FROM TIMESTAMPTZ_TST ORDER BY a;
255+
--Cleanup
256+
DROP TABLE TIMESTAMPTZ_TST;

0 commit comments

Comments
 (0)