#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
 {
        time_t          t;
        struct tztry tt;
        struct tm  *tm;
+       int                     thisyear;
        int                     bestscore;
        char            tmptzdir[MAXPGPATH];
        int                     std_ofs;
 
        /*
         * 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 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 that is right for the recent past and
-        * not so accurate further back. Scoring in this way allows us to
-        * recognize zones that have some commonality with the zic database,
-        * without insisting on exact match. (Note: we probe Thursdays, not
-        * Sundays, to avoid triggering DST-transition bugs in localtime
-        * itself.)
+        * 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
+        * that is right for the recent past and not so accurate further back.
+        * Scoring in this way allows us to recognize zones that have some
+        * commonality with the zic database, without insisting on exact match.
+        * (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;
                                                         &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