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

References NULL, and pg_tz::TZname.

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

1831 {
1832  if (tz)
1833  return tz->TZname;
1834  return NULL;
1835 }
#define NULL
Definition: c.h:229
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 1806 of file localtime.c.

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

Referenced by DecodeTimeOnly().

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

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

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

Referenced by DetermineTimeZoneOffsetInternal().

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

124 {
125  char *p;
126  int warn;
127 
128  warn = IN_NONE;
129  p = _fmt(format, t, s, s + maxsize, &warn);
130  if (p == s + maxsize)
131  return 0;
132  *p = '\0';
133  return p - s;
134 }
static char * _fmt(const char *, const struct pg_tm *, char *, const char *, int *)
Definition: strftime.c:137
static char format
Definition: pg_basebackup.c:80
#define IN_NONE
Definition: strftime.c:115
static void warn(void)
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 1845 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().

1846 {
1847  struct pg_tm *tt;
1848  pg_time_t time2000;
1849 
1850  /*
1851  * To detect leap-second timekeeping, run pg_localtime for what should be
1852  * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
1853  * other result has to be due to leap seconds.
1854  */
1856  tt = pg_localtime(&time2000, tz);
1857  if (!tt || tt->tm_sec != 0)
1858  return false;
1859 
1860  return true;
1861 }
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:950
char * dirname[MAX_TZDIR_DEPTH]
Definition: pgtz.c:399
int depth
Definition: pgtz.c:397
int FreeDir(DIR *dir)
Definition: fd.c:2444
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, NULL, 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:1077
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:950
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:2335
#define ereport(elevel, rest)
Definition: elog.h:122
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1845
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
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
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:2444
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:1077
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:2335
#define ereport(elevel, rest)
Definition: elog.h:122
void * palloc0(Size size)
Definition: mcxt.c:878
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(), 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().

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
#define NULL
Definition: c.h:229
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