
Go to the source code of this file.
Data Structures | |
| struct | pg_tm |
Defines | |
| #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_tm * | pg_localtime (const pg_time_t *timep, const pg_tz *tz) |
| struct pg_tm * | pg_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) |
| size_t | pg_strftime (char *s, size_t max, const char *format, const struct pg_tm *tm) |
| 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) |
| void | pg_timezone_initialize (void) |
| pg_tz * | pg_tzset (const char *tzname) |
| pg_tzenum * | pg_tzenumerate_start (void) |
| pg_tz * | pg_tzenumerate_next (pg_tzenum *dir) |
| void | pg_tzenumerate_end (pg_tzenum *dir) |
Variables | |
| pg_tz * | session_timezone |
| pg_tz * | log_timezone |
| #define TZ_STRLEN_MAX 255 |
Definition at line 44 of file pgtime.h.
Referenced by identify_system_timezone(), init_timezone_hashtable(), pg_load_tz(), pg_open_tzfile(), pg_tzset(), scan_available_timezones(), score_timezone(), timestamp_zone(), timestamptz_zone(), and timetz_zone().
| const char* pg_get_timezone_name | ( | pg_tz * | tz | ) |
Definition at line 1476 of file localtime.c.
References pg_tz::TZname.
Referenced by pg_timezone_names(), show_log_timezone(), and show_timezone().
{
if (tz)
return tz->TZname;
return NULL;
}
Definition at line 1452 of file localtime.c.
References i, pg_tz::state, ttinfo::tt_gmtoff, state::ttis, and state::typecnt.
Referenced by DecodeTimeOnly().
{
/*
* The zone could have more than one ttinfo, if it's historically used
* more than one abbreviation. We return TRUE as long as they all have
* the same gmtoff.
*/
const struct state *sp;
int i;
sp = &tz->state;
for (i = 1; i < sp->typecnt; i++)
{
if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
return false;
}
*gmtoff = sp->ttis[0].tt_gmtoff;
return true;
}
Definition at line 1127 of file localtime.c.
Referenced by abstime2tm(), and GetEpochTime().
Definition at line 1092 of file localtime.c.
References localsub(), 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().
| 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 1315 of file localtime.c.
References state::ats, state::goahead, state::goback, i, pg_next_dst_boundary(), pg_tz::state, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.
Referenced by DetermineTimeZoneOffset(), and pg_next_dst_boundary().
{
const struct state *sp;
const struct ttinfo *ttisp;
int i;
int j;
const pg_time_t t = *timep;
sp = &tz->state;
if (sp->timecnt == 0)
{
/* non-DST zone, use lowest-numbered standard type */
i = 0;
while (sp->ttis[i].tt_isdst)
if (++i >= sp->typecnt)
{
i = 0;
break;
}
ttisp = &sp->ttis[i];
*before_gmtoff = ttisp->tt_gmtoff;
*before_isdst = ttisp->tt_isdst;
return 0;
}
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1]))
{
/* For values outside the transition table, extrapolate */
pg_time_t newt = t;
pg_time_t seconds;
pg_time_t tcycles;
int64 icycles;
int result;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
else
seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
++tcycles;
icycles = tcycles;
if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
return -1;
seconds = icycles;
seconds *= YEARSPERREPEAT;
seconds *= AVGSECSPERYEAR;
if (t < sp->ats[0])
newt += seconds;
else
newt -= seconds;
if (newt < sp->ats[0] ||
newt > sp->ats[sp->timecnt - 1])
return -1; /* "cannot happen" */
result = pg_next_dst_boundary(&newt, before_gmtoff,
before_isdst,
boundary,
after_gmtoff,
after_isdst,
tz);
if (t < sp->ats[0])
*boundary -= seconds;
else
*boundary += seconds;
return result;
}
if (t >= sp->ats[sp->timecnt - 1])
{
/* No known transition > t, so use last known segment's type */
i = sp->types[sp->timecnt - 1];
ttisp = &sp->ttis[i];
*before_gmtoff = ttisp->tt_gmtoff;
*before_isdst = ttisp->tt_isdst;
return 0;
}
if (t < sp->ats[0])
{
/* For "before", use lowest-numbered standard type */
i = 0;
while (sp->ttis[i].tt_isdst)
if (++i >= sp->typecnt)
{
i = 0;
break;
}
ttisp = &sp->ttis[i];
*before_gmtoff = ttisp->tt_gmtoff;
*before_isdst = ttisp->tt_isdst;
*boundary = sp->ats[0];
/* And for "after", use the first segment's type */
i = sp->types[0];
ttisp = &sp->ttis[i];
*after_gmtoff = ttisp->tt_gmtoff;
*after_isdst = ttisp->tt_isdst;
return 1;
}
/* Else search to find the boundary following t */
{
int lo = 1;
int hi = sp->timecnt - 1;
while (lo < hi)
{
int mid = (lo + hi) >> 1;
if (t < sp->ats[mid])
hi = mid;
else
lo = mid + 1;
}
i = lo;
}
j = sp->types[i - 1];
ttisp = &sp->ttis[j];
*before_gmtoff = ttisp->tt_gmtoff;
*before_isdst = ttisp->tt_isdst;
*boundary = sp->ats[i];
j = sp->types[i];
ttisp = &sp->ttis[j];
*after_gmtoff = ttisp->tt_gmtoff;
*after_isdst = ttisp->tt_isdst;
return 1;
}
| size_t pg_strftime | ( | char * | s, | |
| size_t | max, | |||
| const char * | format, | |||
| const struct pg_tm * | tm | |||
| ) |
Definition at line 105 of file strftime.c.
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().
| void pg_timezone_initialize | ( | void | ) |
Definition at line 302 of file pgtz.c.
References pg_tzset().
Referenced by InitializeGUCOptions().
{
/*
* We may not yet know where PGSHAREDIR is (in particular this is true in
* an EXEC_BACKEND subprocess). So use "GMT", which pg_tzset forces to be
* interpreted without reference to the filesystem. This corresponds to
* the bootstrap default for these variables in guc.c, although in
* principle it could be different.
*/
session_timezone = pg_tzset("GMT");
log_timezone = session_timezone;
}
Definition at line 1491 of file localtime.c.
References pg_localtime(), POSTGRES_EPOCH_JDATE, SECS_PER_DAY, and pg_tm::tm_sec.
Referenced by check_log_timezone(), check_timezone(), pg_tzenumerate_next(), score_timezone(), and validate_zone().
{
struct pg_tm *tt;
pg_time_t time2000;
/*
* To detect leap-second timekeeping, run pg_localtime for what should be
* GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
* other result has to be due to leap seconds.
*/
time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
tt = pg_localtime(&time2000, tz);
if (!tt || tt->tm_sec != 0)
return false;
return true;
}
| void pg_tzenumerate_end | ( | pg_tzenum * | dir | ) |
Definition at line 355 of file pgtz.c.
References pg_tzenum::depth, pg_tzenum::dirdesc, pg_tzenum::dirname, FreeDir(), and pfree().
Referenced by pg_timezone_names().
Definition at line 367 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, TRUE, pg_tzenum::tz, tzload(), and pg_tz::TZname.
Referenced by pg_timezone_names().
{
while (dir->depth >= 0)
{
struct dirent *direntry;
char fullname[MAXPGPATH];
struct stat statbuf;
direntry = ReadDir(dir->dirdesc[dir->depth], dir->dirname[dir->depth]);
if (!direntry)
{
/* End of this directory */
FreeDir(dir->dirdesc[dir->depth]);
pfree(dir->dirname[dir->depth]);
dir->depth--;
continue;
}
if (direntry->d_name[0] == '.')
continue;
snprintf(fullname, MAXPGPATH, "%s/%s",
dir->dirname[dir->depth], direntry->d_name);
if (stat(fullname, &statbuf) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat \"%s\": %m", fullname)));
if (S_ISDIR(statbuf.st_mode))
{
/* Step into the subdirectory */
if (dir->depth >= MAX_TZDIR_DEPTH - 1)
ereport(ERROR,
(errmsg_internal("timezone directory stack overflow")));
dir->depth++;
dir->dirname[dir->depth] = pstrdup(fullname);
dir->dirdesc[dir->depth] = AllocateDir(fullname);
if (!dir->dirdesc[dir->depth])
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m",
fullname)));
/* Start over reading in the new directory */
continue;
}
/*
* Load this timezone using tzload() not pg_tzset(), so we don't fill
* the cache
*/
if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state,
TRUE) != 0)
{
/* Zone could not be loaded, ignore it */
continue;
}
if (!pg_tz_acceptable(&dir->tz))
{
/* Ignore leap-second zones */
continue;
}
/* Timezone loaded OK. */
return &dir->tz;
}
/* Nothing more found */
return NULL;
}
| pg_tzenum* pg_tzenumerate_start | ( | void | ) |
Definition at line 338 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().
{
pg_tzenum *ret = (pg_tzenum *) palloc0(sizeof(pg_tzenum));
char *startdir = pstrdup(pg_TZDIR());
ret->baselen = strlen(startdir) + 1;
ret->depth = 0;
ret->dirname[0] = startdir;
ret->dirdesc[0] = AllocateDir(startdir);
if (!ret->dirdesc[0])
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m", startdir)));
return ret;
}
| pg_tz* pg_tzset | ( | const char * | tzname | ) |
Definition at line 218 of file pgtz.c.
References elog, ERROR, FALSE, HASH_ENTER, HASH_FIND, hash_search(), init_timezone_hashtable(), NULL, pg_toupper(), pg_tz::state, TRUE, pg_tz_cache::tz, TZ_STRLEN_MAX, tzload(), pg_tz::TZname, and tzparse().
Referenced by check_log_timezone(), check_timezone(), DecodeDateTime(), DecodeTimeOnly(), pg_timezone_initialize(), timestamp_zone(), timestamptz_zone(), and timetz_zone().
{
pg_tz_cache *tzp;
struct state tzstate;
char uppername[TZ_STRLEN_MAX + 1];
char canonname[TZ_STRLEN_MAX + 1];
char *p;
if (strlen(name) > TZ_STRLEN_MAX)
return NULL; /* not going to fit */
if (!timezone_cache)
if (!init_timezone_hashtable())
return NULL;
/*
* Upcase the given name to perform a case-insensitive hashtable search.
* (We could alternatively downcase it, but we prefer upcase so that we
* can get consistently upcased results from tzparse() in case the name is
* a POSIX-style timezone spec.)
*/
p = uppername;
while (*name)
*p++ = pg_toupper((unsigned char) *name++);
*p = '\0';
tzp = (pg_tz_cache *) hash_search(timezone_cache,
uppername,
HASH_FIND,
NULL);
if (tzp)
{
/* Timezone found in cache, nothing more to do */
return &tzp->tz;
}
/*
* "GMT" is always sent to tzparse(), as per discussion above.
*/
if (strcmp(uppername, "GMT") == 0)
{
if (tzparse(uppername, &tzstate, TRUE) != 0)
{
/* This really, really should not happen ... */
elog(ERROR, "could not initialize GMT time zone");
}
/* Use uppercase name as canonical */
strcpy(canonname, uppername);
}
else if (tzload(uppername, canonname, &tzstate, TRUE) != 0)
{
if (uppername[0] == ':' || tzparse(uppername, &tzstate, FALSE) != 0)
{
/* Unknown timezone. Fail our call instead of loading GMT! */
return NULL;
}
/* For POSIX timezone specs, use uppercase name as canonical */
strcpy(canonname, uppername);
}
/* Save timezone in the cache */
tzp = (pg_tz_cache *) hash_search(timezone_cache,
uppername,
HASH_ENTER,
NULL);
/* hash_search already copied uppername into the hash key */
strcpy(tzp->tz.TZname, canonname);
memcpy(&tzp->tz.state, &tzstate, sizeof(tzstate));
return &tzp->tz;
}
Definition at line 30 of file pgtz.c.
Referenced by assign_log_timezone(), do_pg_start_backup(), do_pg_stop_backup(), log_line_prefix(), logfile_getname(), set_next_rotation_time(), setup_formatted_log_time(), setup_formatted_start_time(), show_log_timezone(), and str_time().
Definition at line 27 of file pgtz.c.
Referenced by abstime2tm(), assign_timezone(), check_timezone(), date2timestamptz(), DecodeDateTime(), DecodeTimeOnly(), DetermineTimeZoneOffset(), show_timezone(), time_timetz(), timeofday(), timestamp2timestamptz(), timestamp2tm(), timestamp_abstime(), timestamptz_pl_interval(), timestamptz_trunc(), and to_timestamp().
1.7.1