PostgreSQL Source Code  git master
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

PGDLLIMPORT pg_tzsession_timezone
 
pg_tzlog_timezone
 

Macro Definition Documentation

◆ TZ_STRLEN_MAX

Typedef Documentation

◆ pg_time_t

Definition at line 23 of file pgtime.h.

◆ pg_tz

Definition at line 40 of file pgtime.h.

◆ pg_tzenum

Definition at line 41 of file pgtime.h.

Function Documentation

◆ pg_get_timezone_name()

const char* pg_get_timezone_name ( pg_tz tz)

Definition at line 1824 of file localtime.c.

References pg_tz::TZname.

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

1825 {
1826  if (tz)
1827  return tz->TZname;
1828  return NULL;
1829 }
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:62

◆ pg_get_timezone_offset()

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

Definition at line 1800 of file localtime.c.

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

Referenced by DecodeTimeOnly().

1801 {
1802  /*
1803  * The zone could have more than one ttinfo, if it's historically used
1804  * more than one abbreviation. We return true as long as they all have
1805  * the same gmtoff.
1806  */
1807  const struct state *sp;
1808  int i;
1809 
1810  sp = &tz->state;
1811  for (i = 1; i < sp->typecnt; i++)
1812  {
1813  if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
1814  return false;
1815  }
1816  *gmtoff = sp->ttis[0].tt_gmtoff;
1817  return true;
1818 }
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

◆ pg_gmtime()

struct pg_tm* pg_gmtime ( const pg_time_t timep)

Definition at line 1355 of file localtime.c.

References gmtsub(), and tm.

Referenced by abstime2tm(), and GetEpochTime().

1356 {
1357  return gmtsub(timep, 0, &tm);
1358 }
static struct pg_tm tm
Definition: localtime.c:107
static struct pg_tm * gmtsub(pg_time_t const *, int32, struct pg_tm *)
Definition: localtime.c:1326

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

1711 {
1712  const struct state *sp;
1713  const char *abbrs;
1714  const struct ttinfo *ttisp;
1715  int abbrind;
1716  int cutoff;
1717  int i;
1718  const pg_time_t t = *timep;
1719 
1720  sp = &tz->state;
1721 
1722  /*
1723  * Locate the abbreviation in the zone's abbreviation list. We assume
1724  * there are not duplicates in the list.
1725  */
1726  abbrs = sp->chars;
1727  abbrind = 0;
1728  while (abbrind < sp->charcnt)
1729  {
1730  if (strcmp(abbrev, abbrs + abbrind) == 0)
1731  break;
1732  while (abbrs[abbrind] != '\0')
1733  abbrind++;
1734  abbrind++;
1735  }
1736  if (abbrind >= sp->charcnt)
1737  return false; /* not there! */
1738 
1739  /*
1740  * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1741  * (goback/goahead zones). Finding the newest or oldest meaning of the
1742  * abbreviation should get us what we want, since extrapolation would just
1743  * be repeating the newest or oldest meanings.
1744  *
1745  * Use binary search to locate the first transition > cutoff time.
1746  */
1747  {
1748  int lo = 0;
1749  int hi = sp->timecnt;
1750 
1751  while (lo < hi)
1752  {
1753  int mid = (lo + hi) >> 1;
1754 
1755  if (t < sp->ats[mid])
1756  hi = mid;
1757  else
1758  lo = mid + 1;
1759  }
1760  cutoff = lo;
1761  }
1762 
1763  /*
1764  * Scan backwards to find the latest interval using the given abbrev
1765  * before the cutoff time.
1766  */
1767  for (i = cutoff - 1; i >= 0; i--)
1768  {
1769  ttisp = &sp->ttis[sp->types[i]];
1770  if (ttisp->tt_abbrind == abbrind)
1771  {
1772  *gmtoff = ttisp->tt_gmtoff;
1773  *isdst = ttisp->tt_isdst;
1774  return true;
1775  }
1776  }
1777 
1778  /*
1779  * Not there, so scan forwards to find the first one after.
1780  */
1781  for (i = cutoff; i < sp->timecnt; i++)
1782  {
1783  ttisp = &sp->ttis[sp->types[i]];
1784  if (ttisp->tt_abbrind == abbrind)
1785  {
1786  *gmtoff = ttisp->tt_gmtoff;
1787  *isdst = ttisp->tt_isdst;
1788  return true;
1789  }
1790  }
1791 
1792  return false; /* hm, not actually used in any interval? */
1793 }
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:165
int tt_abbrind
Definition: pgtz.h:30
int i

◆ pg_localtime()

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

Definition at line 1314 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().

1315 {
1316  return localsub(&tz->state, timep, &tm);
1317 }
static struct pg_tm tm
Definition: localtime.c:107
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:1234

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

1566 {
1567  const struct state *sp;
1568  const struct ttinfo *ttisp;
1569  int i;
1570  int j;
1571  const pg_time_t t = *timep;
1572 
1573  sp = &tz->state;
1574  if (sp->timecnt == 0)
1575  {
1576  /* non-DST zone, use lowest-numbered standard type */
1577  i = 0;
1578  while (sp->ttis[i].tt_isdst)
1579  if (++i >= sp->typecnt)
1580  {
1581  i = 0;
1582  break;
1583  }
1584  ttisp = &sp->ttis[i];
1585  *before_gmtoff = ttisp->tt_gmtoff;
1586  *before_isdst = ttisp->tt_isdst;
1587  return 0;
1588  }
1589  if ((sp->goback && t < sp->ats[0]) ||
1590  (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1591  {
1592  /* For values outside the transition table, extrapolate */
1593  pg_time_t newt = t;
1594  pg_time_t seconds;
1595  pg_time_t tcycles;
1596  int64 icycles;
1597  int result;
1598 
1599  if (t < sp->ats[0])
1600  seconds = sp->ats[0] - t;
1601  else
1602  seconds = t - sp->ats[sp->timecnt - 1];
1603  --seconds;
1604  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1605  ++tcycles;
1606  icycles = tcycles;
1607  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1608  return -1;
1609  seconds = icycles;
1610  seconds *= YEARSPERREPEAT;
1611  seconds *= AVGSECSPERYEAR;
1612  if (t < sp->ats[0])
1613  newt += seconds;
1614  else
1615  newt -= seconds;
1616  if (newt < sp->ats[0] ||
1617  newt > sp->ats[sp->timecnt - 1])
1618  return -1; /* "cannot happen" */
1619 
1620  result = pg_next_dst_boundary(&newt, before_gmtoff,
1621  before_isdst,
1622  boundary,
1623  after_gmtoff,
1624  after_isdst,
1625  tz);
1626  if (t < sp->ats[0])
1627  *boundary -= seconds;
1628  else
1629  *boundary += seconds;
1630  return result;
1631  }
1632 
1633  if (t >= sp->ats[sp->timecnt - 1])
1634  {
1635  /* No known transition > t, so use last known segment's type */
1636  i = sp->types[sp->timecnt - 1];
1637  ttisp = &sp->ttis[i];
1638  *before_gmtoff = ttisp->tt_gmtoff;
1639  *before_isdst = ttisp->tt_isdst;
1640  return 0;
1641  }
1642  if (t < sp->ats[0])
1643  {
1644  /* For "before", use lowest-numbered standard type */
1645  i = 0;
1646  while (sp->ttis[i].tt_isdst)
1647  if (++i >= sp->typecnt)
1648  {
1649  i = 0;
1650  break;
1651  }
1652  ttisp = &sp->ttis[i];
1653  *before_gmtoff = ttisp->tt_gmtoff;
1654  *before_isdst = ttisp->tt_isdst;
1655  *boundary = sp->ats[0];
1656  /* And for "after", use the first segment's type */
1657  i = sp->types[0];
1658  ttisp = &sp->ttis[i];
1659  *after_gmtoff = ttisp->tt_gmtoff;
1660  *after_isdst = ttisp->tt_isdst;
1661  return 1;
1662  }
1663  /* Else search to find the boundary following t */
1664  {
1665  int lo = 1;
1666  int hi = sp->timecnt - 1;
1667 
1668  while (lo < hi)
1669  {
1670  int mid = (lo + hi) >> 1;
1671 
1672  if (t < sp->ats[mid])
1673  hi = mid;
1674  else
1675  lo = mid + 1;
1676  }
1677  i = lo;
1678  }
1679  j = sp->types[i - 1];
1680  ttisp = &sp->ttis[j];
1681  *before_gmtoff = ttisp->tt_gmtoff;
1682  *before_isdst = ttisp->tt_isdst;
1683  *boundary = sp->ats[i];
1684  j = sp->types[i];
1685  ttisp = &sp->ttis[j];
1686  *after_gmtoff = ttisp->tt_gmtoff;
1687  *after_isdst = ttisp->tt_isdst;
1688  return 1;
1689 }
#define AVGSECSPERYEAR
Definition: private.h:147
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:1559
Definition: regguts.h:298
int timecnt
Definition: pgtz.h:44
#define YEARSPERREPEAT
Definition: private.h:88
int i
bool goahead
Definition: pgtz.h:48
int typecnt
Definition: pgtz.h:45

◆ pg_strftime()

size_t pg_strftime ( char *  s,
size_t  max,
const char *  format,
const struct pg_tm tm 
)

Definition at line 122 of file strftime.c.

References _fmt(), and IN_NONE.

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

123 {
124  char *p;
125  enum warn warn = IN_NONE;
126 
127  p = _fmt(format, t, s, s + maxsize, &warn);
128  if (p == s + maxsize)
129  return 0;
130  *p = '\0';
131  return p - s;
132 }
static char * _fmt(const char *, const struct pg_tm *, char *, const char *, enum warn *)
Definition: strftime.c:135
warn
Definition: strftime.c:109
static char format
Definition: pg_basebackup.c:81

◆ pg_timezone_initialize()

void pg_timezone_initialize ( void  )

Definition at line 363 of file pgtz.c.

References pg_tzset(), and session_timezone.

Referenced by InitializeGUCOptions().

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

◆ pg_tz_acceptable()

bool pg_tz_acceptable ( pg_tz tz)

Definition at line 1839 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().

1840 {
1841  struct pg_tm *tt;
1842  pg_time_t time2000;
1843 
1844  /*
1845  * To detect leap-second timekeeping, run pg_localtime for what should be
1846  * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
1847  * other result has to be due to leap seconds.
1848  */
1850  tt = pg_localtime(&time2000, tz);
1851  if (!tt || tt->tm_sec != 0)
1852  return false;
1853 
1854  return true;
1855 }
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1314
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

◆ pg_tzenumerate_end()

void pg_tzenumerate_end ( pg_tzenum dir)

Definition at line 416 of file pgtz.c.

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

Referenced by pg_timezone_names().

417 {
418  while (dir->depth >= 0)
419  {
420  FreeDir(dir->dirdesc[dir->depth]);
421  pfree(dir->dirname[dir->depth]);
422  dir->depth--;
423  }
424  pfree(dir);
425 }
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:391
void pfree(void *pointer)
Definition: mcxt.c:949
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:392
int depth
Definition: pgtz.c:390
int FreeDir(DIR *dir)
Definition: fd.c:2714

◆ pg_tzenumerate_next()

pg_tz* pg_tzenumerate_next ( pg_tzenum dir)

Definition at line 428 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, pfree(), pg_tz_acceptable(), pstrdup(), ReadDir(), S_ISDIR, snprintf(), stat, pg_tz::state, strlcpy(), pg_tzenum::tz, tzload(), and pg_tz::TZname.

Referenced by pg_timezone_names().

429 {
430  while (dir->depth >= 0)
431  {
432  struct dirent *direntry;
433  char fullname[MAXPGPATH * 2];
434  struct stat statbuf;
435 
436  direntry = ReadDir(dir->dirdesc[dir->depth], dir->dirname[dir->depth]);
437 
438  if (!direntry)
439  {
440  /* End of this directory */
441  FreeDir(dir->dirdesc[dir->depth]);
442  pfree(dir->dirname[dir->depth]);
443  dir->depth--;
444  continue;
445  }
446 
447  if (direntry->d_name[0] == '.')
448  continue;
449 
450  snprintf(fullname, sizeof(fullname), "%s/%s",
451  dir->dirname[dir->depth], direntry->d_name);
452  if (stat(fullname, &statbuf) != 0)
453  ereport(ERROR,
455  errmsg("could not stat \"%s\": %m", fullname)));
456 
457  if (S_ISDIR(statbuf.st_mode))
458  {
459  /* Step into the subdirectory */
460  if (dir->depth >= MAX_TZDIR_DEPTH - 1)
461  ereport(ERROR,
462  (errmsg_internal("timezone directory stack overflow")));
463  dir->depth++;
464  dir->dirname[dir->depth] = pstrdup(fullname);
465  dir->dirdesc[dir->depth] = AllocateDir(fullname);
466  if (!dir->dirdesc[dir->depth])
467  ereport(ERROR,
469  errmsg("could not open directory \"%s\": %m",
470  fullname)));
471 
472  /* Start over reading in the new directory */
473  continue;
474  }
475 
476  /*
477  * Load this timezone using tzload() not pg_tzset(), so we don't fill
478  * the cache. Also, don't ask for the canonical spelling: we already
479  * know it, and pg_open_tzfile's way of finding it out is pretty
480  * inefficient.
481  */
482  if (tzload(fullname + dir->baselen, NULL, &dir->tz.state, true) != 0)
483  {
484  /* Zone could not be loaded, ignore it */
485  continue;
486  }
487 
488  if (!pg_tz_acceptable(&dir->tz))
489  {
490  /* Ignore leap-second zones */
491  continue;
492  }
493 
494  /* OK, return the canonical zone name spelling. */
495  strlcpy(dir->tz.TZname, fullname + dir->baselen,
496  sizeof(dir->tz.TZname));
497 
498  /* Timezone loaded OK. */
499  return &dir->tz;
500  }
501 
502  /* Nothing more found */
503  return NULL;
504 }
struct pg_tz tz
Definition: pgtz.c:393
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:556
char * pstrdup(const char *in)
Definition: mcxt.c:1076
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:391
void pfree(void *pointer)
Definition: mcxt.c:949
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:392
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define MAX_TZDIR_DEPTH
Definition: pgtz.c:385
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2596
#define ereport(elevel, rest)
Definition: elog.h:122
#define stat(a, b)
Definition: win32_port.h:266
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1839
struct state state
Definition: pgtz.h:63
int baselen
Definition: pgtz.c:389
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2662
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:62
#define S_ISDIR(m)
Definition: win32_port.h:307
int errmsg(const char *fmt,...)
Definition: elog.c:797
int depth
Definition: pgtz.c:390
int FreeDir(DIR *dir)
Definition: fd.c:2714

◆ pg_tzenumerate_start()

pg_tzenum* pg_tzenumerate_start ( void  )

Definition at line 399 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().

400 {
401  pg_tzenum *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
402  char *startdir = pstrdup(pg_TZDIR());
403 
404  ret->baselen = strlen(startdir) + 1;
405  ret->depth = 0;
406  ret->dirname[0] = startdir;
407  ret->dirdesc[0] = AllocateDir(startdir);
408  if (!ret->dirdesc[0])
409  ereport(ERROR,
411  errmsg("could not open directory \"%s\": %m", startdir)));
412  return ret;
413 }
char * pstrdup(const char *in)
Definition: mcxt.c:1076
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:391
static const char * pg_TZDIR(void)
Definition: pgtz.c:43
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:392
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2596
#define ereport(elevel, rest)
Definition: elog.h:122
void * palloc0(Size size)
Definition: mcxt.c:877
int baselen
Definition: pgtz.c:389
int errmsg(const char *fmt,...)
Definition: elog.c:797
int depth
Definition: pgtz.c:390

◆ pg_tzset()

pg_tz* pg_tzset ( const char *  tzname)

Definition at line 236 of file pgtz.c.

References elog, ERROR, HASH_ENTER, HASH_FIND, hash_search(), init_timezone_hashtable(), 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().

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

pg_tz* pg_tzset_offset ( long  gmtoffset)

Definition at line 322 of file pgtz.c.

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

Referenced by check_timezone().

323 {
324  long absoffset = (gmtoffset < 0) ? -gmtoffset : gmtoffset;
325  char offsetstr[64];
326  char tzname[128];
327 
328  snprintf(offsetstr, sizeof(offsetstr),
329  "%02ld", absoffset / SECS_PER_HOUR);
330  absoffset %= SECS_PER_HOUR;
331  if (absoffset != 0)
332  {
333  snprintf(offsetstr + strlen(offsetstr),
334  sizeof(offsetstr) - strlen(offsetstr),
335  ":%02ld", absoffset / SECS_PER_MINUTE);
336  absoffset %= SECS_PER_MINUTE;
337  if (absoffset != 0)
338  snprintf(offsetstr + strlen(offsetstr),
339  sizeof(offsetstr) - strlen(offsetstr),
340  ":%02ld", absoffset);
341  }
342  if (gmtoffset > 0)
343  snprintf(tzname, sizeof(tzname), "<-%s>+%s",
344  offsetstr, offsetstr);
345  else
346  snprintf(tzname, sizeof(tzname), "<+%s>-%s",
347  offsetstr, offsetstr);
348 
349  return pg_tzset(tzname);
350 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define SECS_PER_MINUTE
Definition: timestamp.h:88
pg_tz * pg_tzset(const char *name)
Definition: pgtz.c:236
#define SECS_PER_HOUR
Definition: timestamp.h:87

Variable Documentation

◆ log_timezone

◆ session_timezone