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

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

Definition at line 370 of file pgtz.c.

References pg_tzset(), and session_timezone.

Referenced by InitializeGUCOptions().

371 {
372  /*
373  * We may not yet know where PGSHAREDIR is (in particular this is true in
374  * an EXEC_BACKEND subprocess). So use "GMT", which pg_tzset forces to be
375  * interpreted without reference to the filesystem. This corresponds to
376  * the bootstrap default for these variables in guc.c, although in
377  * principle it could be different.
378  */
379  session_timezone = pg_tzset("GMT");
381 }
pg_tz * log_timezone
Definition: pgtz.c:31
pg_tz * pg_tzset(const char *name)
Definition: pgtz.c:243
pg_tz * session_timezone
Definition: pgtz.c:28
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
void pg_tzenumerate_end ( pg_tzenum dir)

Definition at line 423 of file pgtz.c.

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

Referenced by pg_timezone_names().

424 {
425  while (dir->depth >= 0)
426  {
427  FreeDir(dir->dirdesc[dir->depth]);
428  pfree(dir->dirname[dir->depth]);
429  dir->depth--;
430  }
431  pfree(dir);
432 }
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:398
void pfree(void *pointer)
Definition: mcxt.c:949
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:399
int depth
Definition: pgtz.c:397
int FreeDir(DIR *dir)
Definition: fd.c:2476
pg_tz* pg_tzenumerate_next ( pg_tzenum dir)

Definition at line 435 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(), snprintf(), pg_tz::state, strlcpy(), pg_tzenum::tz, tzload(), and pg_tz::TZname.

Referenced by pg_timezone_names().

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

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

407 {
408  pg_tzenum *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
409  char *startdir = pstrdup(pg_TZDIR());
410 
411  ret->baselen = strlen(startdir) + 1;
412  ret->depth = 0;
413  ret->dirname[0] = startdir;
414  ret->dirdesc[0] = AllocateDir(startdir);
415  if (!ret->dirdesc[0])
416  ereport(ERROR,
418  errmsg("could not open directory \"%s\": %m", startdir)));
419  return ret;
420 }
char * pstrdup(const char *in)
Definition: mcxt.c:1076
DIR * dirdesc[MAX_TZDIR_DEPTH]
Definition: pgtz.c:398
static const char * pg_TZDIR(void)
Definition: pgtz.c:43
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:399
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2367
#define ereport(elevel, rest)
Definition: elog.h:122
void * palloc0(Size size)
Definition: mcxt.c:877
int baselen
Definition: pgtz.c:396
int errmsg(const char *fmt,...)
Definition: elog.c:797
int depth
Definition: pgtz.c:397
pg_tz* pg_tzset ( const char *  tzname)

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

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

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

Referenced by check_timezone().

330 {
331  long absoffset = (gmtoffset < 0) ? -gmtoffset : gmtoffset;
332  char offsetstr[64];
333  char tzname[128];
334 
335  snprintf(offsetstr, sizeof(offsetstr),
336  "%02ld", absoffset / SECS_PER_HOUR);
337  absoffset %= SECS_PER_HOUR;
338  if (absoffset != 0)
339  {
340  snprintf(offsetstr + strlen(offsetstr),
341  sizeof(offsetstr) - strlen(offsetstr),
342  ":%02ld", absoffset / SECS_PER_MINUTE);
343  absoffset %= SECS_PER_MINUTE;
344  if (absoffset != 0)
345  snprintf(offsetstr + strlen(offsetstr),
346  sizeof(offsetstr) - strlen(offsetstr),
347  ":%02ld", absoffset);
348  }
349  if (gmtoffset > 0)
350  snprintf(tzname, sizeof(tzname), "<-%s>+%s",
351  offsetstr, offsetstr);
352  else
353  snprintf(tzname, sizeof(tzname), "<+%s>-%s",
354  offsetstr, offsetstr);
355 
356  return pg_tzset(tzname);
357 }
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:243
#define SECS_PER_HOUR
Definition: timestamp.h:87

Variable Documentation