8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
22
22
23
23
#include "access/xact.h"
24
24
#include "miscadmin.h"
25
+ #include "utils/builtins.h"
25
26
#include "utils/datetime.h"
26
27
#include "utils/guc.h"
27
28
@@ -36,6 +37,7 @@ static int DecodeTime(char *str, int fmask, int *tmask,
36
37
struct pg_tm * tm , fsec_t * fsec );
37
38
static int DecodeTimezone (char * str , int * tzp );
38
39
static int DecodePosixTimezone (char * str , int * tzp );
40
+ static int DecodeZicTimezone (char * str , int * tzp , struct pg_tm * tm );
39
41
static datetkn * datebsearch (char * key , datetkn * base , unsigned int nel );
40
42
static int DecodeDate (char * str , int fmask , int * tmask , struct pg_tm * tm );
41
43
static void TrimTrailingZeros (char * str );
@@ -888,8 +890,24 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
888
890
{
889
891
char delim = * cp ;
890
892
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
+ }
893
911
while (isdigit ((unsigned char ) * cp ) || * cp == delim )
894
912
APPEND_CHAR (bufp , bufend , * cp ++ );
895
913
}
@@ -980,6 +998,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
980
998
bool haveTextMonth = FALSE;
981
999
int is2digits = FALSE;
982
1000
int bc = FALSE;
1001
+ int zicTzFnum = -1 ;
983
1002
984
1003
/*
985
1004
* 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,
1127
1146
if (tzp == NULL )
1128
1147
return DTERR_BAD_FORMAT ;
1129
1148
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 );
1131
1158
if (dterr )
1132
1159
return dterr ;
1133
1160
@@ -1605,6 +1632,19 @@ DecodeDateTime(char **field, int *ftype, int nf,
1605
1632
if (tm -> tm_mday > day_tab [isleap (tm -> tm_year )][tm -> tm_mon - 1 ])
1606
1633
return DTERR_FIELD_OVERFLOW ;
1607
1634
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
+
1608
1648
/* timezone not specified? then find local timezone if possible */
1609
1649
if (tzp != NULL && !(fmask & DTK_M (TZ )))
1610
1650
{
@@ -1874,7 +1914,15 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
1874
1914
if (tzp == NULL )
1875
1915
return DTERR_BAD_FORMAT ;
1876
1916
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 );
1878
1926
if (dterr )
1879
1927
return dterr ;
1880
1928
@@ -2924,6 +2972,19 @@ DecodePosixTimezone(char *str, int *tzp)
2924
2972
return 0 ;
2925
2973
}
2926
2974
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
+ }
2927
2988
2928
2989
/* DecodeSpecial()
2929
2990
* Decode text string using lookup table.
0 commit comments