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