aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/timezone/pgtz.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index b951830b026..bdd22506672 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.59 2008/02/16 21:16:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.60 2008/07/01 03:40:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -198,7 +198,7 @@ scan_directory_ci(const char *dirname, const char *fname, int fnamelen,
#define T_WEEK ((time_t) (60*60*24*7))
#define T_MONTH ((time_t) (60*60*24*31))
-#define MAX_TEST_TIMES (52*100) /* 100 years, or 1904..2004 */
+#define MAX_TEST_TIMES (52*100) /* 100 years */
struct tztry
{
@@ -367,6 +367,7 @@ identify_system_timezone(void)
time_t t;
struct tztry tt;
struct tm *tm;
+ int thisyear;
int bestscore;
char tmptzdir[MAXPGPATH];
int std_ofs;
@@ -379,11 +380,14 @@ identify_system_timezone(void)
/*
* Set up the list of dates to be probed to see how well our timezone
- * matches the system zone. We first probe January and July of 2004; this
- * serves to quickly eliminate the vast majority of the TZ database
- * entries. If those dates match, we probe every week from 2004 backwards
- * to late 1904. (Weekly resolution is good enough to identify DST
- * transition rules, since everybody switches on Sundays.) The further
+ * matches the system zone. We first probe January and July of the
+ * current year; this serves to quickly eliminate the vast majority of the
+ * TZ database entries. If those dates match, we probe every week for 100
+ * years backwards from the current July. (Weekly resolution is good
+ * enough to identify DST transition rules, since everybody switches on
+ * Sundays.) This is sufficient to cover most of the Unix time_t range,
+ * and we don't want to look further than that since many systems won't
+ * have sane TZ behavior further back anyway. The further
* back the zone matches, the better we score it. This may seem like a
* rather random way of doing things, but experience has shown that
* system-supplied timezone definitions are likely to have DST behavior
@@ -393,9 +397,29 @@ identify_system_timezone(void)
* (Note: we probe Thursdays, not Sundays, to avoid triggering
* DST-transition bugs in localtime itself.)
*/
+ tnow = time(NULL);
+ tm = localtime(&tnow);
+ if (!tm)
+ return NULL; /* give up if localtime is broken... */
+ thisyear = tm->tm_year + 1900;
+
+ t = build_time_t(thisyear, 1, 15);
+ /*
+ * Round back to GMT midnight Thursday. This depends on the knowledge
+ * that the time_t origin is Thu Jan 01 1970. (With a different origin
+ * we'd be probing some other day of the week, but it wouldn't matter
+ * anyway unless localtime() had DST-transition bugs.)
+ */
+ t -= (t % T_WEEK);
+
tt.n_test_times = 0;
- tt.test_times[tt.n_test_times++] = build_time_t(2004, 1, 15);
- tt.test_times[tt.n_test_times++] = t = build_time_t(2004, 7, 15);
+ tt.test_times[tt.n_test_times++] = t;
+
+ t = build_time_t(thisyear, 7, 15);
+ t -= (t % T_WEEK);
+
+ tt.test_times[tt.n_test_times++] = t;
+
while (tt.n_test_times < MAX_TEST_TIMES)
{
t -= T_WEEK;
@@ -410,7 +434,12 @@ identify_system_timezone(void)
&tt,
&bestscore, resultbuf);
if (bestscore > 0)
+ {
+ /* Ignore zic's rather silly "Factory" time zone; use GMT instead */
+ if (strcmp(resultbuf, "Factory") == 0)
+ return NULL;
return resultbuf;
+ }
/*
* Couldn't find a match in the database, so next we try constructed zone