PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 maxsize, const char *format, const struct pg_tm *t)
 
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

PGDLLIMPORT pg_tzsession_timezone
 
PGDLLIMPORT pg_tzlog_timezone
 

Macro Definition Documentation

◆ TZ_STRLEN_MAX

#define TZ_STRLEN_MAX   255

Definition at line 54 of file pgtime.h.

Typedef Documentation

◆ pg_time_t

typedef int64 pg_time_t

Definition at line 23 of file pgtime.h.

◆ pg_tz

typedef struct pg_tz pg_tz

Definition at line 23 of file pgtime.h.

◆ pg_tzenum

typedef struct pg_tzenum pg_tzenum

Definition at line 23 of file pgtime.h.

Function Documentation

◆ pg_get_timezone_name()

const char* pg_get_timezone_name ( pg_tz tz)

Definition at line 1875 of file localtime.c.

1876 {
1877  if (tz)
1878  return tz->TZname;
1879  return NULL;
1880 }
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:68

References pg_tz::TZname.

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

◆ pg_get_timezone_offset()

bool pg_get_timezone_offset ( const pg_tz tz,
long int *  gmtoff 
)

Definition at line 1851 of file localtime.c.

1852 {
1853  /*
1854  * The zone could have more than one ttinfo, if it's historically used
1855  * more than one abbreviation. We return true as long as they all have
1856  * the same gmtoff.
1857  */
1858  const struct state *sp;
1859  int i;
1860 
1861  sp = &tz->state;
1862  for (i = 1; i < sp->typecnt; i++)
1863  {
1864  if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
1865  return false;
1866  }
1867  *gmtoff = sp->ttis[0].tt_utoff;
1868  return true;
1869 }
int i
Definition: isn.c:72
struct state state
Definition: pgtz.h:69
Definition: regguts.h:323
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
int typecnt
Definition: pgtz.h:45
int32 tt_utoff
Definition: pgtz.h:28

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

Referenced by DecodeTimeOnly(), and TimestampTimestampTzRequiresRewrite().

◆ pg_gmtime()

struct pg_tm* pg_gmtime ( const pg_time_t timep)

Definition at line 1389 of file localtime.c.

1390 {
1391  return gmtsub(timep, 0, &tm);
1392 }
static struct pg_tm * gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
Definition: localtime.c:1357
static struct pg_tm tm
Definition: localtime.c:104

References gmtsub(), and tm.

Referenced by AddFileToBackupManifest(), and GetEpochTime().

◆ pg_interpret_timezone_abbrev()

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 1757 of file localtime.c.

1762 {
1763  const struct state *sp;
1764  const char *abbrs;
1765  const struct ttinfo *ttisp;
1766  int abbrind;
1767  int cutoff;
1768  int i;
1769  const pg_time_t t = *timep;
1770 
1771  sp = &tz->state;
1772 
1773  /*
1774  * Locate the abbreviation in the zone's abbreviation list. We assume
1775  * there are not duplicates in the list.
1776  */
1777  abbrs = sp->chars;
1778  abbrind = 0;
1779  while (abbrind < sp->charcnt)
1780  {
1781  if (strcmp(abbrev, abbrs + abbrind) == 0)
1782  break;
1783  while (abbrs[abbrind] != '\0')
1784  abbrind++;
1785  abbrind++;
1786  }
1787  if (abbrind >= sp->charcnt)
1788  return false; /* not there! */
1789 
1790  /*
1791  * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1792  * (goback/goahead zones). Finding the newest or oldest meaning of the
1793  * abbreviation should get us what we want, since extrapolation would just
1794  * be repeating the newest or oldest meanings.
1795  *
1796  * Use binary search to locate the first transition > cutoff time.
1797  */
1798  {
1799  int lo = 0;
1800  int hi = sp->timecnt;
1801 
1802  while (lo < hi)
1803  {
1804  int mid = (lo + hi) >> 1;
1805 
1806  if (t < sp->ats[mid])
1807  hi = mid;
1808  else
1809  lo = mid + 1;
1810  }
1811  cutoff = lo;
1812  }
1813 
1814  /*
1815  * Scan backwards to find the latest interval using the given abbrev
1816  * before the cutoff time.
1817  */
1818  for (i = cutoff - 1; i >= 0; i--)
1819  {
1820  ttisp = &sp->ttis[sp->types[i]];
1821  if (ttisp->tt_desigidx == abbrind)
1822  {
1823  *gmtoff = ttisp->tt_utoff;
1824  *isdst = ttisp->tt_isdst;
1825  return true;
1826  }
1827  }
1828 
1829  /*
1830  * Not there, so scan forwards to find the first one after.
1831  */
1832  for (i = cutoff; i < sp->timecnt; i++)
1833  {
1834  ttisp = &sp->ttis[sp->types[i]];
1835  if (ttisp->tt_desigidx == abbrind)
1836  {
1837  *gmtoff = ttisp->tt_utoff;
1838  *isdst = ttisp->tt_isdst;
1839  return true;
1840  }
1841  }
1842 
1843  return false; /* hm, not actually used in any interval? */
1844 }
int64 pg_time_t
Definition: pgtime.h:23
int timecnt
Definition: pgtz.h:44
int charcnt
Definition: pgtz.h:46
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 4),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
Definition: pgtz.h:27
int tt_desigidx
Definition: pgtz.h:30
bool tt_isdst
Definition: pgtz.h:29
static int charcnt
Definition: zic.c:175

References state::charcnt, charcnt, state::chars, i, pg_tz::state, state::timecnt, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, and state::types.

Referenced by DetermineTimeZoneAbbrevOffsetInternal().

◆ pg_localtime()

struct pg_tm* pg_localtime ( const pg_time_t timep,
const pg_tz tz 
)

Definition at line 1344 of file localtime.c.

1345 {
1346  return localsub(&tz->state, timep, &tm);
1347 }
static struct pg_tm * localsub(struct state const *sp, pg_time_t const *timep, struct pg_tm *const tmp)
Definition: localtime.c:1259

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

Referenced by build_backup_content(), get_formatted_log_time(), get_formatted_start_time(), log_status_format(), logfile_getname(), score_timezone(), set_next_rotation_time(), str_time(), timeofday(), and timestamp2tm().

◆ pg_next_dst_boundary()

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 1610 of file localtime.c.

1617 {
1618  const struct state *sp;
1619  const struct ttinfo *ttisp;
1620  int i;
1621  int j;
1622  const pg_time_t t = *timep;
1623 
1624  sp = &tz->state;
1625  if (sp->timecnt == 0)
1626  {
1627  /* non-DST zone, use lowest-numbered standard type */
1628  i = 0;
1629  while (sp->ttis[i].tt_isdst)
1630  if (++i >= sp->typecnt)
1631  {
1632  i = 0;
1633  break;
1634  }
1635  ttisp = &sp->ttis[i];
1636  *before_gmtoff = ttisp->tt_utoff;
1637  *before_isdst = ttisp->tt_isdst;
1638  return 0;
1639  }
1640  if ((sp->goback && t < sp->ats[0]) ||
1641  (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1642  {
1643  /* For values outside the transition table, extrapolate */
1644  pg_time_t newt = t;
1645  pg_time_t seconds;
1646  pg_time_t tcycles;
1647  int64 icycles;
1648  int result;
1649 
1650  if (t < sp->ats[0])
1651  seconds = sp->ats[0] - t;
1652  else
1653  seconds = t - sp->ats[sp->timecnt - 1];
1654  --seconds;
1655  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1656  ++tcycles;
1657  icycles = tcycles;
1658  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1659  return -1;
1660  seconds = icycles;
1661  seconds *= YEARSPERREPEAT;
1662  seconds *= AVGSECSPERYEAR;
1663  if (t < sp->ats[0])
1664  newt += seconds;
1665  else
1666  newt -= seconds;
1667  if (newt < sp->ats[0] ||
1668  newt > sp->ats[sp->timecnt - 1])
1669  return -1; /* "cannot happen" */
1670 
1671  result = pg_next_dst_boundary(&newt, before_gmtoff,
1672  before_isdst,
1673  boundary,
1674  after_gmtoff,
1675  after_isdst,
1676  tz);
1677  if (t < sp->ats[0])
1678  *boundary -= seconds;
1679  else
1680  *boundary += seconds;
1681  return result;
1682  }
1683 
1684  if (t >= sp->ats[sp->timecnt - 1])
1685  {
1686  /* No known transition > t, so use last known segment's type */
1687  i = sp->types[sp->timecnt - 1];
1688  ttisp = &sp->ttis[i];
1689  *before_gmtoff = ttisp->tt_utoff;
1690  *before_isdst = ttisp->tt_isdst;
1691  return 0;
1692  }
1693  if (t < sp->ats[0])
1694  {
1695  /* For "before", use lowest-numbered standard type */
1696  i = 0;
1697  while (sp->ttis[i].tt_isdst)
1698  if (++i >= sp->typecnt)
1699  {
1700  i = 0;
1701  break;
1702  }
1703  ttisp = &sp->ttis[i];
1704  *before_gmtoff = ttisp->tt_utoff;
1705  *before_isdst = ttisp->tt_isdst;
1706  *boundary = sp->ats[0];
1707  /* And for "after", use the first segment's type */
1708  i = sp->types[0];
1709  ttisp = &sp->ttis[i];
1710  *after_gmtoff = ttisp->tt_utoff;
1711  *after_isdst = ttisp->tt_isdst;
1712  return 1;
1713  }
1714  /* Else search to find the boundary following t */
1715  {
1716  int lo = 1;
1717  int hi = sp->timecnt - 1;
1718 
1719  while (lo < hi)
1720  {
1721  int mid = (lo + hi) >> 1;
1722 
1723  if (t < sp->ats[mid])
1724  hi = mid;
1725  else
1726  lo = mid + 1;
1727  }
1728  i = lo;
1729  }
1730  j = sp->types[i - 1];
1731  ttisp = &sp->ttis[j];
1732  *before_gmtoff = ttisp->tt_utoff;
1733  *before_isdst = ttisp->tt_isdst;
1734  *boundary = sp->ats[i];
1735  j = sp->types[i];
1736  ttisp = &sp->ttis[j];
1737  *after_gmtoff = ttisp->tt_utoff;
1738  *after_isdst = ttisp->tt_isdst;
1739  return 1;
1740 }
int j
Definition: isn.c:73
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:1610
#define AVGSECSPERYEAR
Definition: private.h:154
#define YEARSPERREPEAT
Definition: private.h:95
bool goback
Definition: pgtz.h:47
pg_time_t ats[TZ_MAX_TIMES]
Definition: pgtz.h:49
bool goahead
Definition: pgtz.h:48

References state::ats, AVGSECSPERYEAR, state::goahead, state::goback, i, j, pg_next_dst_boundary(), pg_tz::state, state::timecnt, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by DetermineTimeZoneOffsetInternal(), and pg_next_dst_boundary().

◆ pg_strftime()

size_t pg_strftime ( char *  s,
size_t  maxsize,
const char *  format,
const struct pg_tm t 
)

Definition at line 128 of file strftime.c.

129 {
130  char *p;
131  int saved_errno = errno;
132  enum warn warn = IN_NONE;
133 
134  p = _fmt(format, t, s, s + maxsize, &warn);
135  if (!p)
136  {
137  errno = EOVERFLOW;
138  return 0;
139  }
140  if (p == s + maxsize)
141  {
142  errno = ERANGE;
143  return 0;
144  }
145  *p = '\0';
146  errno = saved_errno;
147  return p - s;
148 }
static char format
#define EOVERFLOW
Definition: private.h:41
warn
Definition: strftime.c:110
@ IN_NONE
Definition: strftime.c:111
static char * _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim, enum warn *warnp)
Definition: strftime.c:151

References _fmt(), EOVERFLOW, format, and IN_NONE.

Referenced by AddFileToBackupManifest(), build_backup_content(), get_formatted_log_time(), get_formatted_start_time(), log_status_format(), logfile_getname(), str_time(), and timeofday().

◆ pg_timezone_initialize()

void pg_timezone_initialize ( void  )

Definition at line 361 of file pgtz.c.

362 {
363  /*
364  * We may not yet know where PGSHAREDIR is (in particular this is true in
365  * an EXEC_BACKEND subprocess). So use "GMT", which pg_tzset forces to be
366  * interpreted without reference to the filesystem. This corresponds to
367  * the bootstrap default for these variables in guc_tables.c, although in
368  * principle it could be different.
369  */
370  session_timezone = pg_tzset("GMT");
372 }
pg_tz * log_timezone
Definition: pgtz.c:31
pg_tz * pg_tzset(const char *tzname)
Definition: pgtz.c:234
pg_tz * session_timezone
Definition: pgtz.c:28

References log_timezone, pg_tzset(), and session_timezone.

Referenced by InitializeGUCOptions().

◆ pg_tz_acceptable()

bool pg_tz_acceptable ( pg_tz tz)

Definition at line 1890 of file localtime.c.

1891 {
1892  struct pg_tm *tt;
1893  pg_time_t time2000;
1894 
1895  /*
1896  * To detect leap-second timekeeping, run pg_localtime for what should be
1897  * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
1898  * other result has to be due to leap seconds.
1899  */
1901  tt = pg_localtime(&time2000, tz);
1902  if (!tt || tt->tm_sec != 0)
1903  return false;
1904 
1905  return true;
1906 }
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:234
#define SECS_PER_DAY
Definition: timestamp.h:126
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1344
Definition: pgtime.h:35
int tm_sec
Definition: pgtime.h:36

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

◆ pg_tzenumerate_end()

void pg_tzenumerate_end ( pg_tzenum dir)

Definition at line 414 of file pgtz.c.

415 {
416  while (dir->depth >= 0)
417  {
418  FreeDir(dir->dirdesc[dir->depth]);
419  pfree(dir->dirname[dir->depth]);
420  dir->depth--;
421  }
422  pfree(dir);
423 }
int FreeDir(DIR *dir)
Definition: fd.c:2983
void pfree(void *pointer)
Definition: mcxt.c:1521
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:390
int depth
Definition: pgtz.c:388
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:389

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

◆ pg_tzenumerate_next()

pg_tz* pg_tzenumerate_next ( pg_tzenum dir)

Definition at line 426 of file pgtz.c.

427 {
428  while (dir->depth >= 0)
429  {
430  struct dirent *direntry;
431  char fullname[MAXPGPATH * 2];
432 
433  direntry = ReadDir(dir->dirdesc[dir->depth], dir->dirname[dir->depth]);
434 
435  if (!direntry)
436  {
437  /* End of this directory */
438  FreeDir(dir->dirdesc[dir->depth]);
439  pfree(dir->dirname[dir->depth]);
440  dir->depth--;
441  continue;
442  }
443 
444  if (direntry->d_name[0] == '.')
445  continue;
446 
447  snprintf(fullname, sizeof(fullname), "%s/%s",
448  dir->dirname[dir->depth], direntry->d_name);
449 
450  if (get_dirent_type(fullname, direntry, true, ERROR) == PGFILETYPE_DIR)
451  {
452  /* Step into the subdirectory */
453  if (dir->depth >= MAX_TZDIR_DEPTH - 1)
454  ereport(ERROR,
455  (errmsg_internal("timezone directory stack overflow")));
456  dir->depth++;
457  dir->dirname[dir->depth] = pstrdup(fullname);
458  dir->dirdesc[dir->depth] = AllocateDir(fullname);
459  if (!dir->dirdesc[dir->depth])
460  ereport(ERROR,
462  errmsg("could not open directory \"%s\": %m",
463  fullname)));
464 
465  /* Start over reading in the new directory */
466  continue;
467  }
468 
469  /*
470  * Load this timezone using tzload() not pg_tzset(), so we don't fill
471  * the cache. Also, don't ask for the canonical spelling: we already
472  * know it, and pg_open_tzfile's way of finding it out is pretty
473  * inefficient.
474  */
475  if (tzload(fullname + dir->baselen, NULL, &dir->tz.state, true) != 0)
476  {
477  /* Zone could not be loaded, ignore it */
478  continue;
479  }
480 
481  if (!pg_tz_acceptable(&dir->tz))
482  {
483  /* Ignore leap-second zones */
484  continue;
485  }
486 
487  /* OK, return the canonical zone name spelling. */
488  strlcpy(dir->tz.TZname, fullname + dir->baselen,
489  sizeof(dir->tz.TZname));
490 
491  /* Timezone loaded OK. */
492  return &dir->tz;
493  }
494 
495  /* Nothing more found */
496  return NULL;
497 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2931
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2865
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:526
@ PGFILETYPE_DIR
Definition: file_utils.h:23
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:586
char * pstrdup(const char *in)
Definition: mcxt.c:1696
#define MAXPGPATH
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1890
#define MAX_TZDIR_DEPTH
Definition: pgtz.c:383
#define snprintf
Definition: port.h:238
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
int baselen
Definition: pgtz.c:387
struct pg_tz tz
Definition: pgtz.c:391

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

◆ pg_tzenumerate_start()

pg_tzenum* pg_tzenumerate_start ( void  )

Definition at line 397 of file pgtz.c.

398 {
399  pg_tzenum *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
400  char *startdir = pstrdup(pg_TZDIR());
401 
402  ret->baselen = strlen(startdir) + 1;
403  ret->depth = 0;
404  ret->dirname[0] = startdir;
405  ret->dirdesc[0] = AllocateDir(startdir);
406  if (!ret->dirdesc[0])
407  ereport(ERROR,
409  errmsg("could not open directory \"%s\": %m", startdir)));
410  return ret;
411 }
void * palloc0(Size size)
Definition: mcxt.c:1347
static const char * pg_TZDIR(void)
Definition: pgtz.c:43

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().

◆ pg_tzset()

pg_tz* pg_tzset ( const char *  tzname)

Definition at line 234 of file pgtz.c.

235 {
236  pg_tz_cache *tzp;
237  struct state tzstate;
238  char uppername[TZ_STRLEN_MAX + 1];
239  char canonname[TZ_STRLEN_MAX + 1];
240  char *p;
241 
242  if (strlen(tzname) > TZ_STRLEN_MAX)
243  return NULL; /* not going to fit */
244 
245  if (!timezone_cache)
247  return NULL;
248 
249  /*
250  * Upcase the given name to perform a case-insensitive hashtable search.
251  * (We could alternatively downcase it, but we prefer upcase so that we
252  * can get consistently upcased results from tzparse() in case the name is
253  * a POSIX-style timezone spec.)
254  */
255  p = uppername;
256  while (*tzname)
257  *p++ = pg_toupper((unsigned char) *tzname++);
258  *p = '\0';
259 
261  uppername,
262  HASH_FIND,
263  NULL);
264  if (tzp)
265  {
266  /* Timezone found in cache, nothing more to do */
267  return &tzp->tz;
268  }
269 
270  /*
271  * "GMT" is always sent to tzparse(), as per discussion above.
272  */
273  if (strcmp(uppername, "GMT") == 0)
274  {
275  if (!tzparse(uppername, &tzstate, true))
276  {
277  /* This really, really should not happen ... */
278  elog(ERROR, "could not initialize GMT time zone");
279  }
280  /* Use uppercase name as canonical */
281  strcpy(canonname, uppername);
282  }
283  else if (tzload(uppername, canonname, &tzstate, true) != 0)
284  {
285  if (uppername[0] == ':' || !tzparse(uppername, &tzstate, false))
286  {
287  /* Unknown timezone. Fail our call instead of loading GMT! */
288  return NULL;
289  }
290  /* For POSIX timezone specs, use uppercase name as canonical */
291  strcpy(canonname, uppername);
292  }
293 
294  /* Save timezone in the cache */
296  uppername,
297  HASH_ENTER,
298  NULL);
299 
300  /* hash_search already copied uppername into the hash key */
301  strcpy(tzp->tz.TZname, canonname);
302  memcpy(&tzp->tz.state, &tzstate, sizeof(tzstate));
303 
304  return &tzp->tz;
305 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
#define elog(elevel,...)
Definition: elog.h:225
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
bool tzparse(const char *name, struct state *sp, bool lastditch)
Definition: localtime.c:936
#define TZ_STRLEN_MAX
Definition: pgtime.h:54
static HTAB * timezone_cache
Definition: pgtz.c:198
static bool init_timezone_hashtable(void)
Definition: pgtz.c:202
unsigned char pg_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:105
pg_tz tz
Definition: pgtz.c:195

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

Referenced by check_log_timezone(), check_timezone(), DecodeDateTime(), DecodeTimeOnly(), DecodeTimezoneName(), FetchDynamicTimeZone(), pg_timezone_initialize(), and pg_tzset_offset().

◆ pg_tzset_offset()

pg_tz* pg_tzset_offset ( long  gmtoffset)

Definition at line 320 of file pgtz.c.

321 {
322  long absoffset = (gmtoffset < 0) ? -gmtoffset : gmtoffset;
323  char offsetstr[64];
324  char tzname[128];
325 
326  snprintf(offsetstr, sizeof(offsetstr),
327  "%02ld", absoffset / SECS_PER_HOUR);
328  absoffset %= SECS_PER_HOUR;
329  if (absoffset != 0)
330  {
331  snprintf(offsetstr + strlen(offsetstr),
332  sizeof(offsetstr) - strlen(offsetstr),
333  ":%02ld", absoffset / SECS_PER_MINUTE);
334  absoffset %= SECS_PER_MINUTE;
335  if (absoffset != 0)
336  snprintf(offsetstr + strlen(offsetstr),
337  sizeof(offsetstr) - strlen(offsetstr),
338  ":%02ld", absoffset);
339  }
340  if (gmtoffset > 0)
341  snprintf(tzname, sizeof(tzname), "<-%s>+%s",
342  offsetstr, offsetstr);
343  else
344  snprintf(tzname, sizeof(tzname), "<+%s>-%s",
345  offsetstr, offsetstr);
346 
347  return pg_tzset(tzname);
348 }
#define SECS_PER_HOUR
Definition: timestamp.h:127
#define SECS_PER_MINUTE
Definition: timestamp.h:128

References pg_tzset(), SECS_PER_HOUR, SECS_PER_MINUTE, and snprintf.

Referenced by check_timezone(), and DecodeTimezoneNameToTz().

Variable Documentation

◆ log_timezone

◆ session_timezone