diff --git a/src/timezone/README b/src/timezone/README
index 48c1eec..0d016b8 100644
--- a/src/timezone/README
+++ b/src/timezone/README
@@ -7,7 +7,7 @@ This is a PostgreSQL adapted version of the timezone library from:
 
 	ftp://elsie.nci.nih.gov/pub/tzcode*.tar.gz
 
-The code is currently synced with release 2007k.  There are many cosmetic
+The code is currently synced with release 2010a.  There are many cosmetic
 (and not so cosmetic) differences from the original tzcode library, but
 diffs in the upstream version should usually be propagated to our version.
 
diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c
index 3fa6d12..b925a28 100644
--- a/src/timezone/localtime.c
+++ b/src/timezone/localtime.c
@@ -357,16 +357,30 @@ tzload(const char *name, char *canonname, struct state * sp, int doextend)
 			sp->ttis[sp->typecnt++] = ts.ttis[1];
 		}
 	}
-	i = 2 * YEARSPERREPEAT;
-	sp->goback = sp->goahead = sp->timecnt > i;
-	sp->goback = sp->goback &&
-		typesequiv(sp, sp->types[i], sp->types[0]) &&
-		differ_by_repeat(sp->ats[i], sp->ats[0]);
-	sp->goahead = sp->goahead &&
-		typesequiv(sp, sp->types[sp->timecnt - 1],
-				   sp->types[sp->timecnt - 1 - i]) &&
-		differ_by_repeat(sp->ats[sp->timecnt - 1],
-						 sp->ats[sp->timecnt - 1 - i]);
+	sp->goback = sp->goahead = FALSE;
+	if (sp->timecnt > 1)
+	{
+		for (i = 1; i < sp->timecnt; ++i)
+		{
+			if (typesequiv(sp, sp->types[i], sp->types[0]) &&
+				differ_by_repeat(sp->ats[i], sp->ats[0]))
+			{
+					sp->goback = TRUE;
+					break;
+			}
+		}
+		for (i = sp->timecnt - 2; i >= 0; --i)
+		{
+			if (typesequiv(sp, sp->types[sp->timecnt - 1],
+						   sp->types[i]) &&
+				differ_by_repeat(sp->ats[sp->timecnt - 1],
+								 sp->ats[i]))
+			{
+				sp->goahead = TRUE;
+				break;
+			}
+		}
+	}
 	return 0;
 }
 
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index 95ea3c8..e196e33 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -287,6 +287,7 @@ score_timezone(const char *tzname, struct tztry * tt)
 	 * Load timezone directly. Don't use pg_tzset, because we don't want all
 	 * timezones loaded in the cache at startup.
 	 */
+	MemSet(&tz.state, 0, sizeof(tz.state));
 	if (tzload(tzname, NULL, &tz.state, TRUE) != 0)
 	{
 		if (tzname[0] == ':' || tzparse(tzname, &tz.state, FALSE) != 0)
@@ -1221,6 +1222,7 @@ pg_tzset(const char *name)
 		return &tzp->tz;
 	}
 
+	MemSet(&tz.state, 0, sizeof(tzstate));
 	if (tzload(uppername, canonname, &tzstate, TRUE) != 0)
 	{
 		if (uppername[0] == ':' || tzparse(uppername, &tzstate, FALSE) != 0)
@@ -1493,6 +1495,7 @@ pg_tzenumerate_next(pg_tzenum *dir)
 		 * Load this timezone using tzload() not pg_tzset(), so we don't fill
 		 * the cache
 		 */
+		MemSet(&dir->tz.state, 0, sizeof(dir->tz.state));
 		if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state,
 				   TRUE) != 0)
 		{
diff --git a/src/timezone/strftime.c b/src/timezone/strftime.c
index 1c6f223..99052a1 100644
--- a/src/timezone/strftime.c
+++ b/src/timezone/strftime.c
@@ -169,7 +169,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
 					{
 						int			warn2 = IN_SOME;
 
-						pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp);
+						pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
 						if (warn2 == IN_ALL)
 							warn2 = IN_THIS;
 						if (warn2 > *warnp)
diff --git a/src/timezone/zic.c b/src/timezone/zic.c
index 32b863f..a8033bf 100644
--- a/src/timezone/zic.c
+++ b/src/timezone/zic.c
@@ -41,7 +41,7 @@ typedef int64 zic_t;
 #endif
 #endif
 
-static char elsieid[] = "@(#)zic.c  8.17";
+static char elsieid[] = "@(#)zic.c	8.20";
 
 /*
  * On some ancient hosts, predicates like `isspace(C)' are defined
@@ -162,7 +162,7 @@ static void rulesub(struct rule * rp,
 		const char *dayp, const char *timep);
 static void setboundaries(void);
 static pg_time_t tadd(const pg_time_t t1, long t2);
-static void usage(void);
+static void usage(FILE *stream, int status);
 static void writezone(const char *name, const char *string);
 static int	yearistype(int year, const char *type);
 
@@ -454,13 +454,15 @@ warning(const char *string)
 }
 
 static void
-usage(void)
+usage(FILE *stream, int status)
 {
-	(void) fprintf(stderr, _("%s: usage is %s \
-[ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
-\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
-				   progname, progname);
-	exit(EXIT_FAILURE);
+	(void) fprintf(stream, _("%s: usage is %s \
+[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
+\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
+\n\
+Report bugs to tz@elsie.nci.nih.gov.\n"),
+		       progname, progname);
+	exit(status);
 }
 
 static const char *psxrules;
@@ -492,11 +494,14 @@ main(int argc, char *argv[])
 			(void) printf("%s\n", elsieid);
 			exit(EXIT_SUCCESS);
 		}
+		else if (strcmp(argv[i], "--help") == 0) {
+			usage(stdout, EXIT_SUCCESS);
+		}
 	while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
 		switch (c)
 		{
 			default:
-				usage();
+				usage(stderr, EXIT_FAILURE);
 			case 'd':
 				if (directory == NULL)
 					directory = optarg;
@@ -560,7 +565,7 @@ main(int argc, char *argv[])
 				break;
 		}
 	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
-		usage();				/* usage message by request */
+		usage(stderr, EXIT_FAILURE);	/* usage message by request */
 	if (directory == NULL)
 		directory = "data";
 	if (yitcommand == NULL)
@@ -2035,7 +2040,7 @@ stringzone(char *result, const struct zone * zpfirst, int zonecount)
 		if (stdrp != NULL && stdrp->r_hiyear == 2037)
 			return;
 	}
-	if (stdrp == NULL && zp->z_nrules != 0)
+	if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0))
 		return;
 	abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
 	doabbr(result, zp->z_format, abbrvar, FALSE, TRUE);
@@ -2115,7 +2120,7 @@ outzone(const struct zone * zpfirst, int zonecount)
 	if (leapseen)
 	{
 		updateminmax(leapminyear);
-		updateminmax(leapmaxyear);
+		updateminmax(leapmaxyear + (leapmaxyear < INT_MAX));
 	}
 	for (i = 0; i < zonecount; ++i)
 	{
