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_timezone_abbrev_is_known (const char *abbrev, bool *isfixed, long int *gmtoff, int *isdst, const pg_tz *tz)
 
const char * pg_get_next_timezone_abbrev (int *indx, 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 50 of file pgtime.h.

◆ pg_tzenum

typedef struct pg_tzenum pg_tzenum

Definition at line 51 of file pgtime.h.

Function Documentation

◆ pg_get_next_timezone_abbrev()

const char * pg_get_next_timezone_abbrev ( int *  indx,
const pg_tz tz 
)

Definition at line 1936 of file localtime.c.

1938{
1939 const char *result;
1940 const struct state *sp = &tz->state;
1941 const char *abbrs;
1942 int abbrind;
1943
1944 /* If we're still in range, the result is the current abbrev. */
1945 abbrs = sp->chars;
1946 abbrind = *indx;
1947 if (abbrind < 0 || abbrind >= sp->charcnt)
1948 return NULL;
1949 result = abbrs + abbrind;
1950
1951 /* Advance *indx past this abbrev and its trailing null. */
1952 while (abbrs[abbrind] != '\0')
1953 abbrind++;
1954 abbrind++;
1955 *indx = abbrind;
1956
1957 return result;
1958}
struct state state
Definition: pgtz.h:69
Definition: regguts.h:323
int charcnt
Definition: pgtz.h:46
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 4),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53

References state::charcnt, state::chars, and pg_tz::state.

Referenced by pg_timezone_abbrevs_zone().

◆ pg_get_timezone_name()

const char * pg_get_timezone_name ( pg_tz tz)

Definition at line 1989 of file localtime.c.

1990{
1991 if (tz)
1992 return tz->TZname;
1993 return NULL;
1994}
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 1965 of file localtime.c.

1966{
1967 /*
1968 * The zone could have more than one ttinfo, if it's historically used
1969 * more than one abbreviation. We return true as long as they all have
1970 * the same gmtoff.
1971 */
1972 const struct state *sp;
1973 int i;
1974
1975 sp = &tz->state;
1976 for (i = 1; i < sp->typecnt; i++)
1977 {
1978 if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
1979 return false;
1980 }
1981 *gmtoff = sp->ttis[0].tt_utoff;
1982 return true;
1983}
int i
Definition: isn.c:77
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 1743 of file localtime.c.

1748{
1749 const struct state *sp;
1750 const char *abbrs;
1751 const struct ttinfo *ttisp;
1752 int abbrind;
1753 int cutoff;
1754 int i;
1755 const pg_time_t t = *timep;
1756
1757 sp = &tz->state;
1758
1759 /*
1760 * Locate the abbreviation in the zone's abbreviation list. We assume
1761 * there are not duplicates in the list.
1762 */
1763 abbrs = sp->chars;
1764 abbrind = 0;
1765 while (abbrind < sp->charcnt)
1766 {
1767 if (strcmp(abbrev, abbrs + abbrind) == 0)
1768 break;
1769 while (abbrs[abbrind] != '\0')
1770 abbrind++;
1771 abbrind++;
1772 }
1773 if (abbrind >= sp->charcnt)
1774 return false; /* not there! */
1775
1776 /*
1777 * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1778 * (goback/goahead zones). Finding the newest or oldest meaning of the
1779 * abbreviation should get us what we want, since extrapolation would just
1780 * be repeating the newest or oldest meanings.
1781 *
1782 * Use binary search to locate the first transition > cutoff time. (Note
1783 * that sp->timecnt could be zero, in which case this loop does nothing
1784 * and only the defaulttype entry will be checked.)
1785 */
1786 {
1787 int lo = 0;
1788 int hi = sp->timecnt;
1789
1790 while (lo < hi)
1791 {
1792 int mid = (lo + hi) >> 1;
1793
1794 if (t < sp->ats[mid])
1795 hi = mid;
1796 else
1797 lo = mid + 1;
1798 }
1799 cutoff = lo;
1800 }
1801
1802 /*
1803 * Scan backwards to find the latest interval using the given abbrev
1804 * before the cutoff time.
1805 */
1806 for (i = cutoff - 1; i >= 0; i--)
1807 {
1808 ttisp = &sp->ttis[sp->types[i]];
1809 if (ttisp->tt_desigidx == abbrind)
1810 {
1811 *gmtoff = ttisp->tt_utoff;
1812 *isdst = ttisp->tt_isdst;
1813 return true;
1814 }
1815 }
1816
1817 /*
1818 * Not found yet; check the defaulttype, which is notionally the era
1819 * before any of the entries in sp->types[].
1820 */
1821 ttisp = &sp->ttis[sp->defaulttype];
1822 if (ttisp->tt_desigidx == abbrind)
1823 {
1824 *gmtoff = ttisp->tt_utoff;
1825 *isdst = ttisp->tt_isdst;
1826 return true;
1827 }
1828
1829 /*
1830 * Not there, so scan forwards to find the first one after the cutoff.
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
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
int defaulttype
Definition: pgtz.h:61
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, state::defaulttype, i, pg_tz::state, state::timecnt, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, and state::types.

Referenced by DetermineTimeZoneAbbrevOffsetInternal(), and pg_timezone_abbrevs_zone().

◆ 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(), pg_tz_acceptable(), 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 the defaulttype */
1628 ttisp = &sp->ttis[sp->defaulttype];
1629 *before_gmtoff = ttisp->tt_utoff;
1630 *before_isdst = ttisp->tt_isdst;
1631 return 0;
1632 }
1633 if ((sp->goback && t < sp->ats[0]) ||
1634 (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1635 {
1636 /* For values outside the transition table, extrapolate */
1637 pg_time_t newt = t;
1638 pg_time_t seconds;
1639 pg_time_t tcycles;
1640 int64 icycles;
1641 int result;
1642
1643 if (t < sp->ats[0])
1644 seconds = sp->ats[0] - t;
1645 else
1646 seconds = t - sp->ats[sp->timecnt - 1];
1647 --seconds;
1648 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1649 ++tcycles;
1650 icycles = tcycles;
1651 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1652 return -1;
1653 seconds = icycles;
1654 seconds *= YEARSPERREPEAT;
1655 seconds *= AVGSECSPERYEAR;
1656 if (t < sp->ats[0])
1657 newt += seconds;
1658 else
1659 newt -= seconds;
1660 if (newt < sp->ats[0] ||
1661 newt > sp->ats[sp->timecnt - 1])
1662 return -1; /* "cannot happen" */
1663
1664 result = pg_next_dst_boundary(&newt, before_gmtoff,
1665 before_isdst,
1666 boundary,
1667 after_gmtoff,
1668 after_isdst,
1669 tz);
1670 if (t < sp->ats[0])
1671 *boundary -= seconds;
1672 else
1673 *boundary += seconds;
1674 return result;
1675 }
1676
1677 if (t >= sp->ats[sp->timecnt - 1])
1678 {
1679 /* No known transition > t, so use last known segment's type */
1680 i = sp->types[sp->timecnt - 1];
1681 ttisp = &sp->ttis[i];
1682 *before_gmtoff = ttisp->tt_utoff;
1683 *before_isdst = ttisp->tt_isdst;
1684 return 0;
1685 }
1686 if (t < sp->ats[0])
1687 {
1688 /* For "before", use the defaulttype */
1689 ttisp = &sp->ttis[sp->defaulttype];
1690 *before_gmtoff = ttisp->tt_utoff;
1691 *before_isdst = ttisp->tt_isdst;
1692 *boundary = sp->ats[0];
1693 /* And for "after", use the first segment's type */
1694 i = sp->types[0];
1695 ttisp = &sp->ttis[i];
1696 *after_gmtoff = ttisp->tt_utoff;
1697 *after_isdst = ttisp->tt_isdst;
1698 return 1;
1699 }
1700 /* Else search to find the boundary following t */
1701 {
1702 int lo = 1;
1703 int hi = sp->timecnt - 1;
1704
1705 while (lo < hi)
1706 {
1707 int mid = (lo + hi) >> 1;
1708
1709 if (t < sp->ats[mid])
1710 hi = mid;
1711 else
1712 lo = mid + 1;
1713 }
1714 i = lo;
1715 }
1716 j = sp->types[i - 1];
1717 ttisp = &sp->ttis[j];
1718 *before_gmtoff = ttisp->tt_utoff;
1719 *before_isdst = ttisp->tt_isdst;
1720 *boundary = sp->ats[i];
1721 j = sp->types[i];
1722 ttisp = &sp->ttis[j];
1723 *after_gmtoff = ttisp->tt_utoff;
1724 *after_isdst = ttisp->tt_isdst;
1725 return 1;
1726}
int64_t int64
Definition: c.h:499
int j
Definition: isn.c:78
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::defaulttype, state::goahead, state::goback, i, j, pg_next_dst_boundary(), pg_tz::state, state::timecnt, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, 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_abbrev_is_known()

bool pg_timezone_abbrev_is_known ( const char *  abbrev,
bool *  isfixed,
long int *  gmtoff,
int *  isdst,
const pg_tz tz 
)

Definition at line 1861 of file localtime.c.

1866{
1867 bool result = false;
1868 const struct state *sp = &tz->state;
1869 const char *abbrs;
1870 int abbrind;
1871
1872 /*
1873 * Locate the abbreviation in the zone's abbreviation list. We assume
1874 * there are not duplicates in the list.
1875 */
1876 abbrs = sp->chars;
1877 abbrind = 0;
1878 while (abbrind < sp->charcnt)
1879 {
1880 if (strcmp(abbrev, abbrs + abbrind) == 0)
1881 break;
1882 while (abbrs[abbrind] != '\0')
1883 abbrind++;
1884 abbrind++;
1885 }
1886 if (abbrind >= sp->charcnt)
1887 return false; /* definitely not there */
1888
1889 /*
1890 * Scan the ttinfo array to find uses of the abbreviation.
1891 */
1892 for (int i = 0; i < sp->typecnt; i++)
1893 {
1894 const struct ttinfo *ttisp = &sp->ttis[i];
1895
1896 if (ttisp->tt_desigidx == abbrind)
1897 {
1898 if (!result)
1899 {
1900 /* First usage */
1901 *isfixed = true; /* for the moment */
1902 *gmtoff = ttisp->tt_utoff;
1903 *isdst = ttisp->tt_isdst;
1904 result = true;
1905 }
1906 else
1907 {
1908 /* Second or later usage, does it match? */
1909 if (*gmtoff != ttisp->tt_utoff ||
1910 *isdst != ttisp->tt_isdst)
1911 {
1912 *isfixed = false;
1913 break; /* no point in looking further */
1914 }
1915 }
1916 }
1917 }
1918
1919 return result;
1920}

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

Referenced by TimeZoneAbbrevIsKnown().

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

2005{
2006 struct pg_tm *tt;
2007 pg_time_t time2000;
2008
2009 /*
2010 * To detect leap-second timekeeping, run pg_localtime for what should be
2011 * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
2012 * other result has to be due to leap seconds.
2013 */
2015 tt = pg_localtime(&time2000, tz);
2016 if (!tt || tt->tm_sec != 0)
2017 return false;
2018
2019 return true;
2020}
#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

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

◆ 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:3025
void pfree(void *pointer)
Definition: mcxt.c:2147
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)
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])
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:1158
int errcode_for_file_access(void)
Definition: elog.c:877
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2907
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2973
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:547
@ 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:2322
#define MAXPGPATH
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:2004
#define MAX_TZDIR_DEPTH
Definition: pgtz.c:383
#define snprintf
Definition: port.h:239
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])
409 errmsg("could not open directory \"%s\": %m", startdir)));
410 return ret;
411}
void * palloc0(Size size)
Definition: mcxt.c:1970
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,
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:226
@ 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