Skip to content

Commit 18aee79

Browse files
committed
Allow timezone names in SQL strings,
'2006-05-24 21:11 Americas/New_York'::timestamptz Joachim Wieland
1 parent 51dfe35 commit 18aee79

File tree

1 file changed

+66
-5
lines changed

1 file changed

+66
-5
lines changed

src/backend/utils/adt/datetime.c

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.166 2006/03/05 15:58:41 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.167 2006/06/07 22:32:31 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -22,6 +22,7 @@
2222

2323
#include "access/xact.h"
2424
#include "miscadmin.h"
25+
#include "utils/builtins.h"
2526
#include "utils/datetime.h"
2627
#include "utils/guc.h"
2728

@@ -36,6 +37,7 @@ static int DecodeTime(char *str, int fmask, int *tmask,
3637
struct pg_tm * tm, fsec_t *fsec);
3738
static int DecodeTimezone(char *str, int *tzp);
3839
static int DecodePosixTimezone(char *str, int *tzp);
40+
static int DecodeZicTimezone(char *str, int *tzp, struct pg_tm * tm);
3941
static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
4042
static int DecodeDate(char *str, int fmask, int *tmask, struct pg_tm * tm);
4143
static void TrimTrailingZeros(char *str);
@@ -888,8 +890,24 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
888890
{
889891
char delim = *cp;
890892

891-
ftype[nf] = DTK_DATE;
892-
APPEND_CHAR(bufp, bufend, *cp++);
893+
if (*cp == '/')
894+
{
895+
ftype[nf] = DTK_TZ;
896+
/* set the first character of the region to upper case
897+
* again*/
898+
field[nf][0] = pg_toupper((unsigned char) field[nf][0]);
899+
/* we have seen "Region/" of a POSIX timezone, continue to
900+
* read the City part */
901+
do {
902+
APPEND_CHAR(bufp, bufend, *cp++);
903+
/* there is for example America/New_York */
904+
} while (isalpha((unsigned char) *cp) || *cp == '_');
905+
}
906+
else
907+
{
908+
ftype[nf] = DTK_DATE;
909+
APPEND_CHAR(bufp, bufend, *cp++);
910+
}
893911
while (isdigit((unsigned char) *cp) || *cp == delim)
894912
APPEND_CHAR(bufp, bufend, *cp++);
895913
}
@@ -980,6 +998,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
980998
bool haveTextMonth = FALSE;
981999
int is2digits = FALSE;
9821000
int bc = FALSE;
1001+
int zicTzFnum = -1;
9831002

9841003
/*
9851004
* We'll insist on at least all of the date fields, but initialize the
@@ -1127,7 +1146,15 @@ DecodeDateTime(char **field, int *ftype, int nf,
11271146
if (tzp == NULL)
11281147
return DTERR_BAD_FORMAT;
11291148

1130-
dterr = DecodeTimezone(field[i], &tz);
1149+
if (strchr(field[i], '/') != NULL)
1150+
{
1151+
/* remember to apply the timezone at the end */
1152+
zicTzFnum = i;
1153+
tmask = DTK_M(TZ);
1154+
break;
1155+
}
1156+
else
1157+
dterr = DecodeTimezone(field[i], &tz);
11311158
if (dterr)
11321159
return dterr;
11331160

@@ -1605,6 +1632,19 @@ DecodeDateTime(char **field, int *ftype, int nf,
16051632
if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
16061633
return DTERR_FIELD_OVERFLOW;
16071634

1635+
if (zicTzFnum != -1)
1636+
{
1637+
Datum tsTz;
1638+
Timestamp timestamp;
1639+
tm2timestamp(tm, *fsec, NULL, &timestamp);
1640+
tsTz = DirectFunctionCall2(timestamp_zone,
1641+
DirectFunctionCall1(textin,
1642+
CStringGetDatum(field[zicTzFnum])),
1643+
TimestampGetDatum(timestamp));
1644+
timestamp2tm(DatumGetTimestampTz(tsTz), tzp, tm, fsec, NULL, NULL);
1645+
fmask &= ~DTK_M(TZ);
1646+
}
1647+
16081648
/* timezone not specified? then find local timezone if possible */
16091649
if (tzp != NULL && !(fmask & DTK_M(TZ)))
16101650
{
@@ -1874,7 +1914,15 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
18741914
if (tzp == NULL)
18751915
return DTERR_BAD_FORMAT;
18761916

1877-
dterr = DecodeTimezone(field[i], &tz);
1917+
if (strchr(field[i], '/') != NULL)
1918+
{
1919+
/* a date has to be specified */
1920+
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1921+
return DTERR_BAD_FORMAT;
1922+
dterr = DecodeZicTimezone(field[i], &tz, tm);
1923+
}
1924+
else
1925+
dterr = DecodeTimezone(field[i], &tz);
18781926
if (dterr)
18791927
return dterr;
18801928

@@ -2924,6 +2972,19 @@ DecodePosixTimezone(char *str, int *tzp)
29242972
return 0;
29252973
}
29262974

2975+
static int
2976+
DecodeZicTimezone(char *str, int *tzp, struct pg_tm * tm)
2977+
{
2978+
struct pg_tz *tz;
2979+
2980+
tz = pg_tzset(str);
2981+
if (!tz)
2982+
return DTERR_BAD_FORMAT;
2983+
2984+
*tzp = DetermineTimeZoneOffset(tm, tz);
2985+
2986+
return 0;
2987+
}
29272988

29282989
/* DecodeSpecial()
29292990
* Decode text string using lookup table.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy