Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3e59e50

Browse files
committed
Refactor datetime functions' timezone lookup code to reduce duplication.
We already had five copies of essentially the same logic, and anupcoming patch introduces yet another use-case. That's past mythreshold of pain, so introduce a common subroutine. There's notthat much net code savings, but the chance of typos should go down.Inspired by a patch from Przemysław Sztoch, but different in detail.Discussion:https://postgr.es/m/01a84551-48dd-1359-bf7e-f6b0203a6bd0@sztoch.pl
1 parentcc1392d commit3e59e50

File tree

4 files changed

+142
-180
lines changed

4 files changed

+142
-180
lines changed

‎src/backend/utils/adt/date.c

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3052,38 +3052,23 @@ timetz_zone(PG_FUNCTION_ARGS)
30523052
TimeTzADT*result;
30533053
inttz;
30543054
chartzname[TZ_STRLEN_MAX+1];
3055-
char*lowzone;
3056-
intdterr,
3057-
type,
3055+
inttype,
30583056
val;
30593057
pg_tz*tzp;
3060-
DateTimeErrorExtraextra;
30613058

30623059
/*
3063-
* Look up the requested timezone. First we look in the timezone
3064-
* abbreviation table (to handle cases like "EST"), and if that fails, we
3065-
* look in the timezone database (to handle cases like
3066-
* "America/New_York"). (This matches the order in which timestamp input
3067-
* checks the cases; it's important because the timezone database unwisely
3068-
* uses a few zone names that are identical to offset abbreviations.)
3060+
* Look up the requested timezone.
30693061
*/
30703062
text_to_cstring_buffer(zone,tzname,sizeof(tzname));
30713063

3072-
/* DecodeTimezoneAbbrev requires lowercase input */
3073-
lowzone=downcase_truncate_identifier(tzname,
3074-
strlen(tzname),
3075-
false);
3064+
type=DecodeTimezoneName(tzname,&val,&tzp);
30763065

3077-
dterr=DecodeTimezoneAbbrev(0,lowzone,&type,&val,&tzp,&extra);
3078-
if (dterr)
3079-
DateTimeParseError(dterr,&extra,NULL,NULL,NULL);
3080-
3081-
if (type==TZ||type==DTZ)
3066+
if (type==TZNAME_FIXED_OFFSET)
30823067
{
30833068
/* fixed-offset abbreviation */
30843069
tz=-val;
30853070
}
3086-
elseif (type==DYNTZ)
3071+
elseif (type==TZNAME_DYNTZ)
30873072
{
30883073
/* dynamic-offset abbreviation, resolve using transaction start time */
30893074
TimestampTznow=GetCurrentTransactionStartTimestamp();
@@ -3093,27 +3078,15 @@ timetz_zone(PG_FUNCTION_ARGS)
30933078
}
30943079
else
30953080
{
3096-
/* try it as a full zone name */
3097-
tzp=pg_tzset(tzname);
3098-
if (tzp)
3099-
{
3100-
/* Get the offset-from-GMT that is valid now for the zone */
3101-
TimestampTznow=GetCurrentTransactionStartTimestamp();
3102-
structpg_tmtm;
3103-
fsec_tfsec;
3081+
/* Get the offset-from-GMT that is valid now for the zone name */
3082+
TimestampTznow=GetCurrentTransactionStartTimestamp();
3083+
structpg_tmtm;
3084+
fsec_tfsec;
31043085

3105-
if (timestamp2tm(now,&tz,&tm,&fsec,NULL,tzp)!=0)
3106-
ereport(ERROR,
3107-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3108-
errmsg("timestamp out of range")));
3109-
}
3110-
else
3111-
{
3086+
if (timestamp2tm(now,&tz,&tm,&fsec,NULL,tzp)!=0)
31123087
ereport(ERROR,
3113-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3114-
errmsg("time zone \"%s\" not recognized",tzname)));
3115-
tz=0;/* keep compiler quiet */
3116-
}
3088+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3089+
errmsg("timestamp out of range")));
31173090
}
31183091

31193092
result= (TimeTzADT*)palloc(sizeof(TimeTzADT));

‎src/backend/utils/adt/datetime.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include"funcapi.h"
2727
#include"miscadmin.h"
2828
#include"nodes/nodeFuncs.h"
29+
#include"parser/scansup.h"
2930
#include"utils/builtins.h"
3031
#include"utils/date.h"
3132
#include"utils/datetime.h"
@@ -3162,6 +3163,90 @@ DecodeSpecial(int field, const char *lowtoken, int *val)
31623163
}
31633164

31643165

3166+
/* DecodeTimezoneName()
3167+
* Interpret string as a timezone abbreviation or name.
3168+
* Throw error if the name is not recognized.
3169+
*
3170+
* The return value indicates what kind of zone identifier it is:
3171+
*TZNAME_FIXED_OFFSET: fixed offset from UTC
3172+
*TZNAME_DYNTZ: dynamic timezone abbreviation
3173+
*TZNAME_ZONE: full tzdb zone name
3174+
*
3175+
* For TZNAME_FIXED_OFFSET, *offset receives the UTC offset (in seconds,
3176+
* with ISO sign convention: positive is east of Greenwich).
3177+
* For the other two cases, *tz receives the timezone struct representing
3178+
* the zone name or the abbreviation's underlying zone.
3179+
*/
3180+
int
3181+
DecodeTimezoneName(constchar*tzname,int*offset,pg_tz**tz)
3182+
{
3183+
char*lowzone;
3184+
intdterr,
3185+
type;
3186+
DateTimeErrorExtraextra;
3187+
3188+
/*
3189+
* First we look in the timezone abbreviation table (to handle cases like
3190+
* "EST"), and if that fails, we look in the timezone database (to handle
3191+
* cases like "America/New_York"). This matches the order in which
3192+
* timestamp input checks the cases; it's important because the timezone
3193+
* database unwisely uses a few zone names that are identical to offset
3194+
* abbreviations.
3195+
*/
3196+
3197+
/* DecodeTimezoneAbbrev requires lowercase input */
3198+
lowzone=downcase_truncate_identifier(tzname,
3199+
strlen(tzname),
3200+
false);
3201+
3202+
dterr=DecodeTimezoneAbbrev(0,lowzone,&type,offset,tz,&extra);
3203+
if (dterr)
3204+
DateTimeParseError(dterr,&extra,NULL,NULL,NULL);
3205+
3206+
if (type==TZ||type==DTZ)
3207+
{
3208+
/* fixed-offset abbreviation, return the offset */
3209+
returnTZNAME_FIXED_OFFSET;
3210+
}
3211+
elseif (type==DYNTZ)
3212+
{
3213+
/* dynamic-offset abbreviation, return its referenced timezone */
3214+
returnTZNAME_DYNTZ;
3215+
}
3216+
else
3217+
{
3218+
/* try it as a full zone name */
3219+
*tz=pg_tzset(tzname);
3220+
if (*tz==NULL)
3221+
ereport(ERROR,
3222+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3223+
errmsg("time zone \"%s\" not recognized",tzname)));
3224+
returnTZNAME_ZONE;
3225+
}
3226+
}
3227+
3228+
/* DecodeTimezoneNameToTz()
3229+
* Interpret string as a timezone abbreviation or name.
3230+
* Throw error if the name is not recognized.
3231+
*
3232+
* This is a simple wrapper for DecodeTimezoneName that produces a pg_tz *
3233+
* result in all cases.
3234+
*/
3235+
pg_tz*
3236+
DecodeTimezoneNameToTz(constchar*tzname)
3237+
{
3238+
pg_tz*result;
3239+
intoffset;
3240+
3241+
if (DecodeTimezoneName(tzname,&offset,&result)==TZNAME_FIXED_OFFSET)
3242+
{
3243+
/* fixed-offset abbreviation, get a pg_tz descriptor for that */
3244+
result=pg_tzset_offset(-offset);/* flip to POSIX sign convention */
3245+
}
3246+
returnresult;
3247+
}
3248+
3249+
31653250
/* ClearPgItmIn
31663251
*
31673252
* Zero out a pg_itm_in

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp