PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pgtime.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pg_tm
 

Macros

#define TZ_STRLEN_MAX   255
 

Typedefs

typedef int64 pg_time_t
 
typedef struct pg_tz pg_tz
 
typedef struct pg_tzenum pg_tzenum
 

Functions

struct pg_tmpg_localtime (const pg_time_t *timep, const pg_tz *tz)
 
struct pg_tmpg_gmtime (const pg_time_t *timep)
 
int pg_next_dst_boundary (const pg_time_t *timep, long int *before_gmtoff, int *before_isdst, pg_time_t *boundary, long int *after_gmtoff, int *after_isdst, const pg_tz *tz)
 
bool pg_interpret_timezone_abbrev (const char *abbrev, const pg_time_t *timep, long int *gmtoff, int *isdst, const pg_tz *tz)
 
bool pg_get_timezone_offset (const pg_tz *tz, long int *gmtoff)
 
const char * pg_get_timezone_name (pg_tz *tz)
 
bool pg_tz_acceptable (pg_tz *tz)
 
size_t pg_strftime (char *s, size_t max, const char *format, const struct pg_tm *tm)
 
void pg_timezone_initialize (void)
 
pg_tzpg_tzset (const char *tzname)
 
pg_tzpg_tzset_offset (long gmtoffset)
 
pg_tzenumpg_tzenumerate_start (void)
 
pg_tzpg_tzenumerate_next (pg_tzenum *dir)
 
void pg_tzenumerate_end (pg_tzenum *dir)
 

Variables

pg_tzsession_timezone
 
pg_tzlog_timezone
 

Macro Definition Documentation

Typedef Documentation

Definition at line 23 of file pgtime.h.

Definition at line 40 of file pgtime.h.

Definition at line 41 of file pgtime.h.

Function Documentation

const char* pg_get_timezone_name ( pg_tz tz)

Definition at line 1770 of file localtime.c.

References NULL, and pg_tz::TZname.

Referenced by pg_timezone_names(), show_log_timezone(), and show_timezone().

1771 {
1772  if (tz)
1773  return tz->TZname;
1774  return NULL;
1775 }
#define NULL
Definition: c.h:226
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:62
bool pg_get_timezone_offset ( const pg_tz tz,
long int *  gmtoff 
)

Definition at line 1746 of file localtime.c.

References i, pg_tz::state, ttinfo::tt_gmtoff, state::ttis, and state::typecnt.

Referenced by DecodeTimeOnly().

1747 {
1748  /*
1749  * The zone could have more than one ttinfo, if it's historically used
1750  * more than one abbreviation. We return true as long as they all have
1751  * the same gmtoff.
1752  */
1753  const struct state *sp;
1754  int i;
1755 
1756  sp = &tz->state;
1757  for (i = 1; i < sp->typecnt; i++)
1758  {
1759  if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
1760  return false;
1761  }
1762  *gmtoff = sp->ttis[0].tt_gmtoff;
1763  return true;
1764 }
int32 tt_gmtoff
Definition: pgtz.h:28
struct state state
Definition: pgtz.h:63
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
Definition: regguts.h:298
int i
int typecnt
Definition: pgtz.h:45
struct pg_tm* pg_gmtime ( const pg_time_t timep)

Definition at line 1295 of file localtime.c.

References gmtsub(), and tm.

Referenced by abstime2tm(), and GetEpochTime().

1296 {
1297  return gmtsub(timep, 0, &tm);
1298 }
static struct pg_tm tm
Definition: localtime.c:103
static struct pg_tm * gmtsub(pg_time_t const *, int32, struct pg_tm *)
Definition: localtime.c:1266
bool pg_interpret_timezone_abbrev ( const char *  abbrev,
const pg_time_t timep,
long int *  gmtoff,
int *  isdst,
const pg_tz tz 
)

Definition at line 1652 of file localtime.c.

References state::charcnt, charcnt, state::chars, i, pg_tz::state, state::timecnt, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, and state::types.

Referenced by DetermineTimeZoneAbbrevOffsetInternal().

1657 {
1658  const struct state *sp;
1659  const char *abbrs;
1660  const struct ttinfo *ttisp;
1661  int abbrind;
1662  int cutoff;
1663  int i;
1664  const pg_time_t t = *timep;
1665 
1666  sp = &tz->state;
1667 
1668  /*
1669  * Locate the abbreviation in the zone's abbreviation list. We assume
1670  * there are not duplicates in the list.
1671  */
1672  abbrs = sp->chars;
1673  abbrind = 0;
1674  while (abbrind < sp->charcnt)
1675  {
1676  if (strcmp(abbrev, abbrs + abbrind) == 0)
1677  break;
1678  while (abbrs[abbrind] != '\0')
1679  abbrind++;
1680  abbrind++;
1681  }
1682  if (abbrind >= sp->charcnt)
1683  return false; /* not there! */
1684 
1685  /*
1686  * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1687  * (goback/goahead zones). Finding the newest or oldest meaning of the
1688  * abbreviation should get us what we want, since extrapolation would just
1689  * be repeating the newest or oldest meanings.
1690  *
1691  * Use binary search to locate the first transition > cutoff time.
1692  */
1693  {
1694  int lo = 0;
1695  int hi = sp->timecnt;
1696 
1697  while (lo < hi)
1698  {
1699  int mid = (lo + hi) >> 1;
1700 
1701  if (t < sp->ats[mid])
1702  hi = mid;
1703  else
1704  lo = mid + 1;
1705  }
1706  cutoff = lo;
1707  }
1708 
1709  /*
1710  * Scan backwards to find the latest interval using the given abbrev
1711  * before the cutoff time.
1712  */
1713  for (i = cutoff - 1; i >= 0; i--)
1714  {
1715  ttisp = &sp->ttis[sp->types[i]];
1716  if (ttisp->tt_abbrind == abbrind)
1717  {
1718  *gmtoff = ttisp->tt_gmtoff;
1719  *isdst = ttisp->tt_isdst;
1720  return true;
1721  }
1722  }
1723 
1724  /*
1725  * Not there, so scan forwards to find the first one after.
1726  */
1727  for (i = cutoff; i < sp->timecnt; i++)
1728  {
1729  ttisp = &sp->ttis[sp->types[i]];
1730  if (ttisp->tt_abbrind == abbrind)
1731  {
1732  *gmtoff = ttisp->tt_gmtoff;
1733  *isdst = ttisp->tt_isdst;
1734  return true;
1735  }
1736  }
1737 
1738  return false; /* hm, not actually used in any interval? */
1739 }
int64 pg_time_t
Definition: pgtime.h:23
int charcnt
Definition: pgtz.h:46
int32 tt_gmtoff
Definition: pgtz.h:28
Definition: pgtz.h:26
bool tt_isdst
Definition: pgtz.h:29
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 3),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53
struct state state
Definition: pgtz.h:63
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
Definition: regguts.h:298
int timecnt
Definition: pgtz.h:44
static int charcnt
Definition: zic.c:163
int tt_abbrind
Definition: pgtz.h:30
int i
struct pg_tm* pg_localtime ( const pg_time_t timep,
const pg_tz tz 
)

Definition at line 1254 of file localtime.c.

References localsub(), pg_tz::state, and tm.

Referenced by abstime2tm(), do_pg_start_backup(), do_pg_stop_backup(), log_line_prefix(), logfile_getname(), pg_tz_acceptable(), score_timezone(), set_next_rotation_time(), setup_formatted_log_time(), setup_formatted_start_time(), str_time(), timeofday(), timestamp2tm(), and timetz_zone().

1255 {
1256  return localsub(&tz->state, timep, &tm);
1257 }
static struct pg_tm tm
Definition: localtime.c:103
struct state state
Definition: pgtz.h:63
static struct pg_tm * localsub(struct state const *sp, pg_time_t const *timep, struct pg_tm *tmp)
Definition: localtime.c:1174
int pg_next_dst_boundary ( const pg_time_t timep,
long int *  before_gmtoff,
int *  before_isdst,
pg_time_t boundary,
long int *  after_gmtoff,
int *  after_isdst,
const pg_tz tz 
)

Definition at line 1505 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::goahead, state::goback, i, pg_tz::state, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by DetermineTimeZoneOffsetInternal().

1512 {
1513  const struct state *sp;
1514  const struct ttinfo *ttisp;
1515  int i;
1516  int j;
1517  const pg_time_t t = *timep;
1518 
1519  sp = &tz->state;
1520  if (sp->timecnt == 0)
1521  {
1522  /* non-DST zone, use lowest-numbered standard type */
1523  i = 0;
1524  while (sp->ttis[i].tt_isdst)
1525  if (++i >= sp->typecnt)
1526  {
1527  i = 0;
1528  break;
1529  }
1530  ttisp = &sp->ttis[i];
1531  *before_gmtoff = ttisp->tt_gmtoff;
1532  *before_isdst = ttisp->tt_isdst;
1533  return 0;
1534  }
1535  if ((sp->goback && t < sp->ats[0]) ||
1536  (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1537  {
1538  /* For values outside the transition table, extrapolate */
1539  pg_time_t newt = t;
1540  pg_time_t seconds;
1541  pg_time_t tcycles;
1542  int64 icycles;
1543  int result;
1544 
1545  if (t < sp->ats[0])
1546  seconds = sp->ats[0] - t;
1547  else
1548  seconds = t - sp->ats[sp->timecnt - 1];
1549  --seconds;
1550  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1551  ++tcycles;
1552  icycles = tcycles;
1553  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1554  return -1;
1555  seconds = icycles;
1556  seconds *= YEARSPERREPEAT;
1557  seconds *= AVGSECSPERYEAR;
1558  if (t < sp->ats[0])
1559  newt += seconds;
1560  else
1561  newt -= seconds;
1562  if (newt < sp->ats[0] ||
1563  newt > sp->ats[sp->timecnt - 1])
1564  return -1; /* "cannot happen" */
1565 
1566  result = pg_next_dst_boundary(&newt, before_gmtoff,
1567  before_isdst,
1568  boundary,
1569  after_gmtoff,
1570  after_isdst,
1571  tz);
1572  if (t < sp->ats[0])
1573  *boundary -= seconds;
1574  else
1575  *boundary += seconds;
1576  return result;
1577  }
1578 
1579  if (t >= sp->ats[sp->timecnt - 1])
1580  {
1581  /* No known transition > t, so use last known segment's type */
1582  i = sp->types[sp->timecnt - 1];
1583  ttisp = &sp->ttis[i];
1584  *before_gmtoff = ttisp->tt_gmtoff;
1585  *before_isdst = ttisp->tt_isdst;
1586  return 0;
1587  }
1588  if (t < sp->ats[0])
1589  {
1590  /* For "before", use lowest-numbered standard type */
1591  i = 0;
1592  while (sp->ttis[i].tt_isdst)
1593  if (++i >= sp->typecnt)
1594  {
1595  i = 0;
1596  break;
1597  }
1598  ttisp = &sp->ttis[i];
1599  *before_gmtoff = ttisp->tt_gmtoff;
1600  *before_isdst = ttisp->tt_isdst;
1601  *boundary = sp->ats[0];
1602  /* And for "after", use the first segment's type */
1603  i = sp->types[0];
1604  ttisp = &sp->ttis[i];
1605  *after_gmtoff = ttisp->tt_gmtoff;
1606  *after_isdst = ttisp->tt_isdst;
1607  return 1;
1608  }
1609  /* Else search to find the boundary following t */
1610  {
1611  int lo = 1;
1612  int hi = sp->timecnt - 1;
1613 
1614  while (lo < hi)
1615  {
1616  int mid = (lo + hi) >> 1;
1617 
1618  if (t < sp->ats[mid])
1619  hi = mid;
1620  else
1621  lo = mid + 1;
1622  }
1623  i = lo;
1624  }
1625  j = sp->types[i - 1];
1626  ttisp = &sp->ttis[j];
1627  *before_gmtoff = ttisp->tt_gmtoff;
1628  *before_isdst = ttisp->tt_isdst;
1629  *boundary = sp->ats[i];
1630  j = sp->types[i];
1631  ttisp = &sp->ttis[j];
1632  *after_gmtoff = ttisp->tt_gmtoff;
1633  *after_isdst = ttisp->tt_isdst;
1634  return 1;
1635 }
#define AVGSECSPERYEAR
Definition: private.h:120
int64 pg_time_t
Definition: pgtime.h:23
bool goback
Definition: pgtz.h:47
int32 tt_gmtoff
Definition: pgtz.h:28
Definition: pgtz.h:26
pg_time_t ats[TZ_MAX_TIMES]
Definition: pgtz.h:49
bool tt_isdst
Definition: pgtz.h:29
struct state state
Definition: pgtz.h:63
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
int pg_next_dst_boundary(const pg_time_t *timep, long int *before_gmtoff, int *before_isdst, pg_time_t *boundary, long int *after_gmtoff, int *after_isdst, const pg_tz *tz)
Definition: localtime.c:1505
Definition: regguts.h:298
int timecnt
Definition: pgtz.h:44
#define YEARSPERREPEAT
Definition: private.h:112
int i
bool goahead
Definition: pgtz.h:48
int typecnt
Definition: pgtz.h:45
size_t pg_strftime ( char *  s,
size_t  max,
const char *  format,
const struct pg_tm tm 
)

Definition at line 123 of file strftime.c.

References _fmt(), IN_NONE, and warn().

Referenced by do_pg_start_backup(), do_pg_stop_backup(), log_line_prefix(), logfile_getname(), setup_formatted_log_time(), setup_formatted_start_time(), str_time(), and timeofday().

125 {
126  char *p;
127  int warn;
128 
129  warn = IN_NONE;
130  p = _fmt(format, t, s, s + maxsize, &warn);
131  if (p == s + maxsize)
132  return 0;
133  *p = '\0';
134  return p - s;
135 }
static char * _fmt(const char *, const struct pg_tm *, char *, const char *, int *)
Definition: strftime.c:138
static char format
Definition: pg_basebackup.c:82
#define IN_NONE
Definition: strftime.c:116
static void warn(void)
void pg_timezone_initialize ( void  )

Definition at line 345 of file pgtz.c.

References pg_tzset(), and session_timezone.

Referenced by InitializeGUCOptions().

346 {
347  /*
348  * We may not yet know where PGSHAREDIR is (in particular this is true in
349  * an EXEC_BACKEND subprocess). So use "GMT", which pg_tzset forces to be
350  * interpreted without reference to the filesystem. This corresponds to
351  * the bootstrap default for these variables in guc.c, although in
352  * principle it could be different.
353  */
354  session_timezone = pg_tzset("GMT");
356 }
pg_tz * log_timezone
Definition: pgtz.c:30
pg_tz * pg_tzset(const char *name)
Definition: pgtz.c:218
pg_tz * session_timezone
Definition: pgtz.c:27
bool pg_tz_acceptable ( pg_tz tz)

Definition at line 1785 of file localtime.c.

References pg_localtime(), POSTGRES_EPOCH_JDATE, SECS_PER_DAY, pg_tm::tm_sec, and UNIX_EPOCH_JDATE.

Referenced by check_log_timezone(), check_timezone(), pg_tzenumerate_next(), score_timezone(), and validate_zone().

1786 {
1787  struct pg_tm *tt;
1788  pg_time_t time2000;
1789 
1790  /*
1791  * To detect leap-second timekeeping, run pg_localtime for what should be
1792  * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
1793  * other result has to be due to leap seconds.
1794  */
1796  tt = pg_localtime(&time2000, tz);
1797  if (!tt || tt->tm_sec != 0)
1798  return false;
1799 
1800  return true;
1801 }
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1254
int64 pg_time_t
Definition: pgtime.h:23
Definition: pgtime.h:25
#define SECS_PER_DAY
Definition: timestamp.h:86
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:162
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163
int tm_sec
Definition: pgtime.h:27
void pg_tzenumerate_end ( pg_tzenum dir)

Definition at line 398 of file pgtz.c.

References pg_tzenum::depth, pg_tzenum::dirdesc, pg_tzenum::dirname, FreeDir(), and pfree().

Referenced by pg_timezone_names().

399 {
400  while (dir->depth >= 0)
401  {
402  FreeDir(dir->dirdesc[dir->depth]);
403  pfree(dir->dirname[dir->depth]);
404  dir->depth--;
405  }
406  pfree(dir);
407 }
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:373
void pfree(void *pointer)
Definition: mcxt.c:992
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:374
int depth
Definition: pgtz.c:372
int FreeDir(DIR *dir)
Definition: fd.c:2393
pg_tz* pg_tzenumerate_next ( pg_tzenum dir)

Definition at line 410 of file pgtz.c.

References AllocateDir(), pg_tzenum::baselen, pg_tzenum::depth, pg_tzenum::dirdesc, pg_tzenum::dirname, ereport, errcode_for_file_access(), errmsg(), errmsg_internal(), ERROR, FreeDir(), MAX_TZDIR_DEPTH, MAXPGPATH, NULL, pfree(), pg_tz_acceptable(), pstrdup(), ReadDir(), snprintf(), pg_tz::state, pg_tzenum::tz, tzload(), and pg_tz::TZname.

Referenced by pg_timezone_names().

411 {
412  while (dir->depth >= 0)
413  {
414  struct dirent *direntry;
415  char fullname[MAXPGPATH];
416  struct stat statbuf;
417 
418  direntry = ReadDir(dir->dirdesc[dir->depth], dir->dirname[dir->depth]);
419 
420  if (!direntry)
421  {
422  /* End of this directory */
423  FreeDir(dir->dirdesc[dir->depth]);
424  pfree(dir->dirname[dir->depth]);
425  dir->depth--;
426  continue;
427  }
428 
429  if (direntry->d_name[0] == '.')
430  continue;
431 
432  snprintf(fullname, MAXPGPATH, "%s/%s",
433  dir->dirname[dir->depth], direntry->d_name);
434  if (stat(fullname, &statbuf) != 0)
435  ereport(ERROR,
437  errmsg("could not stat \"%s\": %m", fullname)));
438 
439  if (S_ISDIR(statbuf.st_mode))
440  {
441  /* Step into the subdirectory */
442  if (dir->depth >= MAX_TZDIR_DEPTH - 1)
443  ereport(ERROR,
444  (errmsg_internal("timezone directory stack overflow")));
445  dir->depth++;
446  dir->dirname[dir->depth] = pstrdup(fullname);
447  dir->dirdesc[dir->depth] = AllocateDir(fullname);
448  if (!dir->dirdesc[dir->depth])
449  ereport(ERROR,
451  errmsg("could not open directory \"%s\": %m",
452  fullname)));
453 
454  /* Start over reading in the new directory */
455  continue;
456  }
457 
458  /*
459  * Load this timezone using tzload() not pg_tzset(), so we don't fill
460  * the cache
461  */
462  if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state,
463  true) != 0)
464  {
465  /* Zone could not be loaded, ignore it */
466  continue;
467  }
468 
469  if (!pg_tz_acceptable(&dir->tz))
470  {
471  /* Ignore leap-second zones */
472  continue;
473  }
474 
475  /* Timezone loaded OK. */
476  return &dir->tz;
477  }
478 
479  /* Nothing more found */
480  return NULL;
481 }
struct pg_tz tz
Definition: pgtz.c:375
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:537
char * pstrdup(const char *in)
Definition: mcxt.c:1165
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:373
void pfree(void *pointer)
Definition: mcxt.c:992
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:374
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define MAX_TZDIR_DEPTH
Definition: pgtz.c:367
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2284
#define ereport(elevel, rest)
Definition: elog.h:122
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1785
struct state state
Definition: pgtz.h:63
int baselen
Definition: pgtz.c:371
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
#define NULL
Definition: c.h:226
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2350
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:62
int errmsg(const char *fmt,...)
Definition: elog.c:797
int depth
Definition: pgtz.c:372
int FreeDir(DIR *dir)
Definition: fd.c:2393
pg_tzenum* pg_tzenumerate_start ( void  )

Definition at line 381 of file pgtz.c.

References AllocateDir(), pg_tzenum::baselen, pg_tzenum::depth, pg_tzenum::dirdesc, pg_tzenum::dirname, ereport, errcode_for_file_access(), errmsg(), ERROR, palloc0(), pg_TZDIR(), and pstrdup().

Referenced by pg_timezone_names().

382 {
383  pg_tzenum *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
384  char *startdir = pstrdup(pg_TZDIR());
385 
386  ret->baselen = strlen(startdir) + 1;
387  ret->depth = 0;
388  ret->dirname[0] = startdir;
389  ret->dirdesc[0] = AllocateDir(startdir);
390  if (!ret->dirdesc[0])
391  ereport(ERROR,
393  errmsg("could not open directory \"%s\": %m", startdir)));
394  return ret;
395 }
char * pstrdup(const char *in)
Definition: mcxt.c:1165
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:373
static const char * pg_TZDIR(void)
Definition: pgtz.c:42
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:374
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2284
#define ereport(elevel, rest)
Definition: elog.h:122
void * palloc0(Size size)
Definition: mcxt.c:920
int baselen
Definition: pgtz.c:371
int errmsg(const char *fmt,...)
Definition: elog.c:797
int depth
Definition: pgtz.c:372
pg_tz* pg_tzset ( const char *  tzname)

Definition at line 218 of file pgtz.c.

References elog, ERROR, HASH_ENTER, HASH_FIND, hash_search(), init_timezone_hashtable(), NULL, pg_toupper(), pg_tz::state, pg_tz_cache::tz, TZ_STRLEN_MAX, tzload(), pg_tz::TZname, and tzparse().

Referenced by check_log_timezone(), check_timezone(), DecodeDateTime(), DecodeTimeOnly(), FetchDynamicTimeZone(), parse_sane_timezone(), pg_timezone_initialize(), pg_tzset_offset(), timestamp_zone(), timestamptz_zone(), and timetz_zone().

219 {
220  pg_tz_cache *tzp;
221  struct state tzstate;
222  char uppername[TZ_STRLEN_MAX + 1];
223  char canonname[TZ_STRLEN_MAX + 1];
224  char *p;
225 
226  if (strlen(name) > TZ_STRLEN_MAX)
227  return NULL; /* not going to fit */
228 
229  if (!timezone_cache)
231  return NULL;
232 
233  /*
234  * Upcase the given name to perform a case-insensitive hashtable search.
235  * (We could alternatively downcase it, but we prefer upcase so that we
236  * can get consistently upcased results from tzparse() in case the name is
237  * a POSIX-style timezone spec.)
238  */
239  p = uppername;
240  while (*name)
241  *p++ = pg_toupper((unsigned char) *name++);
242  *p = '\0';
243 
245  uppername,
246  HASH_FIND,
247  NULL);
248  if (tzp)
249  {
250  /* Timezone found in cache, nothing more to do */
251  return &tzp->tz;
252  }
253 
254  /*
255  * "GMT" is always sent to tzparse(), as per discussion above.
256  */
257  if (strcmp(uppername, "GMT") == 0)
258  {
259  if (!tzparse(uppername, &tzstate, true))
260  {
261  /* This really, really should not happen ... */
262  elog(ERROR, "could not initialize GMT time zone");
263  }
264  /* Use uppercase name as canonical */
265  strcpy(canonname, uppername);
266  }
267  else if (tzload(uppername, canonname, &tzstate, true) != 0)
268  {
269  if (uppername[0] == ':' || !tzparse(uppername, &tzstate, false))
270  {
271  /* Unknown timezone. Fail our call instead of loading GMT! */
272  return NULL;
273  }
274  /* For POSIX timezone specs, use uppercase name as canonical */
275  strcpy(canonname, uppername);
276  }
277 
278  /* Save timezone in the cache */
280  uppername,
281  HASH_ENTER,
282  NULL);
283 
284  /* hash_search already copied uppername into the hash key */
285  strcpy(tzp->tz.TZname, canonname);
286  memcpy(&tzp->tz.state, &tzstate, sizeof(tzstate));
287 
288  return &tzp->tz;
289 }
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:537
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define TZ_STRLEN_MAX
Definition: pgtime.h:44
#define ERROR
Definition: elog.h:43
static bool init_timezone_hashtable(void)
Definition: pgtz.c:184
bool tzparse(const char *name, struct state *sp, bool lastditch)
Definition: localtime.c:878
pg_tz tz
Definition: pgtz.c:177
struct state state
Definition: pgtz.h:63
static HTAB * timezone_cache
Definition: pgtz.c:180
#define NULL
Definition: c.h:226
Definition: regguts.h:298
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:62
const char * name
Definition: encode.c:521
#define elog
Definition: elog.h:219
unsigned char pg_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:105
pg_tz* pg_tzset_offset ( long  gmtoffset)

Definition at line 304 of file pgtz.c.

References pg_tzset(), SECSPERHOUR, SECSPERMIN, and snprintf().

Referenced by check_timezone().

305 {
306  long absoffset = (gmtoffset < 0) ? -gmtoffset : gmtoffset;
307  char offsetstr[64];
308  char tzname[128];
309 
310  snprintf(offsetstr, sizeof(offsetstr),
311  "%02ld", absoffset / SECSPERHOUR);
312  absoffset %= SECSPERHOUR;
313  if (absoffset != 0)
314  {
315  snprintf(offsetstr + strlen(offsetstr),
316  sizeof(offsetstr) - strlen(offsetstr),
317  ":%02ld", absoffset / SECSPERMIN);
318  absoffset %= SECSPERMIN;
319  if (absoffset != 0)
320  snprintf(offsetstr + strlen(offsetstr),
321  sizeof(offsetstr) - strlen(offsetstr),
322  ":%02ld", absoffset);
323  }
324  if (gmtoffset > 0)
325  snprintf(tzname, sizeof(tzname), "<-%s>+%s",
326  offsetstr, offsetstr);
327  else
328  snprintf(tzname, sizeof(tzname), "<+%s>-%s",
329  offsetstr, offsetstr);
330 
331  return pg_tzset(tzname);
332 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
pg_tz * pg_tzset(const char *name)
Definition: pgtz.c:218
#define SECSPERMIN
Definition: tzfile.h:103
#define SECSPERHOUR
Definition: tzfile.h:109

Variable Documentation