@@ -56,8 +56,9 @@ static void AdjustFractDays(double frac, struct pg_tm * tm, fsec_t *fsec,
5656int scale );
5757static int DetermineTimeZoneOffsetInternal (struct pg_tm * tm ,pg_tz * tzp ,
5858pg_time_t * tp );
59- static int DetermineTimeZoneAbbrevOffsetInternal (pg_time_t t ,const char * abbr ,
60- pg_tz * tzp ,int * isdst );
59+ static bool DetermineTimeZoneAbbrevOffsetInternal (pg_time_t t ,
60+ const char * abbr ,pg_tz * tzp ,
61+ int * offset ,int * isdst );
6162static pg_tz * FetchDynamicTimeZone (TimeZoneAbbrevTable * tbl ,const datetkn * tp );
6263
6364
@@ -1689,19 +1690,40 @@ DetermineTimeZoneOffsetInternal(struct pg_tm * tm, pg_tz *tzp, pg_time_t *tp)
16891690 * This differs from the behavior of DetermineTimeZoneOffset() in that a
16901691 * standard-time or daylight-time abbreviation forces use of the corresponding
16911692 * GMT offset even when the zone was then in DS or standard time respectively.
1693+ * (However, that happens only if we can match the given abbreviation to some
1694+ * abbreviation that appears in the IANA timezone data. Otherwise, we fall
1695+ * back to doing DetermineTimeZoneOffset().)
16921696 */
16931697int
16941698DetermineTimeZoneAbbrevOffset (struct pg_tm * tm ,const char * abbr ,pg_tz * tzp )
16951699{
16961700pg_time_t t ;
1701+ int zone_offset ;
1702+ int abbr_offset ;
1703+ int abbr_isdst ;
16971704
16981705/*
16991706 * Compute the UTC time we want to probe at. (In event of overflow, we'll
17001707 * probe at the epoch, which is a bit random but probably doesn't matter.)
17011708 */
1702- ( void ) DetermineTimeZoneOffsetInternal (tm ,tzp ,& t );
1709+ zone_offset = DetermineTimeZoneOffsetInternal (tm ,tzp ,& t );
17031710
1704- return DetermineTimeZoneAbbrevOffsetInternal (t ,abbr ,tzp ,& tm -> tm_isdst );
1711+ /*
1712+ * Try to match the abbreviation to something in the zone definition.
1713+ */
1714+ if (DetermineTimeZoneAbbrevOffsetInternal (t ,abbr ,tzp ,
1715+ & abbr_offset ,& abbr_isdst ))
1716+ {
1717+ /* Success, so use the abbrev-specific answers. */
1718+ tm -> tm_isdst = abbr_isdst ;
1719+ return abbr_offset ;
1720+ }
1721+
1722+ /*
1723+ * No match, so use the answers we already got from
1724+ * DetermineTimeZoneOffsetInternal.
1725+ */
1726+ return zone_offset ;
17051727}
17061728
17071729
@@ -1715,19 +1737,41 @@ DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr,
17151737pg_tz * tzp ,int * isdst )
17161738{
17171739pg_time_t t = timestamptz_to_time_t (ts );
1740+ int zone_offset ;
1741+ int abbr_offset ;
1742+ int tz ;
1743+ struct pg_tm tm ;
1744+ fsec_t fsec ;
17181745
1719- return DetermineTimeZoneAbbrevOffsetInternal (t ,abbr ,tzp ,isdst );
1746+ /*
1747+ * If the abbrev matches anything in the zone data, this is pretty easy.
1748+ */
1749+ if (DetermineTimeZoneAbbrevOffsetInternal (t ,abbr ,tzp ,
1750+ & abbr_offset ,isdst ))
1751+ return abbr_offset ;
1752+
1753+ /*
1754+ * Else, break down the timestamp so we can use DetermineTimeZoneOffset.
1755+ */
1756+ if (timestamp2tm (ts ,& tz ,& tm ,& fsec ,NULL ,tzp )!= 0 )
1757+ ereport (ERROR ,
1758+ (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
1759+ errmsg ("timestamp out of range" )));
1760+
1761+ zone_offset = DetermineTimeZoneOffset (& tm ,tzp );
1762+ * isdst = tm .tm_isdst ;
1763+ return zone_offset ;
17201764}
17211765
17221766
17231767/* DetermineTimeZoneAbbrevOffsetInternal()
17241768 *
17251769 * Workhorse for above two functions: work from a pg_time_t probe instant.
1726- * DST statusis returned into *isdst.
1770+ *On success, return GMT offset and DST statusinto *offset and *isdst.
17271771 */
1728- static int
1729- DetermineTimeZoneAbbrevOffsetInternal (pg_time_t t ,const char * abbr ,
1730- pg_tz * tzp ,int * isdst )
1772+ static bool
1773+ DetermineTimeZoneAbbrevOffsetInternal (pg_time_t t ,const char * abbr ,pg_tz * tzp ,
1774+ int * offset ,int * isdst )
17311775{
17321776char upabbr [TZ_STRLEN_MAX + 1 ];
17331777unsignedchar * p ;
@@ -1739,18 +1783,17 @@ DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr,
17391783* p = pg_toupper (* p );
17401784
17411785/* Look up the abbrev's meaning at this time in this zone */
1742- if (!pg_interpret_timezone_abbrev (upabbr ,
1743- & t ,
1744- & gmtoff ,
1745- isdst ,
1746- tzp ))
1747- ereport (ERROR ,
1748- (errcode (ERRCODE_CONFIG_FILE_ERROR ),
1749- errmsg ("time zone abbreviation \"%s\" is not used in time zone \"%s\"" ,
1750- abbr ,pg_get_timezone_name (tzp ))));
1751-
1752- /* Change sign to agree with DetermineTimeZoneOffset() */
1753- return (int )- gmtoff ;
1786+ if (pg_interpret_timezone_abbrev (upabbr ,
1787+ & t ,
1788+ & gmtoff ,
1789+ isdst ,
1790+ tzp ))
1791+ {
1792+ /* Change sign to agree with DetermineTimeZoneOffset() */
1793+ * offset = (int )- gmtoff ;
1794+ return true;
1795+ }
1796+ return false;
17541797}
17551798
17561799