Index: backend/commands/variable.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/variable.c,v retrieving revision 1.105 diff -c -r1.105 variable.c *** backend/commands/variable.c 31 Dec 2004 21:59:42 -0000 1.105 --- backend/commands/variable.c 1 Mar 2005 17:47:56 -0000 *************** *** 315,327 **** * UNKNOWN as the canonical spelling. * * During GUC initialization, since the timezone library isn't ! * set up yet, pg_get_current_timezone will return NULL and we * will leave the setting as UNKNOWN. If this isn't * overridden from the config file then * pg_timezone_initialize() will eventually select a default * value from the environment. */ ! const char *curzone = pg_get_current_timezone(); if (curzone) value = curzone; --- 315,327 ---- * UNKNOWN as the canonical spelling. * * During GUC initialization, since the timezone library isn't ! * set up yet, pg_get_timezone_name will return NULL and we * will leave the setting as UNKNOWN. If this isn't * overridden from the config file then * pg_timezone_initialize() will eventually select a default * value from the environment. */ ! const char *curzone = pg_get_timezone_name(global_timezone); if (curzone) value = curzone; *************** *** 329,418 **** else { /* ! * Otherwise assume it is a timezone name. ! * ! * We have to actually apply the change before we can have any ! * hope of checking it. So, save the old value in case we ! * have to back out. We have to copy since ! * pg_get_current_timezone returns a pointer to its static ! * state. ! * ! * This would all get a lot simpler if the TZ library had a ! * better API that would let us look up and test a timezone ! * name without making it the default. */ ! const char *cur_tz; ! char *save_tz; ! bool known, ! acceptable; ! ! cur_tz = pg_get_current_timezone(); ! if (cur_tz) ! save_tz = pstrdup(cur_tz); ! else ! save_tz = NULL; ! known = pg_tzset(value); ! acceptable = known ? tz_acceptable() : false; ! if (doit && known && acceptable) { ! /* Keep the changed TZ */ ! HasCTZSet = false; } ! else { ! /* ! * Revert to prior TZ setting; note we haven't changed ! * HasCTZSet in this path, so if we were previously using ! * a fixed offset, we still are. ! */ ! if (save_tz) ! pg_tzset(save_tz); ! else ! { ! /* ! * TZ library wasn't initialized yet. Annoyingly, we ! * will come here during startup because guc-file.l ! * checks the value with doit = false before actually ! * applying. The best approach seems to be as follows: ! * ! * 1. known && acceptable: leave the setting in place, ! * since we'll apply it soon anyway. This is mainly ! * so that any log messages printed during this ! * interval are timestamped with the user's requested ! * timezone. ! * ! * 2. known && !acceptable: revert to GMT for lack of any ! * better idea. (select_default_timezone() may get ! * called later to undo this.) ! * ! * 3. !known: no need to do anything since TZ library did ! * not change its state. ! * ! * Again, this should all go away sometime soon. ! */ ! if (known && !acceptable) ! pg_tzset("GMT"); ! } ! /* Complain if it was bad */ ! if (!known) ! { ! ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("unrecognized time zone name: \"%s\"", ! value))); ! return NULL; ! } ! if (!acceptable) ! { ! ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" appears to use leap seconds", ! value), ! errdetail("PostgreSQL does not support leap seconds."))); ! return NULL; ! } } } } --- 329,364 ---- else { /* ! * Otherwise assume it is a timezone name, and try to load it. */ ! pg_tz *new_tz; ! new_tz = pg_tzset(value); ! if (!new_tz) { ! ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("unrecognized time zone name: \"%s\"", ! value))); ! return NULL; ! } ! ! if (!tz_acceptable(new_tz)) ! { ! ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, ! (errcode(ERRCODE_INVALID_PARAMETER_VALUE), ! errmsg("time zone \"%s\" appears to use leap seconds", ! value), ! errdetail("PostgreSQL does not support leap seconds."))); ! return NULL; } ! ! if (doit) { ! /* Save the changed TZ */ ! global_timezone = new_tz; ! HasCTZSet = false; } } } *************** *** 459,465 **** IntervalPGetDatum(&interval))); } else ! tzn = pg_get_current_timezone(); if (tzn != NULL) return tzn; --- 405,411 ---- IntervalPGetDatum(&interval))); } else ! tzn = pg_get_timezone_name(global_timezone); if (tzn != NULL) return tzn; Index: backend/postmaster/syslogger.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/syslogger.c,v retrieving revision 1.12 diff -c -r1.12 syslogger.c *** backend/postmaster/syslogger.c 1 Jan 2005 20:44:16 -0000 1.12 --- backend/postmaster/syslogger.c 27 Feb 2005 17:18:50 -0000 *************** *** 852,858 **** if (strchr(Log_filename, '%')) { /* treat it as a strftime pattern */ ! tm = pg_localtime(×tamp); pg_strftime(filename + len, MAXPGPATH - len, Log_filename, tm); } else --- 852,858 ---- if (strchr(Log_filename, '%')) { /* treat it as a strftime pattern */ ! tm = pg_localtime(×tamp, global_timezone); pg_strftime(filename + len, MAXPGPATH - len, Log_filename, tm); } else *************** *** 887,893 **** */ rotinterval = Log_RotationAge * 60; /* convert to seconds */ now = time(NULL); ! tm = pg_localtime(&now); now += tm->tm_gmtoff; now -= now % rotinterval; now += rotinterval; --- 887,893 ---- */ rotinterval = Log_RotationAge * 60; /* convert to seconds */ now = time(NULL); ! tm = pg_localtime(&now, global_timezone); now += tm->tm_gmtoff; now -= now % rotinterval; now += rotinterval; Index: backend/utils/adt/datetime.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/datetime.c,v retrieving revision 1.137 diff -c -r1.137 datetime.c *** backend/utils/adt/datetime.c 11 Jan 2005 18:33:45 -0000 1.137 --- backend/utils/adt/datetime.c 28 Feb 2005 19:57:12 -0000 *************** *** 1634,1640 **** res = pg_next_dst_boundary(&prevtime, &before_gmtoff, &before_isdst, &boundary, ! &after_gmtoff, &after_isdst); if (res < 0) goto overflow; /* failure? */ --- 1634,1641 ---- res = pg_next_dst_boundary(&prevtime, &before_gmtoff, &before_isdst, &boundary, ! &after_gmtoff, &after_isdst, ! global_timezone); if (res < 0) goto overflow; /* failure? */ Index: backend/utils/adt/nabstime.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v retrieving revision 1.127 diff -c -r1.127 nabstime.c *** backend/utils/adt/nabstime.c 31 Dec 2004 22:01:22 -0000 1.127 --- backend/utils/adt/nabstime.c 27 Feb 2005 17:09:39 -0000 *************** *** 192,198 **** time -= CTimeZone; if ((!HasCTZSet) && (tzp != NULL)) ! tx = pg_localtime(&time); else tx = pg_gmtime(&time); --- 192,198 ---- time -= CTimeZone; if ((!HasCTZSet) && (tzp != NULL)) ! tx = pg_localtime(&time,global_timezone); else tx = pg_gmtime(&time); *************** *** 1677,1683 **** gettimeofday(&tp, &tpz); tt = (pg_time_t) tp.tv_sec; pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z", ! pg_localtime(&tt)); snprintf(buf, sizeof(buf), templ, tp.tv_usec); len = VARHDRSZ + strlen(buf); --- 1677,1683 ---- gettimeofday(&tp, &tpz); tt = (pg_time_t) tp.tv_sec; pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z", ! pg_localtime(&tt,global_timezone)); snprintf(buf, sizeof(buf), templ, tp.tv_usec); len = VARHDRSZ + strlen(buf); Index: backend/utils/adt/timestamp.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v retrieving revision 1.117 diff -c -r1.117 timestamp.c *** backend/utils/adt/timestamp.c 31 Dec 2004 22:01:22 -0000 1.117 --- backend/utils/adt/timestamp.c 27 Feb 2005 17:10:07 -0000 *************** *** 1078,1084 **** utime = (pg_time_t) dt; if ((Timestamp) utime == dt) { ! struct pg_tm *tx = pg_localtime(&utime); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; --- 1078,1084 ---- utime = (pg_time_t) dt; if ((Timestamp) utime == dt) { ! struct pg_tm *tx = pg_localtime(&utime, global_timezone); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; Index: include/pgtime.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/pgtime.h,v retrieving revision 1.6 diff -c -r1.6 pgtime.h *** include/pgtime.h 31 Dec 2004 22:03:19 -0000 1.6 --- include/pgtime.h 1 Mar 2005 17:47:31 -0000 *************** *** 37,57 **** const char *tm_zone; }; ! extern struct pg_tm *pg_localtime(const pg_time_t *timep); extern struct pg_tm *pg_gmtime(const pg_time_t *timep); extern 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); extern size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm * tm); extern void pg_timezone_initialize(void); ! extern bool pg_tzset(const char *tzname); ! extern bool tz_acceptable(void); ! extern const char *select_default_timezone(void); ! extern const char *pg_get_current_timezone(void); #endif /* _PGTIME_H */ --- 37,60 ---- const char *tm_zone; }; ! typedef struct pg_tz pg_tz; ! ! extern struct pg_tm *pg_localtime(const pg_time_t *timep, const pg_tz *tz); extern struct pg_tm *pg_gmtime(const pg_time_t *timep); extern 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); extern size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm * tm); extern void pg_timezone_initialize(void); ! extern pg_tz *pg_tzset(const char *tzname); ! extern bool tz_acceptable(pg_tz *tz); ! extern const char *pg_get_timezone_name(pg_tz *tz); + extern pg_tz *global_timezone; #endif /* _PGTIME_H */ Index: timezone/localtime.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/timezone/localtime.c,v retrieving revision 1.9 diff -c -r1.9 localtime.c *** timezone/localtime.c 1 Nov 2004 21:34:44 -0000 1.9 --- timezone/localtime.c 1 Mar 2005 17:49:33 -0000 *************** *** 16,23 **** #include - #include "pgtz.h" #include "private.h" #include "tzfile.h" --- 16,23 ---- #include #include "private.h" + #include "pgtz.h" #include "tzfile.h" *************** *** 58,94 **** */ #define TZDEFRULESTRING ",M4.1.0,M10.5.0" - struct ttinfo - { /* time type information */ - long tt_gmtoff; /* UTC offset in seconds */ - int tt_isdst; /* used to set tm_isdst */ - int tt_abbrind; /* abbreviation list index */ - int tt_ttisstd; /* TRUE if transition is std time */ - int tt_ttisgmt; /* TRUE if transition is UTC */ - }; - - struct lsinfo - { /* leap second information */ - pg_time_t ls_trans; /* transition time */ - long ls_corr; /* correction to apply */ - }; - - #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) - - struct state - { - int leapcnt; - int timecnt; - int typecnt; - int charcnt; - pg_time_t ats[TZ_MAX_TIMES]; - unsigned char types[TZ_MAX_TIMES]; - struct ttinfo ttis[TZ_MAX_TYPES]; - char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), - (2 * (TZ_STRLEN_MAX + 1)))]; - struct lsinfo lsis[TZ_MAX_LEAPS]; - }; - struct rule { int r_type; /* type of rule--see below */ --- 58,63 ---- *************** *** 115,136 **** static const char *getrule(const char *strp, struct rule * rulep); static void gmtload(struct state * sp); static void gmtsub(const pg_time_t *timep, long offset, struct pg_tm * tmp); ! static void localsub(const pg_time_t *timep, long offset, struct pg_tm * tmp); static void timesub(const pg_time_t *timep, long offset, const struct state * sp, struct pg_tm * tmp); static pg_time_t transtime(pg_time_t janfirst, int year, ! const struct rule * rulep, long offset); ! static int tzload(const char *name, struct state * sp); ! static int tzparse(const char *name, struct state * sp, int lastditch); ! static struct state lclmem; static struct state gmtmem; - #define lclptr (&lclmem) #define gmtptr (&gmtmem) ! static char lcl_TZname[TZ_STRLEN_MAX + 1]; ! static int lcl_is_set = 0; static int gmt_is_set = 0; /* --- 84,102 ---- static const char *getrule(const char *strp, struct rule * rulep); static void gmtload(struct state * sp); static void gmtsub(const pg_time_t *timep, long offset, struct pg_tm * tmp); ! static void localsub(const pg_time_t *timep, long offset, struct pg_tm * tmp, const pg_tz *tz); static void timesub(const pg_time_t *timep, long offset, const struct state * sp, struct pg_tm * tmp); static pg_time_t transtime(pg_time_t janfirst, int year, ! const struct rule * rulep, long offset); ! int tzparse(const char *name, struct state * sp, int lastditch); ! /* GMT timezone */ static struct state gmtmem; #define gmtptr (&gmtmem) ! static int gmt_is_set = 0; /* *************** *** 156,162 **** return result; } ! static int tzload(register const char *name, register struct state * sp) { register const char *p; --- 122,128 ---- return result; } ! int tzload(register const char *name, register struct state * sp) { register const char *p; *************** *** 589,595 **** * appropriate. */ ! static int tzparse(const char *name, register struct state * sp, const int lastditch) { const char *stdname; --- 555,561 ---- * appropriate. */ ! int tzparse(const char *name, register struct state * sp, const int lastditch) { const char *stdname; *************** *** 839,868 **** } - bool - pg_tzset(const char *name) - { - if (lcl_is_set && strcmp(lcl_TZname, name) == 0) - return true; /* no change */ - - if (strlen(name) >= sizeof(lcl_TZname)) - return false; /* not gonna fit */ - - if (tzload(name, lclptr) != 0) - { - if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) - { - /* Unknown timezone. Fail our call instead of loading GMT! */ - return false; - } - } - - strcpy(lcl_TZname, name); - lcl_is_set = true; - - return true; - } - /* * The easy way to behave "as if no library function calls" localtime * is to not call it--so we drop its guts into "localsub", which can be --- 805,810 ---- *************** *** 872,885 **** * The unused offset argument is for the benefit of mktime variants. */ static void ! localsub(const pg_time_t *timep, const long offset, struct pg_tm * tmp) { ! register struct state *sp; register const struct ttinfo *ttisp; register int i; const pg_time_t t = *timep; ! sp = lclptr; if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; --- 814,827 ---- * The unused offset argument is for the benefit of mktime variants. */ static void ! localsub(const pg_time_t *timep, const long offset, struct pg_tm * tmp, const pg_tz *tz) { ! register const struct state *sp; register const struct ttinfo *ttisp; register int i; const pg_time_t t = *timep; ! sp = &tz->state; if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; *************** *** 906,914 **** struct pg_tm * ! pg_localtime(const pg_time_t *timep) { ! localsub(timep, 0L, &tm); return &tm; } --- 848,856 ---- struct pg_tm * ! pg_localtime(const pg_time_t *timep, const pg_tz *tz) { ! localsub(timep, 0L, &tm, tz); return &tm; } *************** *** 1084,1098 **** int *before_isdst, pg_time_t *boundary, long int *after_gmtoff, ! int *after_isdst) { ! register struct state *sp; register const struct ttinfo *ttisp; int i; int j; const pg_time_t t = *timep; ! sp = lclptr; if (sp->timecnt == 0) { /* non-DST zone, use lowest-numbered standard type */ --- 1026,1041 ---- int *before_isdst, pg_time_t *boundary, long int *after_gmtoff, ! int *after_isdst, ! const pg_tz *tz) { ! register const struct state *sp; register 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 */ *************** *** 1158,1166 **** * Return the name of the current timezone */ const char * ! pg_get_current_timezone(void) { ! if (lcl_is_set) ! return lcl_TZname; return NULL; } --- 1101,1109 ---- * Return the name of the current timezone */ const char * ! pg_get_timezone_name(pg_tz *tz) { ! if (tz) ! return tz->TZname; return NULL; } Index: timezone/pgtz.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/timezone/pgtz.c,v retrieving revision 1.29 diff -c -r1.29 pgtz.c *** timezone/pgtz.c 31 Dec 2004 22:03:59 -0000 1.29 --- timezone/pgtz.c 1 Mar 2005 19:01:12 -0000 *************** *** 26,37 **** --- 26,43 ---- #include "utils/datetime.h" #include "utils/elog.h" #include "utils/guc.h" + #include "utils/hsearch.h" + + /* Current global timezone */ + pg_tz *global_timezone = NULL; static char tzdir[MAXPGPATH]; static int done_tzdir = 0; static const char *identify_system_timezone(void); + static const char *select_default_timezone(void); + static bool set_global_timezone(const char *tzname); /* *************** *** 156,167 **** struct tm *systm; struct pg_tm *pgtm; char cbuf[TZ_STRLEN_MAX + 1]; ! if (!pg_tzset(tzname)) return -1; /* can't handle the TZ name at all */ /* Reject if leap seconds involved */ ! if (!tz_acceptable()) { elog(DEBUG4, "Reject TZ \"%s\": uses leap seconds", tzname); return -1; --- 162,175 ---- struct tm *systm; struct pg_tm *pgtm; char cbuf[TZ_STRLEN_MAX + 1]; + pg_tz *tz; ! tz = pg_tzset(tzname); ! if (!tz) return -1; /* can't handle the TZ name at all */ /* Reject if leap seconds involved */ ! if (!tz_acceptable(tz)) { elog(DEBUG4, "Reject TZ \"%s\": uses leap seconds", tzname); return -1; *************** *** 171,177 **** for (i = 0; i < tt->n_test_times; i++) { pgtt = (pg_time_t) (tt->test_times[i]); ! pgtm = pg_localtime(&pgtt); if (!pgtm) return -1; /* probably shouldn't happen */ systm = localtime(&(tt->test_times[i])); --- 179,185 ---- for (i = 0; i < tt->n_test_times; i++) { pgtt = (pg_time_t) (tt->test_times[i]); ! pgtm = pg_localtime(&pgtt, tz); if (!pgtm) return -1; /* probably shouldn't happen */ systm = localtime(&(tt->test_times[i])); *************** *** 957,962 **** --- 965,1046 ---- #endif /* WIN32 */ + + /* + * We keep loaded timezones in a hashtable so we don't have to + * load and parse the TZ definition file every time it is selected. + */ + static HTAB *timezone_cache = NULL; + static bool + init_timezone_hashtable(void) + { + HASHCTL hash_ctl; + + MemSet(&hash_ctl, 0, sizeof(hash_ctl)); + + hash_ctl.keysize = TZ_STRLEN_MAX; + hash_ctl.entrysize = sizeof(pg_tz); + + timezone_cache = hash_create("Timezones", + 31, + &hash_ctl, + HASH_ELEM); + if (!timezone_cache) + return false; + + return true; + } + + /* + * Load a timezone from file or from cache. + * Does not verify that the timezone is acceptable! + */ + struct pg_tz * + pg_tzset(const char *name) + { + pg_tz *tzp; + pg_tz tz; + + if (strlen(name) >= TZ_STRLEN_MAX) + return NULL; /* not going to fit */ + + if (!timezone_cache) + if (!init_timezone_hashtable()) + return NULL; + + tzp = (pg_tz *)hash_search(timezone_cache, + name, + HASH_FIND, + NULL); + if (tzp) + /* Timezone found in cache, nothing more to do */ + return tzp; + + if (tzload(name, &tz.state) != 0) + { + if (name[0] == ':' || tzparse(name, &tz.state, FALSE) != 0) + /* Unknown timezone. Fail our call instead of loading GMT! */ + return NULL; + } + + strcpy(tz.TZname, name); + + /* Save timezone in the cache */ + tzp = hash_search(timezone_cache, + name, + HASH_ENTER, + NULL); + + if (!tzp) + return NULL; + + strcpy(tzp->TZname, tz.TZname); + memcpy(&tzp->state, &tz.state, sizeof(tz.state)); + + return tzp; + } + + /* * Check whether timezone is acceptable. * *************** *** 968,974 **** * it can restore the old value of TZ if we don't like the new one. */ bool ! tz_acceptable(void) { struct pg_tm *tt; pg_time_t time2000; --- 1052,1058 ---- * it can restore the old value of TZ if we don't like the new one. */ bool ! tz_acceptable(pg_tz *tz) { struct pg_tm *tt; pg_time_t time2000; *************** *** 979,991 **** * any other result has to be due to leap seconds. */ time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400; ! tt = pg_localtime(&time2000); if (!tt || tt->tm_sec != 0) return false; return true; } /* * Identify a suitable default timezone setting based on the environment, * and make it active. --- 1063,1098 ---- * any other result has to be due to leap seconds. */ time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400; ! tt = pg_localtime(&time2000, tz); if (!tt || tt->tm_sec != 0) return false; return true; } + + /* + * Set the global timezone. Verify that it's acceptable first. + */ + static bool + set_global_timezone(const char *tzname) + { + pg_tz *tznew; + + if (!tzname || !tzname[0]) + return false; + + tznew = pg_tzset(tzname); + if (!tznew) + return false; + + if (!tz_acceptable(tznew)) + return false; + + global_timezone = tznew; + return true; + } + /* * Identify a suitable default timezone setting based on the environment, * and make it active. *************** *** 995,1014 **** * from the behavior of the system timezone library. When all else fails, * fall back to GMT. */ ! const char * select_default_timezone(void) { const char *def_tz; def_tz = getenv("TZ"); ! if (def_tz && pg_tzset(def_tz) && tz_acceptable()) return def_tz; def_tz = identify_system_timezone(); ! if (def_tz && pg_tzset(def_tz) && tz_acceptable()) return def_tz; ! if (pg_tzset("GMT") && tz_acceptable()) return "GMT"; ereport(FATAL, --- 1102,1121 ---- * from the behavior of the system timezone library. When all else fails, * fall back to GMT. */ ! static const char * select_default_timezone(void) { const char *def_tz; def_tz = getenv("TZ"); ! if (set_global_timezone(def_tz)) return def_tz; def_tz = identify_system_timezone(); ! if (set_global_timezone(def_tz)) return def_tz; ! if (set_global_timezone("GMT")) return "GMT"; ereport(FATAL, Index: timezone/pgtz.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/timezone/pgtz.h,v retrieving revision 1.10 diff -c -r1.10 pgtz.h *** timezone/pgtz.h 31 Dec 2004 22:03:59 -0000 1.10 --- timezone/pgtz.h 28 Feb 2005 19:23:03 -0000 *************** *** 16,23 **** --- 16,65 ---- #ifndef _PGTZ_H #define _PGTZ_H + #include "tzfile.h" + #define TZ_STRLEN_MAX 255 extern char *pg_TZDIR(void); + #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) + + struct ttinfo + { /* time type information */ + long tt_gmtoff; /* UTC offset in seconds */ + int tt_isdst; /* used to set tm_isdst */ + int tt_abbrind; /* abbreviation list index */ + int tt_ttisstd; /* TRUE if transition is std time */ + int tt_ttisgmt; /* TRUE if transition is UTC */ + }; + + struct lsinfo + { /* leap second information */ + pg_time_t ls_trans; /* transition time */ + long ls_corr; /* correction to apply */ + }; + + struct state + { + int leapcnt; + int timecnt; + int typecnt; + int charcnt; + pg_time_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; + struct ttinfo ttis[TZ_MAX_TYPES]; + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */), + (2 * (TZ_STRLEN_MAX + 1)))]; + struct lsinfo lsis[TZ_MAX_LEAPS]; + }; + + + struct pg_tz { + char TZname[TZ_STRLEN_MAX + 1]; + struct state state; + }; + + int tzload(const char *name, struct state * sp); + int tzparse(const char *name, struct state * sp, int lastditch); + #endif /* _PGTZ_H */ Index: timezone/strftime.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/timezone/strftime.c,v retrieving revision 1.5 diff -c -r1.5 strftime.c *** timezone/strftime.c 29 Aug 2004 05:07:02 -0000 1.5 --- timezone/strftime.c 1 Mar 2005 18:03:34 -0000 *************** *** 23,30 **** #include #include - #include "pgtz.h" #include "private.h" #include "tzfile.h" --- 23,30 ---- #include #include #include "private.h" + #include "pgtz.h" #include "tzfile.h" Index: timezone/zic.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/timezone/zic.c,v retrieving revision 1.13 diff -c -r1.13 zic.c *** timezone/zic.c 27 Sep 2004 19:16:03 -0000 1.13 --- timezone/zic.c 1 Mar 2005 18:04:39 -0000 *************** *** 14,21 **** #include #include - #include "pgtz.h" #include "private.h" #include "tzfile.h" #ifdef HAVE_SYS_STAT_H --- 14,21 ---- #include #include #include "private.h" + #include "pgtz.h" #include "tzfile.h" #ifdef HAVE_SYS_STAT_H