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

Commit 7f28c63

Browse files
author
Nikita Glukhov
committed
Add TZH and TZM timezone format fields for to_timestamp()
1 parent 92087ec commit 7f28c63

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,10 @@ typedef struct
426426
j,
427427
us,
428428
yysz, /* is it YY or YYYY ? */
429-
clock; /* 12 or 24 hour clock? */
429+
clock, /* 12 or 24 hour clock? */
430+
tzsign,
431+
tzh,
432+
tzm;
430433
} TmFromChar;
431434

432435
#define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
@@ -472,6 +475,7 @@ do { \
472475
(_X)->tm_sec = (_X)->tm_year = (_X)->tm_min = (_X)->tm_wday = \
473476
(_X)->tm_hour = (_X)->tm_yday = (_X)->tm_isdst = 0; \
474477
(_X)->tm_mday = (_X)->tm_mon = 1; \
478+
(_X)->tm_zone = NULL; \
475479
} while(0)
476480

477481
#define ZERO_tmtc(_X) \
@@ -611,6 +615,8 @@ typedef enum
611615
DCH_RM,
612616
DCH_SSSS,
613617
DCH_SS,
618+
DCH_TZH,
619+
DCH_TZM,
614620
DCH_TZ,
615621
DCH_US,
616622
DCH_WW,
@@ -758,7 +764,9 @@ static const KeyWord DCH_keywords[] = {
758764
{"RM", 2, DCH_RM, FALSE, FROM_CHAR_DATE_GREGORIAN}, /* R */
759765
{"SSSS", 4, DCH_SSSS, TRUE, FROM_CHAR_DATE_NONE}, /* S */
760766
{"SS", 2, DCH_SS, TRUE, FROM_CHAR_DATE_NONE},
761-
{"TZ", 2, DCH_TZ, FALSE, FROM_CHAR_DATE_NONE}, /* T */
767+
{"TZH", 3, DCH_TZH, FALSE, FROM_CHAR_DATE_NONE}, /* T */
768+
{"TZM", 3, DCH_TZM, TRUE, FROM_CHAR_DATE_NONE},
769+
{"TZ", 2, DCH_TZ, FALSE, FROM_CHAR_DATE_NONE},
762770
{"US", 2, DCH_US, TRUE, FROM_CHAR_DATE_NONE}, /* U */
763771
{"WW", 2, DCH_WW, TRUE, FROM_CHAR_DATE_GREGORIAN}, /* W */
764772
{"W", 1, DCH_W, TRUE, FROM_CHAR_DATE_GREGORIAN},
@@ -881,7 +889,7 @@ static const int DCH_index[KeyWord_INDEX_SIZE] = {
881889
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
882890
-1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
883891
DCH_FX, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, DCH_OF,
884-
DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZ, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
892+
DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZH, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
885893
-1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
886894
DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
887895
-1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, DCH_us, -1, DCH_ww,
@@ -2529,6 +2537,13 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25292537
s += strlen(s);
25302538
}
25312539
break;
2540+
case DCH_TZH:
2541+
case DCH_TZM:
2542+
ereport(ERROR,
2543+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2544+
errmsg("formatting field \"%s\" is only supported in "
2545+
"to_timestamp", n->key->name)));
2546+
break;
25322547
case DCH_OF:
25332548
INVALID_FOR_INTERVAL;
25342549
sprintf(s, "%c%0*d",
@@ -3080,6 +3095,19 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
30803095
errmsg("formatting field \"%s\" is only supported in to_char",
30813096
n->key->name)));
30823097
break;
3098+
case DCH_TZH:
3099+
out->tzsign = *s == '-' ? -1 : +1;
3100+
3101+
if (*s == '+' || *s == '-' || *s == ' ')
3102+
s++;
3103+
3104+
from_char_parse_int_len(&out->tzh, &s, 2, n);
3105+
break;
3106+
case DCH_TZM:
3107+
if (!out->tzsign)
3108+
out->tzsign = +1;
3109+
from_char_parse_int_len(&out->tzm, &s, 2, n);
3110+
break;
30833111
case DCH_A_D:
30843112
case DCH_B_C:
30853113
case DCH_a_d:
@@ -3545,8 +3573,15 @@ to_timestamp(PG_FUNCTION_ARGS)
35453573
fsec_t fsec;
35463574

35473575
do_to_timestamp(date_txt, fmt, &tm, &fsec);
3576+
if (tm.tm_zone)
3577+
{
3578+
int dterr = DecodeTimezone((char *) tm.tm_zone, &tz);
35483579

3549-
tz = DetermineTimeZoneOffset(&tm, session_timezone);
3580+
if (dterr)
3581+
DateTimeParseError(dterr, text_to_cstring(date_txt), "timestamptz");
3582+
}
3583+
else
3584+
tz = DetermineTimeZoneOffset(&tm, session_timezone);
35503585

35513586
if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
35523587
ereport(ERROR,
@@ -3868,6 +3903,22 @@ do_to_timestamp(text *date_txt, text *fmt,
38683903
*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
38693904
DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
38703905

3906+
if (tmfc.tzsign)
3907+
{
3908+
char *tz;
3909+
3910+
if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
3911+
tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
3912+
DateTimeParseError(DTERR_TZDISP_OVERFLOW, date_str, "timestamp");
3913+
3914+
tz = palloc(7);
3915+
3916+
snprintf(tz, 7, "%c%02d:%02d",
3917+
tmfc.tzsign > 0 ? '+' : '-', tmfc.tzh, tmfc.tzm);
3918+
3919+
tm->tm_zone = tz;
3920+
}
3921+
38713922
DEBUG_TM(tm);
38723923

38733924
pfree(date_str);

src/test/regress/expected/horology.out

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2930,6 +2930,36 @@ SELECT to_timestamp('2011-12-18 11:38 PM', 'YYYY-MM-DD HH12:MI PM');
29302930
Sun Dec 18 23:38:00 2011 PST
29312931
(1 row)
29322932

2933+
SELECT to_timestamp('2011-12-18 11:38 +05', 'YYYY-MM-DD HH12:MI TZH');
2934+
to_timestamp
2935+
------------------------------
2936+
Sat Dec 17 22:38:00 2011 PST
2937+
(1 row)
2938+
2939+
SELECT to_timestamp('2011-12-18 11:38 -05', 'YYYY-MM-DD HH12:MI TZH');
2940+
to_timestamp
2941+
------------------------------
2942+
Sun Dec 18 08:38:00 2011 PST
2943+
(1 row)
2944+
2945+
SELECT to_timestamp('2011-12-18 11:38 +05:20', 'YYYY-MM-DD HH12:MI TZH:TZM');
2946+
to_timestamp
2947+
------------------------------
2948+
Sat Dec 17 22:18:00 2011 PST
2949+
(1 row)
2950+
2951+
SELECT to_timestamp('2011-12-18 11:38 -05:20', 'YYYY-MM-DD HH12:MI TZH:TZM');
2952+
to_timestamp
2953+
------------------------------
2954+
Sun Dec 18 08:58:00 2011 PST
2955+
(1 row)
2956+
2957+
SELECT to_timestamp('2011-12-18 11:38 20', 'YYYY-MM-DD HH12:MI TZM');
2958+
to_timestamp
2959+
------------------------------
2960+
Sun Dec 18 03:18:00 2011 PST
2961+
(1 row)
2962+
29332963
--
29342964
-- Check handling of multiple spaces in format and/or input
29352965
--

src/test/regress/sql/horology.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@ SELECT to_timestamp(' 20050302', 'YYYYMMDD');
446446
SELECT to_timestamp('2011-12-18 11:38 AM', 'YYYY-MM-DD HH12:MI PM');
447447
SELECT to_timestamp('2011-12-18 11:38 PM', 'YYYY-MM-DD HH12:MI PM');
448448

449+
SELECT to_timestamp('2011-12-18 11:38 +05', 'YYYY-MM-DD HH12:MI TZH');
450+
SELECT to_timestamp('2011-12-18 11:38 -05', 'YYYY-MM-DD HH12:MI TZH');
451+
SELECT to_timestamp('2011-12-18 11:38 +05:20', 'YYYY-MM-DD HH12:MI TZH:TZM');
452+
SELECT to_timestamp('2011-12-18 11:38 -05:20', 'YYYY-MM-DD HH12:MI TZH:TZM');
453+
SELECT to_timestamp('2011-12-18 11:38 20', 'YYYY-MM-DD HH12:MI TZM');
454+
449455
--
450456
-- Check handling of multiple spaces in format and/or input
451457
--

0 commit comments

Comments
 (0)