Fix assorted breakage in to_char()'s OF format option.
In HEAD, fix incorrect field width for hours part of OF when tm_gmtoff is negative. This was introduced by commit 2d87eedc1d4468d3 as a result of falsely applying a pattern that's correct when + signs are omitted, which is not the case for OF. In 9.4, fix missing abs() call that allowed a sign to be attached to the minutes part of OF. This was fixed in 9.5 by 9b43d73b3f9bef27, but for inscrutable reasons not back-patched. In all three versions, ensure that the sign of tm_gmtoff is correctly reported even when the GMT offset is less than 1 hour. Add regression tests, which evidently we desperately need here. Thomas Munro and Tom Lane, per report from David Fetter
This commit is contained in:
parent
f4ceed6ceb
commit
55c3a04d60
@ -2506,12 +2506,15 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
|
|||||||
break;
|
break;
|
||||||
case DCH_OF:
|
case DCH_OF:
|
||||||
INVALID_FOR_INTERVAL;
|
INVALID_FOR_INTERVAL;
|
||||||
sprintf(s, "%+0*d", S_FM(n->suffix) ? 0 : (tm->tm_gmtoff >= 0) ? 3 : 4,
|
sprintf(s, "%c%0*d",
|
||||||
(int) tm->tm_gmtoff / SECS_PER_HOUR);
|
(tm->tm_gmtoff >= 0) ? '+' : '-',
|
||||||
|
S_FM(n->suffix) ? 0 : 2,
|
||||||
|
abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
if ((int) tm->tm_gmtoff % SECS_PER_HOUR != 0)
|
if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
|
||||||
{
|
{
|
||||||
sprintf(s, ":%02d", abs((int) tm->tm_gmtoff % SECS_PER_HOUR) / SECS_PER_MINUTE);
|
sprintf(s, ":%02d",
|
||||||
|
(abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1699,6 +1699,57 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
|||||||
| 2001 1 1 1 1 1 1
|
| 2001 1 1 1 1 1 1
|
||||||
(66 rows)
|
(66 rows)
|
||||||
|
|
||||||
|
-- Check OF with various zone offsets, particularly fractional hours
|
||||||
|
SET timezone = '00:00';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
+00
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET timezone = '+02:00';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
-02
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET timezone = '-13:00';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
+13
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET timezone = '-00:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
+00:30
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET timezone = '00:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
-00:30
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET timezone = '-04:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
+04:30
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET timezone = '04:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
to_char
|
||||||
|
---------
|
||||||
|
-04:30
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
RESET timezone;
|
||||||
CREATE TABLE TIMESTAMPTZ_TST (a int , b timestamptz);
|
CREATE TABLE TIMESTAMPTZ_TST (a int , b timestamptz);
|
||||||
-- Test year field value with len > 4
|
-- Test year field value with len > 4
|
||||||
INSERT INTO TIMESTAMPTZ_TST VALUES(1, 'Sat Mar 12 23:58:48 1000 IST');
|
INSERT INTO TIMESTAMPTZ_TST VALUES(1, 'Sat Mar 12 23:58:48 1000 IST');
|
||||||
|
@ -248,6 +248,23 @@ SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
|
|||||||
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
||||||
FROM TIMESTAMPTZ_TBL;
|
FROM TIMESTAMPTZ_TBL;
|
||||||
|
|
||||||
|
-- Check OF with various zone offsets, particularly fractional hours
|
||||||
|
SET timezone = '00:00';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
SET timezone = '+02:00';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
SET timezone = '-13:00';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
SET timezone = '-00:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
SET timezone = '00:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
SET timezone = '-04:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
SET timezone = '04:30';
|
||||||
|
SELECT to_char(now(), 'OF');
|
||||||
|
RESET timezone;
|
||||||
|
|
||||||
CREATE TABLE TIMESTAMPTZ_TST (a int , b timestamptz);
|
CREATE TABLE TIMESTAMPTZ_TST (a int , b timestamptz);
|
||||||
|
|
||||||
-- Test year field value with len > 4
|
-- Test year field value with len > 4
|
||||||
|
Loading…
x
Reference in New Issue
Block a user