diff --git a/src/timezone/README b/src/timezone/README
index a4ba7053c4..4372ce542b 100644
--- a/src/timezone/README
+++ b/src/timezone/README
@@ -1,4 +1,4 @@
-$PostgreSQL: pgsql/src/timezone/README,v 1.8 2010/03/11 18:43:24 tgl Exp $
+$PostgreSQL: pgsql/src/timezone/README,v 1.9 2010/04/15 11:00:45 mha Exp $
Timezone
========
@@ -24,3 +24,10 @@ Just search for the current or previous year and see what has changed.
Sometimes a country changes its time zone offsets, for example Georgia
in 2004. Just grepping in the zic database files for 2004 is enough to
spot such a change. Then the files under tznames/ should be updated.
+
+When there has been a new release of Windows (probably including Service
+Packs), the list of matching timezones need to be updated. Run the
+script in src/tools/win32tzlist.pl on a Windows machine running this new
+release and apply any new timezones that it detects. Never remove any
+mappings in case they are removed in Windows, since we still need to
+match properly on the old version.
diff --git a/src/tools/RELEASE_CHANGES b/src/tools/RELEASE_CHANGES
index 1e1bbe8573..47fa03af93 100644
--- a/src/tools/RELEASE_CHANGES
+++ b/src/tools/RELEASE_CHANGES
@@ -12,7 +12,8 @@ For All Releases (major, minor, beta, RC)
o add SGML markup
o check if 'gmake HISTORY.html' works for s
-* Update timezone data to match latest zic database (see src/timezone/README)
+* Update timezone data to match latest zic database and new
+ Windows releases, if any (see src/timezone/README)
* Translation updates
Translations are kept in the project "pgtranslation" on PgFoundry.
diff --git a/src/tools/win32tzlist.pl b/src/tools/win32tzlist.pl
new file mode 100755
index 0000000000..083cc08850
--- /dev/null
+++ b/src/tools/win32tzlist.pl
@@ -0,0 +1,134 @@
+#################################################################
+#
+# win32tzlist.pl -- compare Windows timezone information
+#
+# Copyright (c) 2008-2010, PostgreSQL Global Development Group
+#
+# $PostgreSQL: pgsql/src/tools/win32tzlist.pl,v 1.1 2010/04/15 11:00:45 mha Exp $
+#################################################################
+
+#
+# This script compares the timezone information in the Windows
+# registry with that in pgtz.c. A list of changes will be written
+# to stdout - no attempt is made to automatically edit the file.
+#
+# Run the script from the src/timezone directory.
+#
+
+use strict;
+use warnings;
+
+use Win32::Registry;
+
+#
+# Fetch all timezones in the registry
+#
+my $basekey;
+$HKEY_LOCAL_MACHINE->Open("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", $basekey)
+ or die $!;
+
+my @subkeys;
+$basekey->GetKeys(\@subkeys);
+
+my @system_zones;
+
+foreach my $keyname (@subkeys)
+{
+ my $subkey;
+ my %vals;
+
+ $basekey->Open($keyname, $subkey) or die $!;
+ $subkey->GetValues(\%vals) or die $!;
+ $subkey->Close();
+
+ die "Incomplete timezone data for $keyname!\n"
+ unless ($vals{Std} && $vals{Dlt} && $vals{Display});
+ push @system_zones,
+ {
+ 'std'=>$vals{Std}->[2],
+ 'dlt'=>$vals{Dlt}->[2],
+ 'display'=>clean_displayname($vals{Display}->[2]),
+ };
+}
+
+$basekey->Close();
+
+#
+# Fetch all timezones currently in the file
+#
+my @file_zones;
+open(PGTZ,';
+close(PGTZ);
+$/ = $t;
+
+# Attempt to locate and extract the complete win32_tzmap struct
+$pgtz =~ /win32_tzmap\[\] =\s+{\s+\/\*[^\/]+\*\/\s+(.+?)};/gs
+ or die "Could not locate struct win32_tzmap in pgtz.c!";
+$pgtz = $1;
+
+# Extract each individual record from the struct
+while ($pgtz =~ m/{\s+"([^"]+)",\s+"([^"]+)",\s+"([^"]+)",?\s+},\s+\/\*(.+?)\*\//gs)
+{
+ push @file_zones,
+ {
+ 'std'=>$1,
+ 'dlt'=>$2,
+ 'match'=>$3,
+ 'display'=>clean_displayname($4),
+ };
+}
+
+#
+# Look for anything that has changed
+#
+my @add;
+
+for my $sys (@system_zones)
+{
+ my $match = 0;
+ for my $file (@file_zones)
+ {
+ if ($sys->{std} eq $file->{std})
+ {
+ $match=1;
+ if ($sys->{dlt} ne $file->{dlt})
+ {
+ print "Timezone $sys->{std}, changed name of daylight zone!\n";
+ }
+ if ($sys->{display} ne $file->{display})
+ {
+ print
+"Timezone $sys->{std} changed displayname ('$sys->{display}' from '$file->{display}')!\n";
+ }
+ last;
+ }
+ }
+ unless ($match)
+ {
+ push @add, $sys;
+ }
+}
+
+if (@add)
+{
+ print "\n\nOther than that, add the following timezones:\n";
+ for my $z (@add)
+ {
+ print
+"\t{\n\t\t\"$z->{std}\", \"$z->{dlt}\",\n\t\t\"FIXME\"\n\t},\t\t\t\t\t\t\t/* $z->{display} */\n";
+ }
+}
+
+sub clean_displayname
+{
+ my $dn = shift;
+
+ $dn =~ s/\s+/ /gs;
+ $dn =~ s/\*//gs;
+ $dn =~ s/^\s+//gs;
+ $dn =~ s/\s+$//gs;
+ return $dn;
+}