diff --git a/make/CompileDemos.gmk b/make/CompileDemos.gmk index 3b1839102a7654880712e2282fe33ee257f6b1eb..36829b3d3fd3c4c2a2474a4ec20dada253b955c3 100644 --- a/make/CompileDemos.gmk +++ b/make/CompileDemos.gmk @@ -456,7 +456,7 @@ endif ################################################################################################## ifndef OPENJDK - DB_DEMO_ZIPFILE := $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip) + DB_DEMO_ZIPFILE := $(wildcard $(JDK_TOPDIR)/src/closed/share/db/db-derby-*-bin.zip) $(JDK_OUTPUTDIR)/demo/_the.db.unzipped: $(DB_DEMO_ZIPFILE) $(MKDIR) -p $(@D) diff --git a/make/CompileNativeLibraries.gmk b/make/CompileNativeLibraries.gmk index 57ef12e32cb15e4e151bcf6de49aa74f2e1d83cf..c23b958b066ca325ab0d98fbe69223ee6ee2e9a1 100644 --- a/make/CompileNativeLibraries.gmk +++ b/make/CompileNativeLibraries.gmk @@ -87,6 +87,9 @@ include lib/Awt2dLibraries.gmk include lib/SoundLibraries.gmk +# Include the corresponding custom file, if present. +-include $(CUSTOM_MAKE_DIR)/CompileNativeLibraries.gmk + ########################################################################################## all: $(COPY_FILES) $(BUILD_LIBRARIES) diff --git a/make/Images.gmk b/make/Images.gmk index 884dc4f46feb96d744f784449edfa5d58a413e5e..51d0c144b7312fbc8666a3a97ea266923861a18f 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -562,7 +562,7 @@ ifndef OPENJDK $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > $@ JDK_DB_TARGETS := $(patsubst $(JDK_TOPDIR)/src/closed/share/db/%, $(IMAGES_OUTPUTDIR)/_unzip/%.unzipped, \ - $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip)) \ + $(wildcard $(JDK_TOPDIR)/src/closed/share/db/db-derby-*-bin.zip)) \ $(JDK_IMAGE_DIR)/db/README-JDK.html $(JDK_IMAGE_DIR)/db/3RDPARTY endif diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION index c735be51ca1d0724491f48d3d976a1e82102315b..5e925ada8df37cfc1ab0b860960a51a3199140c2 100644 --- a/make/data/tzdata/VERSION +++ b/make/data/tzdata/VERSION @@ -1,24 +1,24 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # This code is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 only, as # published by the Free Software Foundation. Oracle designates this # particular file as subject to the "Classpath" exception as provided # by Oracle in the LICENSE file that accompanied this code. -# +# # This code is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # version 2 for more details (a copy is included in the LICENSE file that # accompanied this code). -# +# # You should have received a copy of the GNU General Public License version # 2 along with this work; if not, write to the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# +# # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2014c +tzdata2014g diff --git a/make/data/tzdata/africa b/make/data/tzdata/africa index 6f1a1471e0c545dff04c39f95f6143317ec197bc..aa91f365ce13b9829a22cb6ff17998f4b23af8e1 100644 --- a/make/data/tzdata/africa +++ b/make/data/tzdata/africa @@ -21,13 +21,13 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -#
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 #
@@ -49,8 +49,8 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
@@ -58,13 +58,13 @@
 # Previous editions of this database used WAT, CAT, SAT, and EAT
 # for +0:00 through +3:00, respectively,
 # but Mark R V Murray reports that
-# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
-# `CAT' is commonly used for +2:00 in countries north of South Africa, and
-# `WAT' is probably the best name for +1:00, as the common phrase for
-# the area that includes Nigeria is ``West Africa''.
-# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
+# 'SAST' is the official abbreviation for +2:00 in the country of South Africa,
+# 'CAT' is commonly used for +2:00 in countries north of South Africa, and
+# 'WAT' is probably the best name for +1:00, as the common phrase for
+# the area that includes Nigeria is "West Africa".
+# He has heard of "Western Sahara Time" for +0:00 but can find no reference.
 #
-# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
+# To make things confusing, 'WAT' seems to have been used for -1:00 long ago;
 # I'd guess that this was because people needed _some_ name for -1:00,
 # and at the time, far west Africa was the only major land area in -1:00.
 # This usage is now obsolete, as the last use of -1:00 on the African
@@ -77,7 +77,7 @@
 #	 2:00	SAST	South Africa Standard Time
 # and Murray suggests the following abbreviation:
 #	 1:00	WAT	West Africa Time
-# I realize that this leads to `WAT' being used for both -1:00 and 1:00
+# I realize that this leads to 'WAT' being used for both -1:00 and 1:00
 # for times before 1976, but this is the best I can think of
 # until we get more information.
 #
@@ -117,9 +117,9 @@ Rule	Algeria	1980	only	-	Oct	31	 2:00	0	-
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	Algeria	WE%sT	1940 Feb 25 2:00
+Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15  0:01
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	Algeria	WE%sT	1940 Feb 25  2:00
 			1:00	Algeria	CE%sT	1946 Oct  7
 			0:00	-	WET	1956 Jan 29
 			1:00	-	CET	1963 Apr 14
@@ -129,18 +129,8 @@ Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
 			1:00	-	CET
 
 # Angola
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Luanda	0:52:56	-	LMT	1892
-			0:52:04	-	AOT	1911 May 26 # Angola Time
-			1:00	-	WAT
-
 # Benin
-# Whitman says they switched to 1:00 in 1946, not 1934;
-# go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
-			0:00	-	GMT	1934 Feb 26
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Botswana
 # From Paul Eggert (2013-02-21):
@@ -149,14 +139,12 @@ Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Gaborone	1:43:40 -	LMT	1885
 			1:30	-	SAST	1903 Mar
-			2:00	-	CAT	1943 Sep 19 2:00
-			2:00	1:00	CAST	1944 Mar 19 2:00
+			2:00	-	CAT	1943 Sep 19  2:00
+			2:00	1:00	CAST	1944 Mar 19  2:00
 			2:00	-	CAT
 
 # Burkina Faso
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Ouagadougou	-0:06:04 -	LMT	1912
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Burundi
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -164,52 +152,60 @@ Zone Africa/Bujumbura	1:57:28	-	LMT	1890
 			2:00	-	CAT
 
 # Cameroon
-# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Douala	0:38:48	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Cape Verde
+#
+# Shanks gives 1907 for the transition to CVT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907			# Praia
+Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907        # Praia
 			-2:00	-	CVT	1942 Sep
 			-2:00	1:00	CVST	1945 Oct 15
-			-2:00	-	CVT	1975 Nov 25 2:00
+			-2:00	-	CVT	1975 Nov 25  2:00
 			-1:00	-	CVT
 
 # Central African Republic
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bangui	1:14:20	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Chad
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Ndjamena	1:00:12 -	LMT	1912
+Zone	Africa/Ndjamena	1:00:12 -	LMT	1912        # N'Djamena
 			1:00	-	WAT	1979 Oct 14
 			1:00	1:00	WAST	1980 Mar  8
 			1:00	-	WAT
 
 # Comoros
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul   # Moroni, Gran Comoro
+Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul # Moroni, Gran Comoro
 			3:00	-	EAT
 
-# Democratic Republic of Congo
+# Democratic Republic of the Congo
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Kinshasa	1:01:12 -	LMT	1897 Nov 9
-			1:00	-	WAT
 Zone Africa/Lubumbashi	1:49:52 -	LMT	1897 Nov 9
 			2:00	-	CAT
+# The above is for the eastern part; see Africa/Lagos for the western part.
 
 # Republic of the Congo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Brazzaville	1:01:08 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
-# Cote D'Ivoire
+# Côte d'Ivoire / Ivory Coast
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Abidjan	-0:16:08 -	LMT	1912
 			 0:00	-	GMT
+Link Africa/Abidjan Africa/Bamako	# Mali
+Link Africa/Abidjan Africa/Banjul	# Gambia
+Link Africa/Abidjan Africa/Conakry	# Guinea
+Link Africa/Abidjan Africa/Dakar	# Senegal
+Link Africa/Abidjan Africa/Freetown	# Sierra Leone
+Link Africa/Abidjan Africa/Lome		# Togo
+Link Africa/Abidjan Africa/Nouakchott	# Mauritania
+Link Africa/Abidjan Africa/Ouagadougou	# Burkina Faso
+Link Africa/Abidjan Africa/Sao_Tome	# São Tomé and Príncipe
+Link Africa/Abidjan Atlantic/St_Helena	# St Helena
 
 # Djibouti
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -254,30 +250,26 @@ Rule	Egypt	1990	1994	-	May	 1	1:00	1:00	S
 # Egyptians would approve the cancellation."
 #
 # Egypt to cancel daylight saving time
-# 
 # http://www.almasryalyoum.com/en/node/407168
-# 
 # or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_egypt04.html
-# 
 Rule	Egypt	1995	2010	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	1995	2005	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	1995	2005	-	Sep	lastThu	24:00	0	-
 # From Steffen Thorsen (2006-09-19):
 # The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports:
 # Egypt will turn back clocks by one hour at the midnight of Thursday
 # after observing the daylight saving time since May.
 # http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf
-Rule	Egypt	2006	only	-	Sep	21	23:00s	0	-
+Rule	Egypt	2006	only	-	Sep	21	24:00	0	-
 # From Dirk Losch (2007-08-14):
 # I received a mail from an airline which says that the daylight
 # saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
-# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
+# From Jesper Nørgaard Welen (2007-08-15): [The following agree:]
 # http://www.nentjes.info/Bill/bill5.htm
 # http://www.timeanddate.com/worldclock/city.html?n=53
 # From Steffen Thorsen (2007-09-04): The official information...:
 # http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
-Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
+Rule	Egypt	2007	only	-	Sep	Thu>=1	24:00	0	-
 # From Abdelrahman Hassan (2007-09-06):
 # Due to the Hijri (lunar Islamic calendar) year being 11 days shorter
 # than the year of the Gregorian calendar, Ramadan shifts earlier each
@@ -311,15 +303,9 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 #
 # timeanddate[2] and another site I've found[3] also support that.
 #
-# [1] 
-# https://bugzilla.redhat.com/show_bug.cgi?id=492263
-# 
-# [2] 
-# http://www.timeanddate.com/worldclock/clockchange.html?n=53
-# 
-# [3] 
-# http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
-# 
+# [1] https://bugzilla.redhat.com/show_bug.cgi?id=492263
+# [2] http://www.timeanddate.com/worldclock/clockchange.html?n=53
+# [3] http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
 
 # From Arthur David Olson (2009-04-20):
 # In 2009 (and for the next several years), Ramadan ends before the fourth
@@ -329,14 +315,10 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # From Steffen Thorsen (2009-08-11):
 # We have been able to confirm the August change with the Egyptian Cabinet
 # Information and Decision Support Center:
-# 
 # http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
-# 
 #
 # The Middle East News Agency
-# 
 # http://www.mena.org.eg/index.aspx
-# 
 # also reports "Egypt starts winter time on August 21"
 # today in article numbered "71, 11/08/2009 12:25 GMT."
 # Only the title above is available without a subscription to their service,
@@ -344,19 +326,14 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # (at least today).
 
 # From Alexander Krivenyshev (2010-07-20):
-# According to News from Egypt -  Al-Masry Al-Youm Egypt's cabinet has
+# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has
 # decided that Daylight Saving Time will not be used in Egypt during
 # Ramadan.
 #
 # Arabic translation:
-# "Clocks to go back during Ramadan--and then forward again"
-# 
+# "Clocks to go back during Ramadan - and then forward again"
 # http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_egypt02.html
-# 
 
 # From Ahmad El-Dardiry (2014-05-07):
 # Egypt is to change back to Daylight system on May 15
@@ -365,46 +342,77 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # From Gunther Vermier (2015-05-13):
 # our Egypt office confirms that the change will be at 15 May "midnight" (24:00)
 
-# From Paul Eggert (2014-05-13):
+# From Imed Chihi (2014-06-04):
+# We have finally "located" a precise official reference about the DST changes
+# in Egypt.  The Ministers Cabinet decision is explained at
+# http://www.cabinet.gov.eg/Media/CabinetMeetingsDetails.aspx?id=347 ...
+# [T]his (Arabic) site is not accessible outside Egypt, but the page ...
+# translates into: "With regard to daylight saving time, it is scheduled to
+# take effect at exactly twelve o'clock this evening, Thursday, 15 MAY 2014,
+# to be suspended by twelve o'clock on the evening of Thursday, 26 JUN 2014,
+# and re-established again at the end of the month of Ramadan, at twelve
+# o'clock on the evening of Thursday, 31 JUL 2014."  This statement has been
+# reproduced by other (more accessible) sites[, e.g.,]...
+# http://elgornal.net/news/news.aspx?id=4699258
+
+# From Paul Eggert (2014-06-04):
 # Sarah El Deeb and Lee Keath of AP report that the Egyptian government says
 # the change is because of blackouts in Cairo, even though Ahram Online (cited
-# above) says DST had no affect on electricity consumption.  The AP story says
-# DST will not be observed during Ramadan.  There is no information about when
-# DST will end.  See:
+# above) says DST had no affect on electricity consumption.  There is
+# no information about when DST will end this fall.  See:
 # http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833
 #
-# For now, guess that later transitions will use 2010's rules, and that
-# Egypt will agree with Morocco (see below) about the date Ramadan starts and
-# ends, though (unlike Morocco) it will switch at 00:00 standard time.  In
-# Egypt the spring-forward transitions are removed for 2020-2022, when the
-# guessed spring-forward date falls during the estimated Ramadan, and all
-# transitions removed for 2023-2038, where the estimated Ramadan falls entirely
-# outside the guessed daylight-saving time.  Ramadan intrudes on the guessed
-# DST starting in 2039, but that's beyond our somewhat-arbitrary cutoff.
-
-Rule	Egypt	2008	only	-	Aug	lastThu	23:00s	0	-
-Rule	Egypt	2009	only	-	Aug	20	23:00s	0	-
-Rule	Egypt	2010	only	-	Aug	11	0:00	0	-
-Rule	Egypt	2010	only	-	Sep	10	0:00	1:00	S
-Rule	Egypt	2010	only	-	Sep	lastThu	23:00s	0	-
+# For now, guess that later spring and fall transitions will use
+# 2010's rules, and guess that Egypt will switch to standard time at
+# 24:00 the last Thursday before Ramadan, and back to DST at 00:00 the
+# first Friday after Ramadan.  To implement this,
+# transition dates for 2015 through 2037 were determined by running
+# the following program under GNU Emacs 24.3, with the results integrated
+# by hand into the table below.  Ramadan again intrudes on the guessed
+# DST starting in 2038, but that's beyond our somewhat-arbitrary cutoff.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (friday 5))
+#       (while (/= friday (mod a 7))
+#         (setq a (1- a)))
+#       (while (/= friday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (1- a))
+#       (setq b (1- b))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t0\t-\n"
+#                 "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+#     (setq islamic-year (+ 1 islamic-year))))
+Rule	Egypt	2008	only	-	Aug	lastThu	24:00	0	-
+Rule	Egypt	2009	only	-	Aug	20	24:00	0	-
+Rule	Egypt	2010	only	-	Aug	10	24:00	0	-
+Rule	Egypt	2010	only	-	Sep	 9	24:00	1:00	S
+Rule	Egypt	2010	only	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2014	only	-	May	15	24:00	1:00	S
-Rule	Egypt	2014	only	-	Jun	29	 0:00s	0	-
-Rule	Egypt	2014	only	-	Jul	29	 0:00s	1:00	S
-Rule	Egypt	2014	max	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	2014	only	-	Jun	26	24:00	0	-
+Rule	Egypt	2014	only	-	Jul	31	24:00	1:00	S
+Rule	Egypt	2014	max	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2015	2019	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	2015	only	-	Jun	18	 0:00s	0	-
-Rule	Egypt	2015	only	-	Jul	18	 0:00s	1:00	S
-Rule	Egypt	2016	only	-	Jun	 7	 0:00s	0	-
-Rule	Egypt	2016	only	-	Jul	 7	 0:00s	1:00	S
-Rule	Egypt	2017	only	-	May	27	 0:00s	0	-
-Rule	Egypt	2017	only	-	Jun	26	 0:00s	1:00	S
-Rule	Egypt	2018	only	-	May	16	 0:00s	0	-
-Rule	Egypt	2018	only	-	Jun	15	 0:00s	1:00	S
-Rule	Egypt	2019	only	-	May	 6	 0:00s	0	-
-Rule	Egypt	2019	only	-	Jun	 5	 0:00s	1:00	S
-Rule	Egypt	2020	only	-	May	24	 0:00s	1:00	S
-Rule	Egypt	2021	only	-	May	13	 0:00s	1:00	S
-Rule	Egypt	2022	only	-	May	 3	 0:00s	1:00	S
+Rule	Egypt	2015	only	-	Jun	11	24:00	0	-
+Rule	Egypt	2015	only	-	Jul	23	24:00	1:00	S
+Rule	Egypt	2016	only	-	Jun	 2	24:00	0	-
+Rule	Egypt	2016	only	-	Jul	 7	24:00	1:00	S
+Rule	Egypt	2017	only	-	May	25	24:00	0	-
+Rule	Egypt	2017	only	-	Jun	29	24:00	1:00	S
+Rule	Egypt	2018	only	-	May	10	24:00	0	-
+Rule	Egypt	2018	only	-	Jun	14	24:00	1:00	S
+Rule	Egypt	2019	only	-	May	 2	24:00	0	-
+Rule	Egypt	2019	only	-	Jun	 6	24:00	1:00	S
+Rule	Egypt	2020	only	-	May	28	24:00	1:00	S
+Rule	Egypt	2021	only	-	May	13	24:00	1:00	S
+Rule	Egypt	2022	only	-	May	 5	24:00	1:00	S
 Rule	Egypt	2023	max	-	Apr	lastFri	 0:00s	1:00	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -412,60 +420,63 @@ Zone	Africa/Cairo	2:05:09 -	LMT	1900 Oct
 			2:00	Egypt	EE%sT
 
 # Equatorial Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Malabo	0:35:08 -	LMT	1912
-			0:00	-	GMT	1963 Dec 15
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Eritrea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Asmara	2:35:32 -	LMT	1870
-			2:35:32	-	AMT	1890	      # Asmara Mean Time
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:32	-	AMT	1890        # Asmara Mean Time
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Ethiopia
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones
-# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
-# We'll guess that 38E50 is for Adis Dera.
+# From Paul Eggert (2014-07-31):
+# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
+# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
+# 02:00 or 14:00.  Keep this in mind when you ask the time in Amharic.
+#
+# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
+# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
+# 1890, and that they switched to 3:00 on 1936-05-05.  Perhaps 38E50
+# was for Adis Dera.  Quite likely the Shanks data entries are wrong
+# anyway.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Addis_Ababa	2:34:48 -	LMT	1870
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Gabon
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Libreville	0:37:48 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Gambia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Banjul	-1:06:36 -	LMT	1912
-			-1:06:36 -	BMT	1935	# Banjul Mean Time
-			-1:00	-	WAT	1964
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Ghana
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman says DST was observed from 1931 to ``the present'';
-# go with Shanks & Pottenger.
-Rule	Ghana	1936	1942	-	Sep	 1	0:00	0:20	GHST
-Rule	Ghana	1936	1942	-	Dec	31	0:00	0	GMT
+# Whitman says DST was observed from 1931 to "the present";
+# Shanks & Pottenger say 1936 to 1942;
+# and September 1 to January 1 is given by:
+# Scott Keltie J, Epstein M (eds), The Statesman's Year-Book,
+# 57th ed. Macmillan, London (1920), OCLC 609408015, pp xxviii.
+# For lack of better info, assume DST was observed from 1920 to 1942.
+Rule	Ghana	1920	1942	-	Sep	 1	0:00	0:20	GHST
+Rule	Ghana	1920	1942	-	Dec	31	0:00	0	GMT
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Accra	-0:00:52 -	LMT	1918
 			 0:00	Ghana	%s
 
 # Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Conakry	-0:54:52 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Guinea-Bissau
+#
+# Shanks gives 1911-05-26 for the transition to WAT,
+# evidently confusing the date of the Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# with the date that it took effect, namely 1912-01-01.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bissau	-1:02:20 -	LMT	1911 May 26
+Zone	Africa/Bissau	-1:02:20 -	LMT	1912 Jan  1
 			-1:00	-	WAT	1975
 			 0:00	-	GMT
 
@@ -480,8 +491,8 @@ Zone	Africa/Nairobi	2:27:16	-	LMT	1928 Jul
 # Lesotho
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maseru	1:50:00 -	LMT	1903 Mar
-			2:00	-	SAST	1943 Sep 19 2:00
-			2:00	1:00	SAST	1944 Mar 19 2:00
+			2:00	-	SAST	1943 Sep 19  2:00
+			2:00	1:00	SAST	1944 Mar 19  2:00
 			2:00	-	SAST
 
 # Liberia
@@ -549,11 +560,11 @@ Zone	Africa/Tripoli	0:52:44 -	LMT	1920
 			2:00	-	EET	1982
 			1:00	Libya	CE%sT	1990 May  4
 # The 1996 and 1997 entries are from Shanks & Pottenger;
-# the IATA SSIM data contain some obvious errors.
+# the IATA SSIM data entries contain some obvious errors.
 			2:00	-	EET	1996 Sep 30
 			1:00	Libya	CE%sT	1997 Oct  4
-			2:00	-	EET	2012 Nov 10 2:00
-			1:00	Libya	CE%sT	2013 Oct 25 2:00
+			2:00	-	EET	2012 Nov 10  2:00
+			1:00	Libya	CE%sT	2013 Oct 25  2:00
 			2:00	-	EET
 
 # Madagascar
@@ -569,18 +580,8 @@ Zone	Africa/Blantyre	2:20:00 -	LMT	1903 Mar
 			2:00	-	CAT
 
 # Mali
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bamako	-0:32:00 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Jun 20
-			 0:00	-	GMT
-
 # Mauritania
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Nov 28
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Mauritius
 
@@ -604,9 +605,7 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 
 # From Steffen Thorsen (2008-07-10):
 # According to
-# 
 # http://www.lexpress.mu/display_article.php?news_id=111216
-# 
 # (in French), Mauritius will start and end their DST a few days earlier
 # than previously announced (2008-11-01 to 2009-03-31).  The new start
 # date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
@@ -621,22 +620,17 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 
 # From Alex Krivenyshev (2008-07-11):
 # Seems that English language article "The revival of daylight saving
-# time:  Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
 # published on Monday, June 30, 2008...
 #
 # I guess that article in French "Le gouvernement avance l'introduction
-# de l'heure d'ete" stating that DST in Mauritius starting on October 26
-# and ending on March 27, 2009 is the most recent one.
-# ...
-# 
+# de l'heure d'été" stating that DST in Mauritius starting on October 26
+# and ending on March 27, 2009 is the most recent one....
 # http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html
-# 
 
 # From Riad M. Hossen Ally (2008-08-03):
 # The Government of Mauritius weblink
-# 
 # http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
-# 
 # Cabinet Decision of July 18th, 2008 states as follows:
 #
 # 4. ...Cabinet has agreed to the introduction into the National Assembly
@@ -646,33 +640,25 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 # States of America. It will start at two o'clock in the morning on the
 # last Sunday of October and will end at two o'clock in the morning on
 # the last Sunday of March the following year. The summer time for the
-# year 2008 - 2009 will, therefore, be effective as from 26 October 2008
+# year 2008-2009 will, therefore, be effective as from 26 October 2008
 # and end on 29 March 2009.
 
 # From Ed Maste (2008-10-07):
 # THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the
 # beginning / ending of summer time is 2 o'clock standard time in the
 # morning of the last Sunday of October / last Sunday of March.
-# 
 # http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
-# 
 
 # From Steffen Thorsen (2009-06-05):
 # According to several sources, Mauritius will not continue to observe
 # DST the coming summer...
 #
 # Some sources, in French:
-# 
 # http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB
-# 
-# 
 # http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-
-# 
 #
 # Our wrap-up:
-# 
 # http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html
-# 
 
 # From Arthur David Olson (2009-07-11):
 # The "mauritius-dst-will-not-repeat" wrapup includes this:
@@ -685,18 +671,18 @@ Rule Mauritius	1983	only	-	Mar	21	0:00	0	-
 Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	S
 Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Mauritius	3:50:00 -	LMT	1907		# Port Louis
+Zone Indian/Mauritius	3:50:00 -	LMT	1907 # Port Louis
 			4:00 Mauritius	MU%sT	# Mauritius Time
 # Agalega Is, Rodriguez
 # no information; probably like Indian/Mauritius
 
 # Mayotte
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
+Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul # Mamoutzou
 			3:00	-	EAT
 
 # Morocco
-# See the `europe' file for Spanish Morocco (Africa/Ceuta).
+# See the 'europe' file for Spanish Morocco (Africa/Ceuta).
 
 # From Alex Krivenyshev (2008-05-09):
 # Here is an article that Morocco plan to introduce Daylight Saving Time between
@@ -704,60 +690,44 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 #
 # "... Morocco is to save energy by adjusting its clock during summer so it will
 # be one hour ahead of GMT between 1 June and 27 September, according to
-# Communication Minister and Gov ernment Spokesman, Khalid Naciri...."
+# Communication Minister and Government Spokesman, Khalid Naciri...."
 #
-# 
 # http://www.worldtimezone.net/dst_news/dst_news_morocco01.html
-# 
-# OR
-# 
 # http://en.afrik.com/news11892.html
-# 
 
 # From Alex Krivenyshev (2008-05-09):
-# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse:
-# 
+# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe
+# Presse:
 # http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view
-# 
 #
 # Morocco shifts to daylight time on June 1st through September 27, Govt.
 # spokesman.
 
 # From Patrice Scattolin (2008-05-09):
 # According to this article:
-# 
 # http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html
-# 
-# (and republished here:
-# 
-# http://www.actu.ma/heure-dete-comment_i127896_0.html
-# 
-# )
-# the changes occurs at midnight:
-#
-# saturday night may 31st at midnight (which in french is to be
-# intrepreted as the night between saturday and sunday)
-# sunday night the 28th  at midnight
-#
-# Seeing that the 28th is monday, I am guessing that she intends to say
-# the midnight of the 28th which is the midnight between sunday and
-# monday, which jives with other sources that say that it's inclusive
-# june1st to sept 27th.
+# (and republished here: )
+# the changes occur at midnight:
+#
+# Saturday night May 31st at midnight (which in French is to be
+# interpreted as the night between Saturday and Sunday)
+# Sunday night the 28th at midnight
+#
+# Seeing that the 28th is Monday, I am guessing that she intends to say
+# the midnight of the 28th which is the midnight between Sunday and
+# Monday, which jives with other sources that say that it's inclusive
+# June 1st to Sept 27th.
 #
 # The decision was taken by decree *2-08-224 *but I can't find the decree
 # published on the web.
 #
 # It's also confirmed here:
-# 
 # http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm
-# 
-# on a government portal as being  between june 1st and sept 27th (not yet
-# posted in english).
+# on a government portal as being between June 1st and Sept 27th (not yet
+# posted in English).
 #
-# The following google query will generate many relevant hits:
-# 
+# The following Google query will generate many relevant hits:
 # http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search
-# 
 
 # From Steffen Thorsen (2008-08-27):
 # Morocco will change the clocks back on the midnight between August 31
@@ -765,47 +735,32 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # of September:
 #
 # One article about it (in French):
-# 
 # http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default
-# 
 #
 # We have some further details posted here:
-# 
 # http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
-# 
 
 # From Steffen Thorsen (2009-03-17):
 # Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according
 # to many sources, such as
-# 
 # http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html
-# 
-# 
 # http://www.medi1sat.ma/fr/depeche.aspx?idp=2312
-# 
 # (French)
 #
 # Our summary:
-# 
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html
-# 
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to official document from Royaume du Maroc Premier Ministre,
-# Ministere de la Modernisation des Secteurs Publics
+# Ministère de la Modernisation des Secteurs Publics
 #
 # Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
 # concerning the amendment of the legal time, the Ministry of Modernization of
 # Public Sectors announced that the official time in the Kingdom will be
 # advanced 60 minutes from Sunday 31 May 2009 at midnight.
 #
-# 
 # http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf
-# 
-#
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_morocco03.html
-# 
 
 # From Steffen Thorsen (2010-04-13):
 # Several news media in Morocco report that the Ministry of Modernization
@@ -813,51 +768,33 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # 2010-05-02 to 2010-08-08.
 #
 # Example:
-# 
 # http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html
-# 
 # (French)
 # Our page:
-# 
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html
-# 
 
 # From Dan Abitol (2011-03-30):
 # ...Rules for Africa/Casablanca are the following (24h format)
-# The 3rd april 2011 at 00:00:00, [it] will be 3rd april 1:00:00
-# The 31th july 2011 at 00:59:59,  [it] will be 31th July 00:00:00
+# The 3rd April 2011 at 00:00:00, [it] will be 3rd April 01:00:00
+# The 31st July 2011 at 00:59:59, [it] will be 31st July 00:00:00
 # ...Official links of change in morocco
 # The change was broadcast on the FM Radio
 # I ve called ANRT (telecom regulations in Morocco) at
 # +212.537.71.84.00
-# 
 # http://www.anrt.net.ma/fr/
-# 
 # They said that
-# 
 # http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view
-# 
 # is the official publication to look at.
 # They said that the decision was already taken.
 #
 # More articles in the press
-# 
-# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev
-# 
-# e.html
-# 
+# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-leve.html
 # http://www.lematin.ma/Actualite/Express/Article.asp?id=148923
-# 
-# 
 # http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim
-# anche-prochain-5538.html
-# 
 
 # From Petr Machata (2011-03-30):
 # They have it written in English here:
-# 
 # http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view
-# 
 #
 # It says there that "Morocco will resume its standard time on July 31,
 # 2011 at midnight." Now they don't say whether they mean midnight of
@@ -865,20 +802,16 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # also been like that in the past.
 
 # From Alexander Krivenyshev (2012-03-09):
-# According to Infomédiaire web site from Morocco (infomediaire.ma),
-# on March 9, 2012, (in French) Heure légale:
-# Le Maroc adopte officiellement l'heure d'été
-# 
+# According to Infomédiaire web site from Morocco (infomediaire.ma),
+# on March 9, 2012, (in French) Heure légale:
+# Le Maroc adopte officiellement l'heure d'été
 # http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9
-# 
 # Governing Council adopted draft decree, that Morocco DST starts on
 # the last Sunday of March (March 25, 2012) and ends on
 # last Sunday of September (September 30, 2012)
 # except the month of Ramadan.
 # or (brief)
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_morocco06.html
-# 
 
 # From Arthur David Olson (2012-03-10):
 # The infomediaire.ma source indicates that the system is to be in
@@ -889,17 +822,13 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 
 # From Christophe Tropamer (2012-03-16):
 # Seen Morocco change again:
-# 
 # http://www.le2uminutes.com/actualite.php
-# 
-# "...à partir du dernier dimance d'avril et non fins mars,
-# comme annoncé précédemment."
+# "...à partir du dernier dimanche d'avril et non fins mars,
+# comme annoncé précédemment."
 
 # From Milamber Space Network (2012-07-17):
 # The official return to GMT is announced by the Moroccan government:
-# 
 # http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French]
-# 
 #
 # Google translation, lightly edited:
 # Back to the standard time of the Kingdom (GMT)
@@ -917,7 +846,7 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # announced a bit in advance.  On 2012-07-11 the Moroccan government
 # announced that year's Ramadan daylight-saving transitions would be
 # 2012-07-20 and 2012-08-20; see
-# .
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288
 
 # From Andrew Paprocki (2013-07-02):
 # Morocco announced that the year's Ramadan daylight-savings
@@ -937,39 +866,36 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # From Sebastien Willemijns (2014-03-18):
 # http://www.afriquinfos.com/articles/2014/3/18/maroc-heure-dete-avancez-tous-horloges-247891.asp
 
-# From Paul Eggert (2014-03-19):
-# To estimate what the Moroccan government will do in future years,
-# transition dates for 2014 through 2038 were determined by running
-# the following program under GNU Emacs 24.3:
-#
-# (let ((islamic-year 1435))
-#   (while (< islamic-year 1461)
-#     (let ((a
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 9 1 islamic-year))))
-#	    (b
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 10 1 islamic-year)))))
-#	(insert
-#	 (format
-#	  (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 3:00\t0\t-\n"
-#		  "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 2:00\t1:00\tS\n")
-#	  (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
-#	  (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+# From Milamber Space Network (2014-06-05):
+# The Moroccan government has recently announced that the country will return
+# to standard time at 03:00 on Saturday, June 28, 2014 local time....  DST
+# will resume again at 02:00 on Saturday, August 2, 2014....
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=586
+
+# From Paul Eggert (2014-06-05):
+# For now, guess that later spring and fall transitions will use 2014's rules,
+# and guess that Morocco will switch to standard time at 03:00 the last
+# Saturday before Ramadan, and back to DST at 02:00 the first Saturday after
+# Ramadan.  To implement this, transition dates for 2015 through 2037 were
+# determined by running the following program under GNU Emacs 24.3, with the
+# results integrated by hand into the table below.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (saturday 6))
+#       (while (/= saturday (mod (setq a (1- a)) 7)))
+#       (while (/= saturday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t0\t-\n"
+#                 "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
 #     (setq islamic-year (+ 1 islamic-year))))
-#
-# with spring-forward transitions removed for 2023-2025, when the
-# normal spring-forward date falls during the estimated Ramadan; with
-# all transitions removed for 2026-2035, where the estimated Ramadan
-# falls entirely outside daylight-saving time; and with fall-back
-# transitions removed for 2036-2037, where the normal fall-back
-# date falls during the estimated Ramadan.  Normally, the table would
-# stop after 2037 because 32-bit time_t values roll around early in 2038,
-# but that would imply a prediction of perpetual DST after March 2038
-# due to the year-2037 glitches.  So, this table instead stops after
-# 2038, the first non-glitchy year after the 32-bit rollover.
-# An advantage of stopping after 2038 is that it lets zic guess
-# TZ='WET0WEST,M3.5.0,M10.5.0/3' for time stamps far in the future.
 
 # RULE	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 
@@ -991,46 +917,44 @@ Rule	Morocco	1978	only	-	Aug	 4	 0:00	0	-
 Rule	Morocco	2008	only	-	Jun	 1	 0:00	1:00	S
 Rule	Morocco	2008	only	-	Sep	 1	 0:00	0	-
 Rule	Morocco	2009	only	-	Jun	 1	 0:00	1:00	S
-Rule	Morocco	2009	only	-	Aug	 21	 0:00	0	-
+Rule	Morocco	2009	only	-	Aug	21	 0:00	0	-
 Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
 Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
 Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
-Rule	Morocco	2011	only	-	Jul	 31	 0	0	-
-Rule	Morocco	2012	2013	-	Apr	 lastSun 2:00	1:00	S
-Rule	Morocco	2012	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2012	only	-	Jul	 20	 3:00	0	-
-Rule	Morocco	2012	only	-	Aug	 20	 2:00	1:00	S
-Rule	Morocco	2013	only	-	Jul	  7	 3:00	0	-
-Rule	Morocco	2013	only	-	Aug	 10	 2:00	1:00	S
-Rule	Morocco	2013	2035	-	Oct	 lastSun 3:00	0	-
-Rule	Morocco	2014	2022	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2014	only	-	Jun	 29	 3:00	0	-
-Rule	Morocco	2014	only	-	Jul	 29	 2:00	1:00	S
-Rule	Morocco	2015	only	-	Jun	 18	 3:00	0	-
-Rule	Morocco	2015	only	-	Jul	 18	 2:00	1:00	S
-Rule	Morocco	2016	only	-	Jun	  7	 3:00	0	-
-Rule	Morocco	2016	only	-	Jul	  7	 2:00	1:00	S
-Rule	Morocco	2017	only	-	May	 27	 3:00	0	-
-Rule	Morocco	2017	only	-	Jun	 26	 2:00	1:00	S
-Rule	Morocco	2018	only	-	May	 16	 3:00	0	-
-Rule	Morocco	2018	only	-	Jun	 15	 2:00	1:00	S
-Rule	Morocco	2019	only	-	May	  6	 3:00	0	-
-Rule	Morocco	2019	only	-	Jun	  5	 2:00	1:00	S
-Rule	Morocco	2020	only	-	Apr	 24	 3:00	0	-
-Rule	Morocco	2020	only	-	May	 24	 2:00	1:00	S
-Rule	Morocco	2021	only	-	Apr	 13	 3:00	0	-
-Rule	Morocco	2021	only	-	May	 13	 2:00	1:00	S
-Rule	Morocco	2022	only	-	Apr	  3	 3:00	0	-
-Rule	Morocco	2022	only	-	May	  3	 2:00	1:00	S
-Rule	Morocco	2023	only	-	Apr	 22	 2:00	1:00	S
-Rule	Morocco	2024	only	-	Apr	 10	 2:00	1:00	S
-Rule	Morocco	2025	only	-	Mar	 31	 2:00	1:00	S
-Rule	Morocco	2026	max	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2036	only	-	Oct	 21	 3:00	0	-
-Rule	Morocco	2037	only	-	Oct	 11	 3:00	0	-
-Rule	Morocco	2038	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2038	only	-	Oct	 30	 2:00	1:00	S
-Rule	Morocco	2038	max	-	Oct	 lastSun 3:00	0	-
+Rule	Morocco	2011	only	-	Jul	31	 0	0	-
+Rule	Morocco	2012	2013	-	Apr	lastSun	 2:00	1:00	S
+Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
+Rule	Morocco	2012	only	-	Jul	20	 3:00	0	-
+Rule	Morocco	2012	only	-	Aug	20	 2:00	1:00	S
+Rule	Morocco	2013	only	-	Jul	 7	 3:00	0	-
+Rule	Morocco	2013	only	-	Aug	10	 2:00	1:00	S
+Rule	Morocco	2013	max	-	Oct	lastSun	 3:00	0	-
+Rule	Morocco	2014	2022	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2014	only	-	Jun	28	 3:00	0	-
+Rule	Morocco	2014	only	-	Aug	 2	 2:00	1:00	S
+Rule	Morocco	2015	only	-	Jun	13	 3:00	0	-
+Rule	Morocco	2015	only	-	Jul	18	 2:00	1:00	S
+Rule	Morocco	2016	only	-	Jun	 4	 3:00	0	-
+Rule	Morocco	2016	only	-	Jul	 9	 2:00	1:00	S
+Rule	Morocco	2017	only	-	May	20	 3:00	0	-
+Rule	Morocco	2017	only	-	Jul	 1	 2:00	1:00	S
+Rule	Morocco	2018	only	-	May	12	 3:00	0	-
+Rule	Morocco	2018	only	-	Jun	16	 2:00	1:00	S
+Rule	Morocco	2019	only	-	May	 4	 3:00	0	-
+Rule	Morocco	2019	only	-	Jun	 8	 2:00	1:00	S
+Rule	Morocco	2020	only	-	Apr	18	 3:00	0	-
+Rule	Morocco	2020	only	-	May	30	 2:00	1:00	S
+Rule	Morocco	2021	only	-	Apr	10	 3:00	0	-
+Rule	Morocco	2021	only	-	May	15	 2:00	1:00	S
+Rule	Morocco	2022	only	-	Apr	 2	 3:00	0	-
+Rule	Morocco	2022	only	-	May	 7	 2:00	1:00	S
+Rule	Morocco	2023	only	-	Apr	22	 2:00	1:00	S
+Rule	Morocco	2024	only	-	Apr	13	 2:00	1:00	S
+Rule	Morocco	2025	only	-	Apr	 5	 2:00	1:00	S
+Rule	Morocco	2026	max	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2035	only	-	Oct	27	 3:00	0	-
+Rule	Morocco	2036	only	-	Oct	18	 3:00	0	-
+Rule	Morocco	2037	only	-	Oct	10	 3:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
@@ -1049,11 +973,17 @@ Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
 # Assume that this has been true since Western Sahara switched to GMT,
 # since most of it was then controlled by Morocco.
 
-Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan
+Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan # El Aaiún
 			-1:00	-	WAT	1976 Apr 14
 			 0:00	Morocco	WE%sT
 
 # Mozambique
+#
+# Shanks gives 1903-03-01 for the transition to CAT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 			2:00	-	CAT
@@ -1062,8 +992,8 @@ Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 # The 1994-04-03 transition is from Shanks & Pottenger.
 # Shanks & Pottenger report no DST after 1998-04; go with IATA.
 
-# From Petronella Sibeene (2007-03-30) in
-# :
+# From Petronella Sibeene (2007-03-30):
+# http://allafrica.com/stories/200703300178.html
 # While the entire country changes its time, Katima Mulilo and other
 # settlements in Caprivi unofficially will not because the sun there
 # rises and sets earlier compared to other regions.  Chief of
@@ -1080,34 +1010,41 @@ Rule	Namibia	1994	max	-	Sep	Sun>=1	2:00	1:00	S
 Rule	Namibia	1995	max	-	Apr	Sun>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Windhoek	1:08:24 -	LMT	1892 Feb 8
-			1:30	-	SWAT	1903 Mar	# SW Africa Time
-			2:00	-	SAST	1942 Sep 20 2:00
-			2:00	1:00	SAST	1943 Mar 21 2:00
+			1:30	-	SWAT	1903 Mar    # SW Africa Time
+			2:00	-	SAST	1942 Sep 20  2:00
+			2:00	1:00	SAST	1943 Mar 21  2:00
 			2:00	-	SAST	1990 Mar 21 # independence
 			2:00	-	CAT	1994 Apr  3
 			1:00	Namibia	WA%sT
 
 # Niger
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Niamey	 0:08:28 -	LMT	1912
-			-1:00	-	WAT	1934 Feb 26
-			 0:00	-	GMT	1960
-			 1:00	-	WAT
+# See Africa/Lagos.
 
 # Nigeria
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Lagos	0:13:36 -	LMT	1919 Sep
 			1:00	-	WAT
-
-# Reunion
+Link Africa/Lagos Africa/Bangui	     # Central African Republic
+Link Africa/Lagos Africa/Brazzaville # Rep. of the Congo
+Link Africa/Lagos Africa/Douala	     # Cameroon
+Link Africa/Lagos Africa/Kinshasa    # Dem. Rep. of the Congo (west)
+Link Africa/Lagos Africa/Libreville  # Gabon
+Link Africa/Lagos Africa/Luanda	     # Angola
+Link Africa/Lagos Africa/Malabo	     # Equatorial Guinea
+Link Africa/Lagos Africa/Niamey	     # Niger
+Link Africa/Lagos Africa/Porto-Novo  # Benin
+
+# Réunion
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun	# Saint-Denis
-			4:00	-	RET	# Reunion Time
+Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun # Saint-Denis
+			4:00	-	RET	# Réunion Time
 #
-# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
+# Crozet Islands also observes Réunion time; see the 'antarctica' file.
+#
+# Scattered Islands (Îles Éparses) administered from Réunion are as follows.
 # The following information about them is taken from
-# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
-# no longer available as of 1999-08-17).
+# Îles Éparses (, 1997-07-22,
+# in French; no longer available as of 1999-08-17).
 # We have no info about their time zone histories.
 #
 # Bassas da India - uninhabited
@@ -1122,32 +1059,21 @@ Zone	Africa/Kigali	2:00:16 -	LMT	1935 Jun
 			2:00	-	CAT
 
 # St Helena
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/St_Helena	-0:22:48 -	LMT	1890		# Jamestown
-			-0:22:48 -	JMT	1951	# Jamestown Mean Time
-			 0:00	-	GMT
+# See Africa/Abidjan.
 # The other parts of the St Helena territory are similar:
 #	Tristan da Cunha: on GMT, say Whitman and the CIA
-#	Ascension: on GMT, says usno1995 and the CIA
+#	Ascension: on GMT, say the USNO (1995-12-21) and the CIA
 #	Gough (scientific station since 1955; sealers wintered previously):
 #		on GMT, says the CIA
-#	Inaccessible, Nightingale: no information, but probably GMT
-
-# Sao Tome and Principe
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Sao_Tome	 0:26:56 -	LMT	1884
-			-0:36:32 -	LMT	1912	# Lisbon Mean Time
-			 0:00	-	GMT
+#	Inaccessible, Nightingale: uninhabited
 
+# São Tomé and Príncipe
 # Senegal
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Dakar	-1:09:44 -	LMT	1912
-			-1:00	-	WAT	1941 Jun
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Seychelles
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
+Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun # Victoria
 			4:00	-	SCT	# Seychelles Time
 # From Paul Eggert (2001-05-30):
 # Aldabra, Farquhar, and Desroches, originally dependencies of the
@@ -1157,17 +1083,7 @@ Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
 # Possibly the islands were uninhabited.
 
 # Sierra Leone
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger.
-Rule	SL	1935	1942	-	Jun	 1	0:00	0:40	SLST
-Rule	SL	1935	1942	-	Oct	 1	0:00	0	WAT
-Rule	SL	1957	1962	-	Jun	 1	0:00	1:00	SLST
-Rule	SL	1957	1962	-	Sep	 1	0:00	0	GMT
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Freetown	-0:53:00 -	LMT	1882
-			-0:53:00 -	FMT	1913 Jun # Freetown Mean Time
-			-1:00	SL	%s	1957
-			 0:00	SL	%s
+# See Africa/Abidjan.
 
 # Somalia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1190,9 +1106,9 @@ Zone Africa/Johannesburg 1:52:00 -	LMT	1892 Feb 8
 
 # Sudan
 #
-# From 
-# Sudan News Agency (2000-01-13)
-# , also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
+# From 
+# Sudan News Agency (2000-01-13),
+# also reported by Michaël De Beukelaer-Dossche via Steffen Thorsen:
 # Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
 # Saturday....  This was announced Thursday by Caretaker State Minister for
 # Manpower Abdul-Rahman Nur-Eddin.
@@ -1223,14 +1139,12 @@ Zone Africa/Dar_es_Salaam 2:37:08 -	LMT	1931
 			3:00	-	EAT
 
 # Togo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Lome	0:04:52 -	LMT	1893
-			0:00	-	GMT
+# See Africa/Abidjan.
 
 # Tunisia
 
 # From Gwillim Law (2005-04-30):
-# My correspondent, Risto Nykanen, has alerted me to another adoption of DST,
+# My correspondent, Risto Nykänen, has alerted me to another adoption of DST,
 # this time in Tunisia.  According to Yahoo France News
 # , in a story attributed to AP
 # and dated 2005-04-26, "Tunisia has decided to advance its official time by
@@ -1239,8 +1153,8 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # Saturday."  (My translation)
 #
 # From Oscar van Vlijmen (2005-05-02):
-# LaPresse, the first national daily newspaper ...
-# 
+# La Presse, the first national daily newspaper ...
+# http://www.lapresse.tn/archives/archives280405/actualites/lheure.html
 # ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30,
 # 1h standard time.
 #
@@ -1253,18 +1167,12 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # From Steffen Thorsen (2009-03-16):
 # According to several news sources, Tunisia will not observe DST this year.
 # (Arabic)
-# 
 # http://www.elbashayer.com/?page=viewn&nid=42546
-# 
-# 
 # http://www.babnet.net/kiwidetail-15295.asp
-# 
 #
 # We have also confirmed this with the US embassy in Tunisia.
 # We have a wrap-up about this on the following page:
-# 
 # http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html
-# 
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to Tunis Afrique Presse News Agency
@@ -1272,20 +1180,17 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # Standard time to be kept the whole year long (tap.info.tn):
 #
 # (in English)
-# 
 # http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157
-# 
 #
 # (in Arabic)
-# 
 # http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1
-# 
 
-# From Arthur David Olson (2009--3-18):
-# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact
-# that the fasting month of ramadan coincides with the period concerned by summer time.
-# Therefore, the standard time will be kept unchanged the whole year long."
-# So foregoing DST seems to be an exception (albeit one that may be repeated in the  future).
+# From Arthur David Olson (2009-03-18):
+# The Tunis Afrique Presse News Agency notice contains this: "This measure is
+# due to the fact that the fasting month of Ramadan coincides with the period
+# concerned by summer time.  Therefore, the standard time will be kept
+# unchanged the whole year long."  So foregoing DST seems to be an exception
+# (albeit one that may be repeated in the future).
 
 # From Alexander Krivenyshev (2010-03-27):
 # According to some news reports Tunis confirmed not to use DST in 2010
@@ -1297,12 +1202,8 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # coincided with the month of Ramadan..."
 #
 # (in Arabic)
-# 
 # http://www.moheet.com/show_news.aspx?nid=358861&pg=1
-# 
 # http://www.almadenahnews.com/newss/news.php?c=118&id=38036
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_tunis02.html
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1337,7 +1238,7 @@ Rule	Tunisia	2006	2008	-	Oct	lastSun	 2:00s	0	-
 # Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Tunis	0:40:44 -	LMT	1881 May 12
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			1:00	Tunisia	CE%sT
 
 # Uganda
diff --git a/make/data/tzdata/antarctica b/make/data/tzdata/antarctica
index e31bada94fb711b41f7bfba27d655c662d9b614e..0cdac27086160968d754b480ea825831be348b6b 100644
--- a/make/data/tzdata/antarctica
+++ b/make/data/tzdata/antarctica
@@ -21,19 +21,16 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # From Paul Eggert (1999-11-15):
 # To keep things manageable, we list only locations occupied year-round; see
-# 
 # COMNAP - Stations and Bases
-# 
+# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/
 # and
-# 
 # Summary of the Peri-Antarctic Islands (1998-07-23)
-# 
+# http://www.spri.cam.ac.uk/bob/periant.htm
 # for information.
 # Unless otherwise specified, we have no time zone information.
 #
@@ -78,19 +75,19 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
-# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
-# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
-# Marambio, Seymour I, -6414-05637, since 1969-10-29
+# Carlini, Potter Cove, King George Island, -6414-0602320, since 1982-01
+# Esperanza, Hope Bay, -6323-05659, since 1952-12-17
+# Marambio, -6414-05637, since 1969-10-29
 # Orcadas, Laurie I, -6016-04444, since 1904-02-22
-# San Martin, Debenham I, -6807-06708, since 1951-03-21
+# San Martín, Barry I, -6808-06706, since 1951-03-21
 #	(except 1960-03 / 1976-03-21)
 
 # Australia - territories
 # Heard Island, McDonald Islands (uninhabited)
 #	previously sealers and scientific personnel wintered
-#	
 #	Margaret Turner reports
-#	 (1999-09-30) that they're UTC+5, with no DST;
+#	http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
+#	(1999-09-30) that they're UTC+5, with no DST;
 #	presumably this is when they have visitors.
 #
 # year-round bases
@@ -107,14 +104,10 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 # The changes occurred on 2009-10-18 at 02:00 (local times).
 #
 # Government source: (Australian Antarctic Division)
-# 
 # http://www.aad.gov.au/default.asp?casid=37079
-# 
 #
 # We have more background information here:
-# 
 # http://www.timeanddate.com/news/time/antarctica-new-times.html
-# 
 
 # From Steffen Thorsen (2010-03-10):
 # We got these changes from the Australian Antarctic Division: ...
@@ -129,50 +122,49 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 # - Mawson station stays on UTC+5.
 #
 # Background:
-# 
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
-# 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Casey	0	-	zzz	1969
-			8:00	-	WST	2009 Oct 18 2:00
-						# Western (Aus) Standard Time
-			11:00	-	CAST	2010 Mar 5 2:00
-						# Casey Time
-			8:00	-	WST	2011 Oct 28 2:00
+			8:00	-	AWST	2009 Oct 18  2:00
+						# Australian Western Std Time
+			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
+			8:00	-	AWST	2011 Oct 28  2:00
 			11:00	-	CAST	2012 Feb 21 17:00u
-			8:00	-	WST
+			8:00	-	AWST
 Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
-			7:00	-	DAVT	1964 Nov # Davis Time
+			7:00	-	DAVT	1964 Nov    # Davis Time
 			0	-	zzz	1969 Feb
-			7:00	-	DAVT	2009 Oct 18 2:00
+			7:00	-	DAVT	2009 Oct 18  2:00
 			5:00	-	DAVT	2010 Mar 10 20:00u
-			7:00	-	DAVT	2011 Oct 28 2:00
+			7:00	-	DAVT	2011 Oct 28  2:00
 			5:00	-	DAVT	2012 Feb 21 20:00u
 			7:00	-	DAVT
 Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
-			6:00	-	MAWT	2009 Oct 18 2:00
-						# Mawson Time
+			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
 			5:00	-	MAWT
 # References:
-# 
 # Casey Weather (1998-02-26)
-# 
-# 
+# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
 # Davis Station, Antarctica (1998-02-26)
-# 
-# 
+# http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html
 # Mawson Station, Antarctica (1998-02-25)
-# 
+# http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html
+
+# Belgium - year-round base
+# Princess Elisabeth, Queen Maud Land, -713412+0231200, since 2007
 
 # Brazil - year-round base
-# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
+# Ferraz, King George Island, -6205+05824, since 1983/4
+
+# Bulgaria - year-round base
+# St. Kliment Ohridski, Livingston Island, -623829-0602153, since 1988
 
 # Chile - year-round bases and towns
 # Escudero, South Shetland Is, -621157-0585735, since 1994
-# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
-# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
-# Capitan Arturo Prat, -6230-05941
+# Frei Montalva, King George Island, -6214-05848, since 1969-03-07
+# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
+# Prat, -6230-05941
 # Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
 # These locations have always used Santiago time; use TZ='America/Santiago'.
 
@@ -180,31 +172,35 @@ Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
 # Great Wall, King George Island, -6213-05858, since 1985-02-20
 # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
 
-# France - year-round bases
+# France - year-round bases (also see "France & Italy")
 #
 # From Antoine Leca (1997-01-20):
-# Time data are from Nicole Pailleau at the IFRTP
+# Time data entries are from Nicole Pailleau at the IFRTP
 # (French Institute for Polar Research and Technology).
-# She confirms that French Southern Territories and Terre Adelie bases
-# don't observe daylight saving time, even if Terre Adelie supplies came
+# She confirms that French Southern Territories and Terre Adélie bases
+# don't observe daylight saving time, even if Terre Adélie supplies came
 # from Tasmania.
 #
 # French Southern Territories with year-round inhabitants
 #
-# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
-# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
-# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
+# Alfred Faure, Possession Island, Crozet Islands, -462551+0515152, since 1964;
+#	sealing & whaling stations operated variously 1802/1911+;
+#	see Indian/Reunion.
+#
+# Martin-de-Viviès, Amsterdam Island, -374105+0773155, since 1950
+# Port-aux-Français, Kerguelen Islands, -492110+0701303, since 1951;
 #	whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
 #
 # St Paul Island - near Amsterdam, uninhabited
 #	fishing stations operated variously 1819/1931
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Kerguelen	0	-	zzz	1950	# Port-aux-Francais
+Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
 			5:00	-	TFT	# ISO code TF Time
 #
 # year-round base in the main continent
-# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
+# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
+#  (2005-12-05)
 #
 # Another base at Port-Martin, 50km east, began operation in 1947.
 # It was destroyed by fire on 1952-01-14.
@@ -214,20 +210,22 @@ Zone Antarctica/DumontDUrville 0 -	zzz	1947
 			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
 			0	-	zzz	1956 Nov
 			10:00	-	DDUT	# Dumont-d'Urville Time
-# Reference:
-# 
-# Dumont d'Urville Station (2005-12-05)
-# 
+
+# France & Italy - year-round base
+# Concordia, -750600+1232000, since 2005
 
 # Germany - year-round base
-# Georg von Neumayer, -7039-00815
+# Neumayer III, -704080-0081602, since 2009
 
-# India - year-round base
-# Dakshin Gangotri, -7005+01200
+# India - year-round bases
+# Bharati, -692428+0761114, since 2012
+# Maitri, -704558+0114356, since 1989
+
+# Italy - year-round base (also see "France & Italy")
+# Zuchelli, Terra Nova Bay, -744140+1640647, since 1986
 
 # Japan - year-round bases
-# Dome Fuji, -7719+03942
-# Syowa, -690022+0393524
+# Syowa (also known as Showa), -690022+0393524, since 1957
 #
 # From Hideyuki Suzuki (1999-02-06):
 # In all Japanese stations, +0300 is used as the standard time.
@@ -239,11 +237,11 @@ Zone Antarctica/DumontDUrville 0 -	zzz	1947
 Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
 			3:00	-	SYOT	# Syowa Time
 # See:
-# 
 # NIPR Antarctic Research Activities (1999-08-17)
-# 
+# http://www.nipr.ac.jp/english/ara01.html
 
 # S Korea - year-round base
+# Jang Bogo, Terra Nova Bay, -743700+1641205 since 2014
 # King Sejong, King George Island, -6213-05847, since 1988
 
 # New Zealand - claims
@@ -287,11 +285,14 @@ Rule	Troll	2005	max	-	Mar	lastSun	1:00u	2:00	CEST
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
-     			0:00	Troll	%s
+			0:00	Troll	%s
 
 # Poland - year-round base
 # Arctowski, King George Island, -620945-0582745, since 1977
 
+# Romania - year-bound base
+# Law-Racoviță, Larsemann Hills, -692319+0762251, since 1986
+
 # Russia - year-round bases
 # Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
 # Mirny, Davis coast, -6633+09301, since 1956-02
@@ -301,8 +302,8 @@ Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
 #	year-round from 1960/61 to 1992
 
 # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
-# 
-# From Craig Mundell (1994-12-15):
+# From Craig Mundell (1994-12-15):
+# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
 # Vostok, which is one of the Russian stations, is set on the same
 # time as Moscow, Russia.
 #
@@ -317,7 +318,7 @@ Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
 #
 # From Paul Eggert (2001-05-04):
 # This seems to be hopelessly confusing, so I asked Lee Hotz about it
-# in person.  He said that some Antartic locations set their local
+# in person.  He said that some Antarctic locations set their local
 # time so that noon is the warmest part of the day, and that this
 # changes during the year and does not necessarily correspond to mean
 # solar noon.  So the Vostok time might have been whatever the clocks
@@ -329,9 +330,12 @@ Zone Antarctica/Vostok	0	-	zzz	1957 Dec 16
 
 # S Africa - year-round bases
 # Marion Island, -4653+03752
-# Sanae, -7141-00250
+# SANAE IV, Vesleskarvet, Queen Maud Land, -714022-0025026, since 1997
+
+# Ukraine - year-round base
+# Vernadsky (formerly Faraday), Galindez Island, -651445-0641526, since 1954
 
-# UK
+# United Kingdom
 #
 # British Antarctic Territories (BAT) claims
 # South Orkney Islands
@@ -387,7 +391,7 @@ Zone Antarctica/Palmer	0	-	zzz	1965
 # but that he found it more convenient to keep GMT+12
 # as supplies for the station were coming from McMurdo Sound,
 # which was on GMT+12 because New Zealand was on GMT+12 all year
-# at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
+# at that time (1957).  (Source: Siple's book 90 Degrees South.)
 #
 # From Susan Smith
 # http://www.cybertours.com/whs/pole10.html
diff --git a/make/data/tzdata/asia b/make/data/tzdata/asia
index 595c8ed7245b4a96440a84e356070d2a246e18f1..906c0a97cda61696d2efcf3e1224cd92fc727c09 100644
--- a/make/data/tzdata/asia
+++ b/make/data/tzdata/asia
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-08-11):
 #
@@ -49,13 +49,17 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
+#
+# For Russian data circa 1919, a source is:
+# Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+# (See the 'europe' file for a fuller citation.)
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
 #	     std  dst
@@ -70,13 +74,14 @@
 #	7:00 WIB	west Indonesia (Waktu Indonesia Barat)
 #	8:00 WITA	central Indonesia (Waktu Indonesia Tengah)
 #	8:00 CST	China
-#	9:00 CJT	Central Japanese Time (1896/1937)*
+#	8:00 JWST	Western Standard Time (Japan, 1896/1937)*
+#	9:00 JCST	Central Standard Time (Japan, 1896/1937)
 #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
 #	9:00 JST  JDT	Japan
 #	9:00 KST  KDT	Korea
-#	9:30 CST	(Australian) Central Standard Time
+#	9:30 ACST	Australian Central Standard Time
 #
-# See the `europe' file for Russia and Turkey in Asia.
+# See the 'europe' file for Russia and Turkey in Asia.
 
 # From Guy Harris:
 # Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
@@ -86,7 +91,7 @@
 
 ###############################################################################
 
-# These rules are stolen from the `europe' file.
+# These rules are stolen from the 'europe' file.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	EUAsia	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EUAsia	1979	1995	-	Sep	lastSun	 1:00u	0	-
@@ -138,11 +143,11 @@ Zone	Asia/Kabul	4:36:48 -	LMT	1890
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
 			3:00	-	YERT	1957 Mar    # Yerevan Time
-			4:00 RussiaAsia YER%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia YER%sT	1991 Mar 31  2:00s
 			3:00	1:00	YERST	1991 Sep 23 # independence
-			3:00 RussiaAsia	AM%sT	1995 Sep 24 2:00s
+			3:00 RussiaAsia	AM%sT	1995 Sep 24  2:00s
 			4:00	-	AMT	1997
-			4:00 RussiaAsia	AM%sT	2012 Mar 25 2:00s
+			4:00 RussiaAsia	AM%sT	2012 Mar 25  2:00s
 			4:00	-	AMT
 
 # Azerbaijan
@@ -155,16 +160,16 @@ Rule	Azer	1997	max	-	Oct	lastSun	 5:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
 			3:00	-	BAKT	1957 Mar    # Baku Time
-			4:00 RussiaAsia BAK%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
 			3:00	1:00	BAKST	1991 Aug 30 # independence
 			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
-			4:00	-	AZT	1996 # Azerbaijan time
+			4:00	-	AZT	1996     # Azerbaijan Time
 			4:00	EUAsia	AZ%sT	1997
 			4:00	Azer	AZ%sT
 
 # Bahrain
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
+Zone	Asia/Bahrain	3:22:20 -	LMT	1920     # Manamah
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
@@ -174,13 +179,8 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # Daylight Saving Time from June 16 to Sept 30
 #
 # Bangladesh to introduce daylight saving time likely from June 16
-# 
 # http://www.asiantribune.com/?q=node/17288
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
-# 
 #
 # "... Bangladesh government has decided to switch daylight saving time from
 # June
@@ -195,17 +195,11 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # the 19th and 20th, and they have not set the end date yet.
 #
 # Some sources:
-# 
 # http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
-# 
-# 
 # http://bdnews24.com/details.php?id=85889&cid=2
-# 
 #
 # Our wrap-up:
-# 
 # http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
-# 
 
 # From A. N. M. Kamrus Saadat (2009-06-15):
 # Finally we've got the official mail regarding DST start time where DST start
@@ -220,13 +214,8 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 #
 # Following report by same newspaper-"The Daily Star Friday":
 # "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
-# 
 # http://www.thedailystar.net/newDesign/news-details.php?nid=107021
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
-# 
 
 # From Steffen Thorsen (2009-10-13):
 # IANS (Indo-Asian News Service) now reports:
@@ -235,22 +224,15 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # "continue for an indefinite period."
 #
 # One of many places where it is published:
-# 
 # http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
-# 
 
 # From Alexander Krivenyshev (2009-12-24):
 # According to Bangladesh newspaper "The Daily Star,"
 # Bangladesh will change its clock back to Standard Time on Dec 31, 2009.
 #
 # Clock goes back 1-hr on Dec 31 night.
-# 
 # http://www.thedailystar.net/newDesign/news-details.php?nid=119228
-# 
-# and
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html
-# 
 #
 # "...The government yesterday decided to put the clock back by one hour
 # on December 31 midnight and the new time will continue until March 31,
@@ -260,17 +242,12 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # From Alexander Krivenyshev (2010-03-22):
 # According to Bangladesh newspaper "The Daily Star,"
 # Cabinet cancels Daylight Saving Time
-# 
 # http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html
-# 
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	S
-Rule	Dhaka	2009	only	-	Dec	31	23:59	0	-
+Rule	Dhaka	2009	only	-	Dec	31	24:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
@@ -301,7 +278,7 @@ Zone	Indian/Chagos	4:49:40	-	LMT	1907
 
 # Brunei
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
+Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar # Bandar Seri Begawan
 			7:30	-	BNT	1933
 			8:00	-	BNT
 
@@ -310,16 +287,16 @@ Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
 # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Rangoon	6:24:40 -	LMT	1880		# or Yangon
-			6:24:40	-	RMT	1920	   # Rangoon Mean Time?
-			6:30	-	BURT	1942 May   # Burma Time
-			9:00	-	JST	1945 May 3
-			6:30	-	MMT		   # Myanmar Time
+Zone	Asia/Rangoon	6:24:40 -	LMT	1880        # or Yangon
+			6:24:40	-	RMT	1920        # Rangoon Mean Time?
+			6:30	-	BURT	1942 May    # Burma Time
+			9:00	-	JST	1945 May  3
+			6:30	-	MMT	# Myanmar Time
 
 # Cambodia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -332,12 +309,12 @@ Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
 # From Bob Devine (1988-01-28):
 # No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
 # China is across 4 physical time zones, before Feb 1, 1986 only the
-# Peking (Bejing) time zone was recognized.  Since that date, China
-# has two of 'em -- Peking's and Urumqi (named after the capital of
+# Peking (Beijing) time zone was recognized.  Since that date, China
+# has two of 'em - Peking's and Ürümqi (named after the capital of
 # the Xinjiang Uyghur Autonomous Region).  I don't know about DST for it.
 #
 # . . .I just deleted the DST table and this editor makes it too
-# painful to suck in another copy..  So, here is what I have for
+# painful to suck in another copy.  So, here is what I have for
 # DST start/end dates for Peking's time zone (info from AP):
 #
 #     1986 May 4 - Sept 14
@@ -347,15 +324,16 @@ Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
 # CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
 # CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
 
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that China (except for Hong Kong and Macau)
-# has had a single time zone since 1980 May 1, observing summer DST
-# from 1986 through 1991; this contradicts Devine's
-# note about Time magazine, though apparently _something_ happened in 1986.
-# Go with Shanks & Pottenger for now.  I made up names for the other
-# pre-1980 time zones.
+# From Paul Eggert (2008-02-11):
+# Jim Mann, "A clumsy embrace for another western custom: China on daylight
+# time - sort of", Los Angeles Times, 1986-05-05 ... [says] that China began
+# observing daylight saving time in 1986.
 
-# From Shanks & Pottenger:
+# From Paul Eggert (2014-06-30):
+# Shanks & Pottenger have China switching to a single time zone in 1980, but
+# this doesn't seem to be correct.  They also write that China observed summer
+# DST from 1986 through 1991, which seems to match the above commentary, so
+# go with them for DST rules as follows:
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Shang	1940	only	-	Jun	 3	0:00	1:00	D
 Rule	Shang	1940	1941	-	Oct	 1	0:00	0	S
@@ -369,7 +347,7 @@ Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
 # historic timezones from some Taiwan websites.  And yes, there are official
 # Chinese names for these locales (before 1949).
 #
-# From Jesper Norgaard Welen (2006-07-14):
+# From Jesper Nørgaard Welen (2006-07-14):
 # I have investigated the timezones around 1970 on the
 # http://www.astro.com/atlas site [with provinces and county
 # boundaries summarized below]....  A few other exceptions were two
@@ -380,65 +358,97 @@ Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
 # (could be true), for the moment I am assuming that those two
 # counties are mistakes in the astro.com data.
 
-# From Paul Eggert (2008-02-11):
-# I just now checked Google News for western news sources that talk
-# about China's single time zone, and couldn't find anything before 1986
-# talking about China being in one time zone.  (That article was: Jim
-# Mann, "A clumsy embrace for another western custom: China on daylight
-# time--sort of", Los Angeles Times, 1986-05-05.  By the way, this
-# article confirms the tz database's data claiming that China began
-# observing daylight saving time in 1986.
-#
-# From Thomas S. Mullaney (2008-02-11):
-# I think you're combining two subjects that need to treated
-# separately: daylight savings (which, you're correct, wasn't
-# implemented until the 1980s) and the unified time zone centered near
-# Beijing (which was implemented in 1949). Briefly, there was also a
-# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
-# ceased, and the second eventually recognized (again, in the 1980s).
-#
-# From Paul Eggert (2008-06-30):
-# There seems to be a good chance China switched to a single time zone in 1949
-# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
-# reliable documentary source saying so yet, so for now we still go with
-# Shanks & Pottenger.
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
+# From Paul Eggert (2014-06-30):
+# Alois Treindl kindly sent me translations of the following two sources:
+#
+# (1)
+# Guo Qingsheng (National Time-Service Center, CAS, Xi'an 710600, China)
+# Beijing Time at the Beginning of the PRC
+# China Historical Materials of Science and Technology
+# (Zhongguo ke ji shi liao, 中国科技史料), Vol. 24, No. 1 (2003)
+# It gives evidence that at the beginning of the PRC, Beijing time was
+# officially apparent solar time!  However, Guo also says that the
+# evidence is dubious, as the relevant institute of astronomy had not
+# been taken over by the PRC yet.  It's plausible that apparent solar
+# time was announced but never implemented, and that people continued
+# to use UT+8.  As the Shanghai radio station (and I presume the
+# observatory) was still under control of French missionaries, it
+# could well have ignored any such mandate.
+#
+# (2)
+# Guo Qing-sheng (Shaanxi Astronomical Observatory, CAS, Xi'an 710600, China)
+# A Study on the Standard Time Changes for the Past 100 Years in China
+# [undated and unknown publication location]
+# It says several things:
+#   * The Qing dynasty used local apparent solar time throughout China.
+#   * The Republic of China instituted Beijing mean solar time effective
+#     the official calendar book of 1914.
+#   * The French Concession in Shanghai set up signal stations in
+#     French docks in the 1890s, controlled by Xujiahui (Zikawei)
+#     Observatory and set to local mean time.
+#   * "From the end of the 19th century" it changed to UT+8.
+#   * Chinese Customs (by then reduced to a tool of foreign powers)
+#     eventually standardized on this time for all ports, and it
+#     became used by railways as well.
+#   * In 1918 the Central Observatory proposed dividing China into
+#     five time zones (see below for details).  This caught on
+#     at first only in coastal areas observing UT+8.
+#   * During WWII all of China was in theory was at UT+7.  In practice
+#     this was ignored in the west, and I presume was ignored in
+#     Japanese-occupied territory.
+#   * Japanese-occupied Manchuria was at UT+9, i.e., Japan time.
+#   * The five-zone plan was resurrected after WWII and officially put into
+#     place (with some modifications) in March 1948.  It's not clear
+#     how well it was observed in areas under Nationalist control.
+#   * The People's Liberation Army used UT+8 during the civil war.
+#
+# An AP article "Shanghai Internat'l Area Little Changed" in the
+# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
+# different - the occupied districts going by Tokyo time, an hour
+# ahead of that prevailing in the rest of Shanghai."  Guess that the
+# Xujiahui Observatory was under French control and stuck with UT+8.
+#
+# In earlier versions of this file, China had many separate Zone entries, but
+# this was based on what were apparently incorrect data in Shanks & Pottenger.
+# This has now been simplified to the two entries Asia/Shanghai and
+# Asia/Urumqi, with the others being links for backward compatibility.
+# Proposed in 1918 and theoretically in effect until 1949 (although in practice
+# mainly observed in coastal areas), the five zones were:
+#
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Asia/Harbin (currently a link to Asia/Shanghai)
 # Heilongjiang (except Mohe county), Jilin
-Zone	Asia/Harbin	8:26:44	-	LMT	1928 # or Haerbin
-			8:30	-	CHAT	1932 Mar # Changbai Time
-			8:00	-	CST	1940
-			9:00	-	CHAT	1966 May
-			8:30	-	CHAT	1980 May
-			8:00	PRC	C%sT
-# Zhongyuan Time ("Central plain Time")
+#
+# Zhongyuan Time ("Central plain Time") UT+8
+# Asia/Shanghai
 # most of China
-# Milne gives 8:05:56.7; round to nearest.
-Zone	Asia/Shanghai	8:05:57	-	LMT	1928
-			8:00	Shang	C%sT	1949
-			8:00	PRC	C%sT
-# Long-shu Time (probably due to Long and Shu being two names of that area)
+# This currently represents most other zones as well,
+# as apparently these regions have been the same since 1970.
+# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
+# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+#
+# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Asia/Chongqing (currently a link to Asia/Shanghai)
 # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
 # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
 # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
 # Yangchun, Yangjiang, Yu'nan, and Yunfu.
-Zone	Asia/Chongqing	7:06:20	-	LMT	1928 # or Chungking
-			7:00	-	LONT	1980 May # Long-shu Time
-			8:00	PRC	C%sT
-# Xin-zang Time ("Xinjiang-Tibet Time")
+#
+# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Asia/Urumqi
+# This currently represents Kunlun Time as well,
+# as apparently the two regions have been the same since 1970.
 # The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
 # the Guangdong counties  Xuwen, Haikang, Suixi, Lianjiang,
 # Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
 # east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
-# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
+# east Xinjiang, including Ürümqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
 # Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
 # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
 # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
-Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
-			6:00	-	URUT	1980 May # Urumqi Time
-			8:00	PRC	C%sT
-# Kunlun Time
+#
+# Kunlun Time UT+5.5
+# Asia/Kashgar (currently a link to Asia/Urumqi)
 # West Tibet, including Pulan, Aheqi, Shufu, Shule;
 # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
 # Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
@@ -455,9 +465,9 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # population of Xinjiang, typically use "Xinjiang time" which is two
 # hours behind Beijing time, or UTC +0600. The government of the Xinjiang
 # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
-# local governments such as the Urumqi city government use both times in
+# local governments such as the Ürümqi city government use both times in
 # publications, referring to what is popularly called Xinjiang time as
-# "Urumqi time." When Uyghurs make an appointment in the Uyghur language
+# "Ürümqi time." When Uyghurs make an appointment in the Uyghur language
 # they almost invariably use Xinjiang time.
 #
 # (Their ethnic Han compatriots would typically have no clue of its
@@ -469,21 +479,6 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # the province not having dual times but four times in use at the same
 # time. Some areas remained on standard Xinjiang time or Beijing time and
 # others moving their clocks ahead.)
-#
-# ...an example of an official website using of Urumqi time.
-#
-# The first few lines of the Google translation of
-# 
-# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39
-# 
-# (retrieved 2009-10-13)
-# > Urumqi fire seven people are missing the alleged losses of at least
-# > 500 million yuan
-# >
-# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20),
-# > Urumqi City Department of International Plaza Luther Qiantang River
-# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men
-# > have worked continuously for 22 hours...
 
 # From Luther Ma (2009-11-19):
 # With the risk of being redundant to previous answers these are the most common
@@ -494,7 +489,7 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # 3. Urumqi...
 # 4. Kashgar...
 # ...
-# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the
+# 5. It seems that Uyghurs in Ürümqi has been using Xinjiang since at least the
 # 1960's. I know of one Han, now over 50, who grew up in the surrounding
 # countryside and used Xinjiang time as a child.
 #
@@ -506,10 +501,55 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # Autonomous Region under the PRC. (Before that Uyghurs, of course, would also
 # not be using Beijing time, but some local time.)
 
-Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
-			5:30	-	KAST	1940	 # Kashgar Time
-			5:00	-	KAST	1980 May
+# From David Cochrane (2014-03-26):
+# Just a confirmation that Ürümqi time was implemented in Ürümqi on 1 Feb 1986:
+# http://content.time.com/time/magazine/article/0,9171,960684,00.html
+
+# From Luther Ma (2014-04-22):
+# I have interviewed numerous people of various nationalities and from
+# different localities in Xinjiang and can confirm the information in Guo's
+# report regarding Xinjiang, as well as the Time article reference by David
+# Cochrane.  Whether officially recognized or not (and both are officially
+# recognized), two separate times have been in use in Xinjiang since at least
+# the Cultural Revolution: Xinjiang Time (XJT), aka Ürümqi Time or local time;
+# and Beijing Time.  There is no confusion in Xinjiang as to which name refers
+# to which time. Both are widely used in the province, although in some
+# population groups might be use one to the exclusion of the other.  The only
+# problem is that computers and smart phones list Ürümqi (or Kashgar) as
+# having the same time as Beijing.
+
+# From Paul Eggert (2014-06-30):
+# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
+# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
+# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
+# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
+#
+# Xinjiang Time is well-documented as being officially recognized.  E.g., see
+# "The Working-Calendar for The Xinjiang Uygur Autonomous Region Government"
+#  (2014-04-22).
+# Unfortunately, we have no good records of time in Xinjiang before 1986.
+# During the 20th century parts of Xinjiang were ruled by the Qing dynasty,
+# the Republic of China, various warlords, the First and Second East Turkestan
+# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
+# China, and tracking down all these organizations' timekeeping rules would be
+# quite a trick.  Approximate this lost history by a transition from LMT to
+# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# which happens to be the date given by Shanks & Pottenger (no doubt as a
+# guess) as the transition from LMT.  Ignore the usage of UT+8 before
+# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# that the sort of users who prefer Asia/Urumqi now typically ignored the
+# UT+8 mandate back then.
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Beijing time, used throughout China; represented by Shanghai.
+Zone	Asia/Shanghai	8:05:43	-	LMT	1901
+			8:00	Shang	C%sT	1949
 			8:00	PRC	C%sT
+# Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi
+# / Wulumuqi.  (Please use Asia/Shanghai if you prefer Beijing time.)
+Zone	Asia/Urumqi	5:50:20	-	LMT	1928
+			6:00	-	XJT
 
 
 # Hong Kong (Xianggang)
@@ -524,15 +564,11 @@ Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
 # and incorrect rules. Although the exact switch over time is missing, I
 # think 3:30 is correct. The official DST record for Hong Kong can be
 # obtained from
-# 
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# .
 
 # From Arthur David Olson (2009-10-28):
 # Here are the dates given at
-# 
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# 
 # as of 2009-10-28:
 # Year        Period
 # 1941        1 Apr to 30 Sep
@@ -612,35 +648,113 @@ Zone	Asia/Hong_Kong	7:36:42 -	LMT	1904 Oct 30
 
 # Taiwan
 
-# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
-# was still controlled by Japan.  This is hard to believe, but we don't
-# have any other information.
-
 # From smallufo (2010-04-03):
-# According to Taiwan's CWB,
-# 
+# According to Taiwan's CWB [Central Weather Bureau],
 # http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm
-# 
 # Taipei has DST in 1979 between July 1st and Sep 30.
 
-# From Arthur David Olson (2010-04-07):
-# Here's Google's translation of the table at the bottom of the "summert.htm" page:
-# Decade 	                                                    Name                      Start and end date
-# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time               May 1 to September 30
-# 41 years of the Republic of China (AD 1952)                 Daylight Saving Time      March 1 to October 31
-# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time      April 1 to October 31
-# In the 44 years to 45 years (AD 1955-1956 years)            Daylight Saving Time      April 1 to September 30
-# Republic of China 46 years to 48 years (AD 1957-1959)       Summer Time               April 1 to September 30
-# Republic of China 49 years to 50 years (AD 1960-1961)       Summer Time               June 1 to September 30
-# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
-# Republic of China 63 years to 64 years (1974-1975 AD)       Daylight Saving Time      April 1 to September 30
-# Republic of China 65 years to 67 years (1976-1978 AD)       Stop Daylight Saving Time
-# Republic of China 68 years (AD 1979)                        Daylight Saving Time      July 1 to September 30
-# Republic of China since 69 years (AD 1980)                  Stop Daylight Saving Time
+# From Yu-Cheng Chuang (2013-07-12):
+# On Dec 28, 1895, the Meiji Emperor announced Ordinance No. 167 of
+# Meiji Year 28 "The clause about standard time", mentioned that
+# Taiwan and Penghu Islands, as well as Yaeyama and Miyako Islands
+# (both in Okinawa) adopt the Western Standard Time which is based on
+# 120E. The adoption began from Jan 1, 1896. The original text can be
+# found on Wikisource:
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+# ... This could be the first adoption of time zone in Taiwan, because
+# during the Qing Dynasty, it seems that there was no time zone
+# declared officially.
+#
+# Later, in the beginning of World War II, on Sep 25, 1937, the Showa
+# Emperor announced Ordinance No. 529 of Showa Year 12 "The clause of
+# revision in the ordinance No. 167 of Meiji year 28 about standard
+# time", in which abolished the adoption of Western Standard Time in
+# western islands (listed above), which means the whole Japan
+# territory, including later occupations, adopt Japan Central Time
+# (UTC+9). The adoption began on Oct 1, 1937. The original text can
+# be found on Wikisource:
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
+#
+# That is, the time zone of Taipei switched to UTC+9 on Oct 1, 1937.
+
+# From Yu-Cheng Chuang (2014-07-02):
+# I've found more evidence about when the time zone was switched from UTC+9
+# back to UTC+8 after WW2.  I believe it was on Sep 21, 1945.  In a document
+# during Japanese era [1] in which the officer told the staff to change time
+# zone back to Western Standard Time (UTC+8) on Sep 21.  And in another
+# history page of National Cheng Kung University [2], on Sep 21 there is a
+# note "from today, switch back to Western Standard Time".  From these two
+# materials, I believe that the time zone change happened on Sep 21.  And
+# today I have found another monthly journal called "The Astronomical Herald"
+# from The Astronomical Society of Japan [3] in which it mentioned the fact
+# that:
+#
+# 1. Standard Time of the Country (Japan) was adopted on Jan 1, 1888, using
+# the time at 135E (GMT+9)
+#
+# 2. Standard Time of the Country was renamed to Central Standard Time, on Jan
+# 1, 1898, and on the same day, the new territories Taiwan and Penghu islands,
+# as well as Yaeyama and Miyako islands, adopted a new time zone called
+# Western Standard Time, which is in GMT+8.
+#
+# 3. Western Standard Time was deprecated on Sep 30, 1937. From then all the
+# territories of Japan adopted the same time zone, which is Central Standard
+# Time.
+#
+# [1] Academica Historica, Taiwan:
+# http://163.29.208.22:8080/govsaleShowImage/connect_img.php?s=00101738900090036&e=00101738900090037
+# [2] Nat'l Cheng Kung University 70th Anniversary Special Site:
+# http://www.ncku.edu.tw/~ncku70/menu/001/01_01.htm
+# [3] Yukio Niimi, The Standard Time in Japan (1997), p.475:
+# http://www.asj.or.jp/geppou/archive_open/1997/pdf/19971001c.pdf
+
+# Yu-Cheng Chuang (2014-07-03):
+# I finally have found the real official gazette about changing back to
+# Western Standard Time on Sep 21 in Taiwan.  It's Taiwan Governor-General
+# Bulletin No. 386 in Showa 20 years (1945), published on Sep 19, 1945. [1] ...
+# [It] abolishes Bulletin No. 207 in Showa 12 years (1937), which is a local
+# bulletin in Taiwan for that Ordinance No. 529. It also mentioned that 1am on
+# Sep 21, 1945 will be 12am on Sep 21.  I think this bulletin is much more
+# official than the one I mentioned in my first mail, because it's from the
+# top-level government in Taiwan. If you're going to quote any resource, this
+# would be a good one.
+# [1] Taiwan Governor-General Gazette, No. 1018, Sep 19, 1945:
+# http://db2.th.gov.tw/db2/view/viewImg.php?imgcode=0072031018a&num=19&bgn=019&end=019&otherImg=&type=gener
+
+# From Yu-Cheng Chuang (2014-07-02):
+# In 1946, DST in Taiwan was from May 15 and ended on Sep 30. The info from
+# Central Weather Bureau website was not correct.
+#
+# Original Bulletin:
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=03502F0AKM1AF
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0350300AKM1B0 (cont.)
+#
+# In 1947, DST in Taiwan was expanded to Oct 31. There is a backup of that
+# telegram announcement from Taiwan Province Government:
+#
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0360310AKZ431
+#
+# Here is a brief translation:
+#
+#   The Summer Time this year is adopted from midnight Apr 15 until Sep 20
+#   midnight. To save (energy?) consumption, we're expanding Summer Time
+#   adoption till Oct 31 midnight.
+#
+# The Central Weather Bureau website didn't mention that, however it can
+# be found from historical government announcement database.
+
+# From Paul Eggert (2014-07-03):
+# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
+# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Taiwan	1945	1951	-	May	1	0:00	1:00	D
-Rule	Taiwan	1945	1951	-	Oct	1	0:00	0	S
+Rule	Taiwan	1946	only	-	May	15	0:00	1:00	D
+Rule	Taiwan	1946	only	-	Oct	1	0:00	0	S
+Rule	Taiwan	1947	only	-	Apr	15	0:00	1:00	D
+Rule	Taiwan	1947	only	-	Nov	1	0:00	0	S
+Rule	Taiwan	1948	1951	-	May	1	0:00	1:00	D
+Rule	Taiwan	1948	1951	-	Oct	1	0:00	0	S
 Rule	Taiwan	1952	only	-	Mar	1	0:00	1:00	D
 Rule	Taiwan	1952	1954	-	Nov	1	0:00	0	S
 Rule	Taiwan	1953	1959	-	Apr	1	0:00	1:00	D
@@ -648,11 +762,14 @@ Rule	Taiwan	1955	1961	-	Oct	1	0:00	0	S
 Rule	Taiwan	1960	1961	-	Jun	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Apr	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Oct	1	0:00	0	S
-Rule	Taiwan	1979	only	-	Jun	30	0:00	1:00	D
-Rule	Taiwan	1979	only	-	Sep	30	0:00	0	S
+Rule	Taiwan	1979	only	-	Jul	1	0:00	1:00	D
+Rule	Taiwan	1979	only	-	Oct	1	0:00	0	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Taipei	8:06:00 -	LMT	1896 # or Taibei or T'ai-pei
+# Taipei or Taibei or T'ai-pei
+Zone	Asia/Taipei	8:06:00 -	LMT	1896 Jan  1
+			8:00	-	JWST	1937 Oct  1
+			9:00	-	JST	1945 Sep 21  1:00
 			8:00	Taiwan	C%sT
 
 # Macau (Macao, Aomen)
@@ -672,7 +789,7 @@ Rule	Macau	1975	1977	-	Apr	Sun>=15	3:30	1:00	S
 Rule	Macau	1978	1980	-	Apr	Sun>=15	0:00	1:00	S
 Rule	Macau	1978	1980	-	Oct	Sun>=15	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Macau	7:34:20 -	LMT	1912
+Zone	Asia/Macau	7:34:20 -	LMT	1912 Jan  1
 			8:00	Macau	MO%sT	1999 Dec 20 # return to China
 			8:00	PRC	C%sT
 
@@ -721,7 +838,7 @@ Link	Asia/Nicosia	Europe/Nicosia
 # republic has changed its time zone back to that of Moscow.  As a result it
 # is now just four hours ahead of Greenwich Mean Time, rather than five hours
 # ahead.  The switch was decreed by the pro-Western president of Georgia,
-# Mikhail Saakashvili, who said the change was partly prompted by the process
+# Mikheil Saakashvili, who said the change was partly prompted by the process
 # of integration into Europe.
 
 # From Teimuraz Abashidze (2005-11-07):
@@ -734,29 +851,31 @@ Link	Asia/Nicosia	Europe/Nicosia
 # I don't know what can be done, especially knowing that some years ago our
 # DST rules where changed THREE TIMES during one month.
 
+# Milne 1899 says Tbilisi (Tiflis) time was 2:59:05.7.
+# Byalokoz 1919 says Georgia was 2:59:11.
+# Go with Byalokoz.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
-			2:59:16	-	TBMT	1924 May  2 # Tbilisi Mean Time
+Zone	Asia/Tbilisi	2:59:11 -	LMT	1880
+			2:59:11	-	TBMT	1924 May  2 # Tbilisi Mean Time
 			3:00	-	TBIT	1957 Mar    # Tbilisi Time
-			4:00 RussiaAsia TBI%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia TBI%sT	1991 Mar 31  2:00s
 			3:00	1:00	TBIST	1991 Apr  9 # independence
-			3:00 RussiaAsia GE%sT	1992 # Georgia Time
+			3:00 RussiaAsia GE%sT	1992        # Georgia Time
 			3:00 E-EurAsia	GE%sT	1994 Sep lastSun
 			4:00 E-EurAsia	GE%sT	1996 Oct lastSun
 			4:00	1:00	GEST	1997 Mar lastSun
 			4:00 E-EurAsia	GE%sT	2004 Jun 27
-			3:00 RussiaAsia	GE%sT	2005 Mar lastSun 2:00
+			3:00 RussiaAsia	GE%sT	2005 Mar lastSun  2:00
 			4:00	-	GET
 
 # East Timor
 
 # See Indonesia for the 1945 transition.
 
-# From Joao Carrascalao, brother of the former governor of East Timor, in
-# 
+# From João Carrascalão, brother of the former governor of East Timor, in
 # East Timor may be late for its millennium
-#  (1999-12-26/31):
+#  (1999-12-26/31):
 # Portugal tried to change the time forward in 1974 because the sun
 # rises too early but the suggestion raised a lot of problems with the
 # Timorese and I still don't think it would work today because it
@@ -766,25 +885,25 @@ Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
 # We don't have any record of the above attempt.
 # Most likely our records are incomplete, but we have no better data.
 
-# 
 # From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
-# (2000-08-16):
+# http://www.hri.org/news/world/undh/2000/00-08-16.undh.html
+# (2000-08-16):
 # The Cabinet of the East Timor Transition Administration decided
 # today to advance East Timor's time by one hour.  The time change,
 # which will be permanent, with no seasonal adjustment, will happen at
 # midnight on Saturday, September 16.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Dili	8:22:20 -	LMT	1912
+Zone	Asia/Dili	8:22:20 -	LMT	1912 Jan  1
 			8:00	-	TLT	1942 Feb 21 23:00 # E Timor Time
 			9:00	-	JST	1945 Sep 23
 			9:00	-	TLT	1976 May  3
-			8:00	-	WITA	2000 Sep 17 00:00
+			8:00	-	WITA	2000 Sep 17  0:00
 			9:00	-	TLT
 
 # India
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
+Zone	Asia/Kolkata	5:53:28 -	LMT	1880        # Kolkata
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
 			6:30	-	BURT	1942 May 15 # Burma Time
 			5:30	-	IST	1942 Sep
@@ -798,7 +917,7 @@ Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
 # Indonesia
 #
 # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
-# 
+# http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime
 # says that Indonesia's time zones changed on 1988-01-01.  Looking at some
 # time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
 # and Kalimantan Tengah) switching from UTC+8 to UTC+7.
@@ -810,7 +929,7 @@ Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
 # other formal surrender ceremonies were September 9, 11, and 13, plus
 # September 12 for the regional surrender to Mountbatten in Singapore.
 # These would be the earliest possible times for a change.
-# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
+# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
 # Traditionnelles, 1987, Paris) says that Java and Madura switched
 # from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
 # (Hollandia).  For now, assume all Indonesian locations other than Jayapura
@@ -835,7 +954,7 @@ Zone Asia/Jakarta	7:07:12 -	LMT	1867 Aug 10
 # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
 # but this must be a typo.
 			7:07:12	-	BMT	1923 Dec 31 23:47:12 # Batavia
-			7:20	-	JAVT	1932 Nov	 # Java Time
+			7:20	-	JAVT	1932 Nov    # Java Time
 			7:30	-	WIB	1942 Mar 23
 			9:00	-	JST	1945 Sep 23
 			7:30	-	WIB	1948 May
@@ -861,7 +980,7 @@ Zone Asia/Makassar	7:57:36 -	LMT	1920
 # Maluku Islands, West Papua, Papua
 Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
 			9:00	-	WIT	1944 Sep  1
-			9:30	-	CST	1964
+			9:30	-	ACST	1964
 			9:00	-	WIT
 
 # Iran
@@ -927,7 +1046,7 @@ Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
 # Several of my users have reported that Iran will not observe DST anymore:
 # http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
 #
-# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
+# From Reuters (2007-09-16), with a heads-up from Jesper Nørgaard Welen:
 # ... the Guardian Council ... approved a law on Sunday to re-introduce
 # daylight saving time ...
 # http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
@@ -993,7 +1112,7 @@ Rule	Iran	2036	2037	-	Mar	21	0:00	1:00	D
 Rule	Iran	2036	2037	-	Sep	21	0:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tehran	3:25:44	-	LMT	1916
-			3:25:44	-	TMT	1946	# Tehran Mean Time
+			3:25:44	-	TMT	1946     # Tehran Mean Time
 			3:30	-	IRST	1977 Nov
 			4:00	Iran	IR%sT	1979
 			3:30	Iran	IR%sT
@@ -1018,17 +1137,11 @@ Zone	Asia/Tehran	3:25:44	-	LMT	1916
 # From Steffen Thorsen (2008-03-10):
 # The cabinet in Iraq abolished DST last week, according to the following
 # news sources (in Arabic):
-# 
 # http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
-# 
-# 
 # http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
-# 
 #
 # We have published a short article in English about the change:
-# 
 # http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
-# 
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Iraq	1982	only	-	May	1	0:00	1:00	D
@@ -1037,14 +1150,14 @@ Rule	Iraq	1983	only	-	Mar	31	0:00	1:00	D
 Rule	Iraq	1984	1985	-	Apr	1	0:00	1:00	D
 Rule	Iraq	1985	1990	-	Sep	lastSun	1:00s	0	S
 Rule	Iraq	1986	1990	-	Mar	lastSun	1:00s	1:00	D
-# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
+# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the ':01' is a typo.
 # Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
 #
 Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	D
 Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baghdad	2:57:40	-	LMT	1890
-			2:57:36	-	BMT	1918	    # Baghdad Mean Time?
+			2:57:36	-	BMT	1918     # Baghdad Mean Time?
 			3:00	-	AST	1982 May
 			3:00	Iraq	A%sT
 
@@ -1272,7 +1385,7 @@ Rule	Zion	2013	max	-	Oct	lastSun	2:00	0	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
-			2:20:40	-	JMT	1918	# Jerusalem Mean Time?
+			2:20:40	-	JMT	1918 # Jerusalem Mean Time?
 			2:00	Zion	I%sT
 
 
@@ -1281,15 +1394,15 @@ Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
 
 # Japan
 
-# `9:00' and `JST' is from Guy Harris.
+# '9:00' and 'JST' is from Guy Harris.
 
 # From Paul Eggert (1995-03-06):
 # Today's _Asahi Evening News_ (page 4) reports that Japan had
-# daylight saving between 1948 and 1951, but ``the system was discontinued
-# because the public believed it would lead to longer working hours.''
+# daylight saving between 1948 and 1951, but "the system was discontinued
+# because the public believed it would lead to longer working hours."
 
-# From Mayumi Negishi in the 2005-08-10 Japan Times
-# :
+# From Mayumi Negishi in the 2005-08-10 Japan Times:
+# http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm
 # Occupation authorities imposed daylight-saving time on Japan on
 # [1948-05-01]....  But lack of prior debate and the execution of
 # daylight-saving time just three days after the bill was passed generated
@@ -1313,7 +1426,8 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
 
 # From Hideyuki Suzuki (1998-11-09):
 # 'Tokyo' usually stands for the former location of Tokyo Astronomical
-# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
+# Observatory: 139 degrees 44' 40.90" E (9h 18m 58.727s),
+# 35 degrees 39' 16.0" N.
 # This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
 # edited by National Astronomical Observatory of Japan....
 # JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
@@ -1321,10 +1435,10 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
 
 # From Hideyuki Suzuki (1998-11-16):
 # The ordinance No. 51 (1886) established "standard time" in Japan,
-# which stands for the time on E 135 degree.
+# which stands for the time on 135 degrees E.
 # In the ordinance No. 167 (1895), "standard time" was renamed to "central
 # standard time".  And the same ordinance also established "western standard
-# time", which stands for the time on E 120 degree....  But "western standard
+# time", which stands for the time on 120 degrees E....  But "western standard
 # time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
 # 167, there is no mention regarding for what place western standard time is
 # standard....
@@ -1332,27 +1446,33 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
 # I wrote "ordinance" above, but I don't know how to translate.
 # In Japanese it's "chokurei", which means ordinance from emperor.
 
-# Shanks & Pottenger claim JST in use since 1896, and that a few
-# places (e.g. Ishigaki) use +0800; go with Suzuki.  Guess that all
-# ordinances took effect on Jan 1.
+# From Yu-Cheng Chuang (2013-07-12):
+# ...the Meiji Emperor announced Ordinance No. 167 of Meiji Year 28 "The clause
+# about standard time" ... The adoption began from Jan 1, 1896.
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+#
+# ...the Showa Emperor announced Ordinance No. 529 of Showa Year 12 ... which
+# means the whole Japan territory, including later occupations, adopt Japan
+# Central Time (UTC+9). The adoption began on Oct 1, 1937.
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
-			9:00	-	JST	1896
-			9:00	-	CJT	1938
+			9:00	-	JST	1896 Jan  1
+			9:00	-	JCST	1937 Oct  1
 			9:00	Japan	J%sT
 # Since 1938, all Japanese possessions have been like Asia/Tokyo.
 
 # Jordan
 #
-# From 
-# Jordan Week (1999-07-01)  via Steffen Thorsen (1999-09-09):
+# From 
+# Jordan Week (1999-07-01) via Steffen Thorsen (1999-09-09):
 # Clocks in Jordan were forwarded one hour on Wednesday at midnight,
 # in accordance with the government's decision to implement summer time
 # all year round.
 #
-# From 
-# Jordan Week (1999-09-30)  via Steffen Thorsen (1999-11-09):
+# From 
+# Jordan Week (1999-09-30) via Steffen Thorsen (1999-11-09):
 # Winter time starts today Thursday, 30 September. Clocks will be turned back
 # by one hour.  This is the latest government decision and it's final!
 # The decision was taken because of the increase in working hours in
@@ -1372,9 +1492,7 @@ Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
 
 # From Steffen Thorsen (2009-04-02):
 # This single one might be good enough, (2009-03-24, Arabic):
-# 
 # http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279
-# 
 #
 # Google's translation:
 #
@@ -1465,9 +1583,8 @@ Zone	Asia/Amman	2:23:44 -	LMT	1931
 # - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
 # - Oral switched from +5:00 to +4:00 in spring 1989.
 
-# 
-# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
-# 
+# From Kazakhstan Embassy's News Bulletin #11
+#  (2005-03-21):
 # The Government of Kazakhstan passed a resolution March 15 abolishing
 # daylight saving time citing lack of economic benefits and health
 # complications coupled with a decrease in productivity.
@@ -1500,10 +1617,10 @@ Zone	Asia/Qyzylorda	4:21:52 -	LMT	1924 May  2
 			6:00	-	KIZT	1982 Apr  1
 			5:00 RussiaAsia	KIZ%sT	1991
 			5:00	-	KIZT	1991 Dec 16 # independence
-			5:00	-	QYZT	1992 Jan 19 2:00
+			5:00	-	QYZT	1992 Jan 19  2:00
 			6:00 RussiaAsia	QYZ%sT	2005 Mar 15
 			6:00	-	QYZT
-# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
+# Aqtobe (aka Aktobe, formerly Aktyubinsk)
 Zone	Asia/Aqtobe	3:48:40	-	LMT	1924 May  2
 			4:00	-	AKTT	1930 Jun 21 # Aktyubinsk Time
 			5:00	-	AKTT	1981 Apr  1
@@ -1523,7 +1640,7 @@ Zone	Asia/Aqtau	3:21:04	-	LMT	1924 May  2
 			6:00	-	SHET	1982 Apr  1
 			5:00 RussiaAsia	SHE%sT	1991
 			5:00	-	SHET	1991 Dec 16 # independence
-			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun 2:00 # Aqtau Time
+			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun  2:00 # Aqtau Time
 			4:00 RussiaAsia	AQT%sT	2005 Mar 15
 			5:00	-	AQTT
 # West Kazakhstan
@@ -1532,7 +1649,7 @@ Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
 			5:00	-	URAT	1981 Apr  1
 			5:00	1:00	URAST	1981 Oct  1
 			6:00	-	URAT	1982 Apr  1
-			5:00 RussiaAsia	URA%sT	1989 Mar 26 2:00
+			5:00 RussiaAsia	URA%sT	1989 Mar 26  2:00
 			4:00 RussiaAsia	URA%sT	1991
 			4:00	-	URAT	1991 Dec 16 # independence
 			4:00 RussiaAsia	ORA%sT	2005 Mar 15 # Oral Time
@@ -1543,7 +1660,7 @@ Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
 
 # From Paul Eggert (2005-08-15):
 # According to an article dated today in the Kyrgyzstan Development Gateway
-# 
+# http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml
 # Kyrgyzstan is canceling the daylight saving time system.  I take the article
 # to mean that they will leave their clocks at 6 hours ahead of UTC.
 # From Malik Abdugaliev (2005-09-21):
@@ -1558,17 +1675,17 @@ Rule	Kyrgyz	1997	2004	-	Oct	lastSun	2:30	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
 			5:00	-	FRUT	1930 Jun 21 # Frunze Time
-			6:00 RussiaAsia FRU%sT	1991 Mar 31 2:00s
-			5:00	1:00	FRUST	1991 Aug 31 2:00 # independence
-			5:00	Kyrgyz	KG%sT	2005 Aug 12    # Kyrgyzstan Time
+			6:00 RussiaAsia FRU%sT	1991 Mar 31  2:00s
+			5:00	1:00	FRUST	1991 Aug 31  2:00 # independence
+			5:00	Kyrgyz	KG%sT	2005 Aug 12 # Kyrgyzstan Time
 			6:00	-	KGT
 
 ###############################################################################
 
 # Korea (North and South)
 
-# From Annie I. Bang (2006-07-10) in
-# :
+# From Annie I. Bang (2006-07-10):
+# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
 # The Ministry of Commerce, Industry and Energy has already
 # commissioned a research project [to reintroduce DST] and has said
 # the system may begin as early as 2008....  Korea ran a daylight
@@ -1581,19 +1698,29 @@ Rule	ROK	1960	only	-	Sep	13	0:00	0	S
 Rule	ROK	1987	1988	-	May	Sun>=8	0:00	1:00	D
 Rule	ROK	1987	1988	-	Oct	Sun>=8	0:00	0	S
 
+# From Paul Eggert (2014-07-01):
+# The following entries are from Shanks & Pottenger, except that I
+# guessed that time zone abbreviations through 1945 followed the same
+# rules as discussed under Taiwan, with nominal switches from JST to KST
+# when the respective cities were taken over by the Allies after WWII.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Seoul	8:27:52	-	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Sep  8
 			9:00	-	KST	1954 Mar 21
 			8:00	ROK	K%sT	1961 Aug 10
 			8:30	-	KST	1968 Oct
 			9:00	ROK	K%sT
 Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Aug 24
 			9:00	-	KST	1954 Mar 21
 			8:00	-	KST	1961 Aug 10
 			9:00	-	KST
@@ -1602,21 +1729,13 @@ Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
 
 # Kuwait
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# From the Arab Times (2007-03-14):
-# The Civil Service Commission (CSC) has approved a proposal forwarded
-# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
-# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
-# .
-# From Paul Eggert (2007-03-29):
-# We don't know the details, or whether the approval means it'll happen,
-# so for now we assume no DST.
 Zone	Asia/Kuwait	3:11:56 -	LMT	1950
 			3:00	-	AST
 
 # Laos
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9 # or Viangchan
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9       # or Viangchan
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -1657,8 +1776,8 @@ Rule	NBorneo	1935	1941	-	Sep	14	0:00	0:20	TS # one-Third Summer
 Rule	NBorneo	1935	1941	-	Dec	14	0:00	0	-
 #
 # peninsular Malaysia
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# .
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -1670,12 +1789,12 @@ Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			7:30	-	MALT	1982 Jan  1
 			8:00	-	MYT	# Malaysia Time
 # Sabah & Sarawak
-# From Paul Eggert (2006-03-22):
-# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
-# transition dates are from Mok Ly Yng.
+# From Paul Eggert (2014-08-12):
+# The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
+# and 1982 transition dates are from Mok Ly Yng.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
-			7:30	-	BORT	1933	# Borneo Time
+			7:30	-	BORT	1933        # Borneo Time
 			8:00	NBorneo	BOR%sT	1942 Feb 16
 			9:00	-	JST	1945 Sep 12
 			8:00	-	BORT	1982 Jan  1
@@ -1683,22 +1802,21 @@ Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
 
 # Maldives
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
-			4:54:00	-	MMT	1960	# Male Mean Time
-			5:00	-	MVT		# Maldives Time
+Zone	Indian/Maldives	4:54:00 -	LMT	1880 # Male
+			4:54:00	-	MMT	1960 # Male Mean Time
+			5:00	-	MVT	# Maldives Time
 
 # Mongolia
 
 # Shanks & Pottenger say that Mongolia has three time zones, but
-# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
-# both say that it has just one.
+# The USNO (1995-12-21) and the CIA map Standard Time Zones of the World
+# (2005-03) both say that it has just one.
 
 # From Oscar van Vlijmen (1999-12-11):
-# 
 # General Information Mongolia
-#  (1999-09)
+#  (1999-09)
 # "Time: Mongolia has two time zones. Three westernmost provinces of
-# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
+# Bayan-Ölgii, Uvs, and Hovd are one hour earlier than the capital city, and
 # the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
 # eight hours."
 
@@ -1709,7 +1827,7 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # of implementation may have been different....
 # Some maps in the past have indicated that there was an additional time
 # zone in the eastern part of Mongolia, including the provinces of Dornod,
-# Suhbaatar, and possibly Khentij.
+# Sükhbaatar, and possibly Khentii.
 
 # From Paul Eggert (1999-12-15):
 # Naming and spelling is tricky in Mongolia.
@@ -1723,10 +1841,10 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
 # there are three time zones.
 #
-# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
-# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
-#	Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
-# Provinces [at 9:00]: Dornod, Sukhbaatar
+# Provinces [at 7:00]: Bayan-Ölgii, Uvs, Khovd, Zavkhan, Govi-Altai
+# Provinces [at 8:00]: Khövsgöl, Bulgan, Arkhangai, Khentii, Töv,
+#	Bayankhongor, Övörkhangai, Dundgovi, Dornogovi, Ömnögovi
+# Provinces [at 9:00]: Dornod, Sükhbaatar
 #
 # [The province of Selenge is omitted from the above lists.]
 
@@ -1743,16 +1861,16 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # We have wildly conflicting information about Mongolia's time zones.
 # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
 # there is only one time zone and that DST is observed, citing Microsoft
-# Windows XP as the source.  Risto Nykanen (2005-05-16) reports that
+# Windows XP as the source.  Risto Nykänen (2005-05-16) reports that
 # travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
 # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
 # Washington, DC says there are two time zones, with DST observed.
 # He also found
-# 
+# http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&
 # which also says that there is DST, and which has a comment by "Toddius"
 # (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
 # The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
-# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
+# and some Eastern provinces are +9 GMT but Sükhbaatar Aimag is SUHK +8.5 GMT.
 # The SUKH timezone is new this year, it is one of the few things the
 # parliament passed during the tumultuous winter session."
 # For now, let's ignore this information, until we have more confirmation.
@@ -1768,29 +1886,23 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # +08:00 instead. Different sources appear to disagree with the tz
 # database on this, e.g.:
 #
-# 
 # http://www.timeanddate.com/worldclock/city.html?n=1026
-# 
-# 
 # http://www.worldtimeserver.com/current_time_in_MN.aspx
-# 
 #
 # both say GMT+08:00.
 
 # From Steffen Thorsen (2008-03-31):
 # eznis airways, which operates several domestic flights, has a flight
 # schedule here:
-# 
 # http://www.eznis.com/Container.jsp?id=112
-# 
 # (click the English flag for English)
 #
-# There it appears that flights between Choibalsan and Ulaanbatar arrive
+# There it appears that flights between Choibalsan and Ulaanbaatar arrive
 # about 1:35 - 1:50 hours later in local clock time, no matter the
-# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
-# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
+# direction, while Ulaanbaatar-Khovd takes 2 hours in the Eastern
+# direction and 3:35 back, which indicates that Ulaanbaatar and Khovd are
 # in different time zones (like we know about), while Choibalsan and
-# Ulaanbatar are in the same time zone (correction needed).
+# Ulaanbaatar are in the same time zone (correction needed).
 
 # From Arthur David Olson (2008-05-19):
 # Assume that Choibalsan is indeed offset by 8:00.
@@ -1806,7 +1918,7 @@ Rule	Mongol	1983	only	-	Oct	1	0:00	0	-
 # (1996-09) says 1996-10-25.  Go with Shanks & Pottenger through 1998.
 #
 # Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
-# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
+# in Choibalsan (more precisely, in Dornod and Sükhbaatar) took place
 # at 02:00 standard time, not at 00:00 local time as in the rest of
 # the country.  That would be odd, and possibly is a result of their
 # correction of 02:00 (in the previous edition) not being done correctly
@@ -1822,13 +1934,13 @@ Rule	Mongol	2002	2006	-	Mar	lastSat	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
 Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
-			6:00	-	HOVT	1978	# Hovd Time
+			6:00	-	HOVT	1978     # Hovd Time
 			7:00	Mongol	HOV%sT
 # Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
 Zone	Asia/Ulaanbaatar 7:07:32 -	LMT	1905 Aug
-			7:00	-	ULAT	1978	# Ulaanbaatar Time
+			7:00	-	ULAT	1978     # Ulaanbaatar Time
 			8:00	Mongol	ULA%sT
-# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
+# Choibalsan, a.k.a. Bajan Tümen, Bajan Tumen, Chojbalsan,
 # Choybalsan, Sanbejse, Tchoibalsan
 Zone	Asia/Choibalsan	7:38:00 -	LMT	1905 Aug
 			7:00	-	ULAT	1978
@@ -1860,7 +1972,7 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # 00:01 was to make it clear which day it was on.
 
 # From Paul Eggert (2002-03-15):
-# Jesper Norgaard found this URL:
+# Jesper Nørgaard found this URL:
 # http://www.pak.gov.pk/public/news/app/app06_dec.htm
 # (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
 # advance the clocks by one hour on the night between the first
@@ -1892,43 +2004,30 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # Here is an article that Pakistan plan to introduce Daylight Saving Time
 # on June 1, 2008 for 3 months.
 #
-# "... The federal cabinet on Wednesday announced a new conservation plan to help
-# reduce load shedding by approving the closure of commercial centres at 9pm and
-# moving clocks forward by one hour for the next three months.
-# ...."
+# "... The federal cabinet on Wednesday announced a new conservation plan to
+# help reduce load shedding by approving the closure of commercial centres at
+# 9pm and moving clocks forward by one hour for the next three months. ...."
 #
-# 
 # http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
-# 
-# OR
-# 
 # http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
-# 
 
 # From Arthur David Olson (2008-05-19):
 # XXX--midnight transitions is a guess; 2008 only is a guess.
 
 # From Alexander Krivenyshev (2008-08-28):
 # Pakistan government has decided to keep the watches one-hour advanced
-# for another 2 months--plan to return to Standard Time on October 31
+# for another 2 months - plan to return to Standard Time on October 31
 # instead of August 31.
 #
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
-# 
-# OR
-# 
 # http://dailymailnews.com/200808/28/news/dmbrn03.html
-# 
 
 # From Alexander Krivenyshev (2009-04-08):
 # Based on previous media reports that "... proposed plan to
 # advance clocks by one hour from May 1 will cause disturbance
 # to the working schedules rather than bringing discipline in
 # official working."
-# 
 # http://www.thenews.com.pk/daily_detail.asp?id=171280
-# 
 #
 # recent news that instead of May 2009 - Pakistan plan to
 # introduce DST from April 15, 2009
@@ -1936,15 +2035,8 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # FYI: Associated Press Of Pakistan
 # April 08, 2009
 # Cabinet okays proposal to advance clocks by one hour from April 15
-# 
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1
-# 
-#
-# or
-#
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html
-# 
 #
 # ....
 # The Federal Cabinet on Wednesday approved the proposal to
@@ -1957,34 +2049,20 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # clocks backward by one hour from October 1. A formal announcement to
 # this effect will be made after the Prime Minister grants approval in
 # this regard."
-# 
 # http://www.thenews.com.pk/updates.asp?id=87168
-# 
 
 # From Alexander Krivenyshev (2009-09-28):
 # According to Associated Press Of Pakistan, it is confirmed that
-# Pakistan clocks across the country would be turned back by an hour from October
-# 1, 2009.
+# Pakistan clocks across the country would be turned back by an hour from
+# October 1, 2009.
 #
 # "Clocks to go back one hour from 1 Oct"
-# 
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
-# 
-
-# From Steffen Thorsen (2009-09-29):
-# Alexander Krivenyshev wrote:
-# > According to Associated Press Of Pakistan, it is confirmed that
-# > Pakistan clocks across the country would be turned back by an hour from October
-# > 1, 2009.
 #
+# From Steffen Thorsen (2009-09-29):
 # Now they seem to have changed their mind, November 1 is the new date:
-# 
 # http://www.thenews.com.pk/top_story_detail.asp?Id=24742
-# 
 # "The country's clocks will be reversed by one hour on November 1.
 # Officials of Federal Ministry for Interior told this to Geo News on
 # Monday."
@@ -1996,11 +2074,9 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 #
 # We have confirmed this year's end date with both with the Ministry of
 # Water and Power and the Pakistan Electric Power Company:
-# 
 # http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
-# 
 
-# From Christoph Goehre (2009-10-01):
+# From Christoph Göhre (2009-10-01):
 # [T]he German Consulate General in Karachi reported me today that Pakistan
 # will go back to standard time on 1st of November.
 
@@ -2016,22 +2092,17 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # Now, it seems that the decision to not observe DST in final:
 #
 # "Govt Withdraws Plan To Advance Clocks"
-# 
 # http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041
-# 
 #
 # "People laud PM's announcement to end DST"
-# 
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2
-# 
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
 Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
 Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
-Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
+Rule Pakistan	2008	2009	-	Nov	1	0:00	0	-
 Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
-Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Karachi	4:28:12 -	LMT	1907
@@ -2105,10 +2176,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # the PA has decided to implement DST in April.
 
 # From Paul Eggert (1999-09-20):
-# Daoud Kuttab writes in
-# 
-# Holiday havoc
-#  (Jerusalem Post, 1999-04-22) that
+# Daoud Kuttab writes in Holiday havoc
+# http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html
+# (Jerusalem Post, 1999-04-22) that
 # the Palestinian National Authority changed to DST on 1999-04-15.
 # I vaguely recall that they switch back in October (sorry, forgot the source).
 # For now, let's assume that the spring switch was at 24:00,
@@ -2121,7 +2191,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # A user from Gaza reported that Gaza made the change early because of
 # the Ramadan.  Next year Ramadan will be even earlier, so I think
 # there is a good chance next year's end date will be around two weeks
-# earlier--the same goes for Jordan.
+# earlier - the same goes for Jordan.
 
 # From Steffen Thorsen (2006-08-17):
 # I was informed by a user in Bethlehem that in Bethlehem it started the
@@ -2140,7 +2210,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # I guess it is likely that next year's date will be moved as well,
 # because of the Ramadan.
 
-# From Jesper Norgaard Welen (2007-09-18):
+# From Jesper Nørgaard Welen (2007-09-18):
 # According to Steffen Thorsen's web site the Gaza Strip and the rest of the
 # Palestinian territories left DST early on 13.th. of September at 2:00.
 
@@ -2157,16 +2227,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
 # the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
 #
-# 
 # http://www.guardian.co.uk/world/feedarticle/7759001
-# 
-# 
 # http://www.abcnews.go.com/International/wireStory?id=5676087
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
-# 
 
 # From Alexander Krivenyshev (2009-03-26):
 # According to the Palestine News Network (arabic.pnn.ps), Palestinian
@@ -2174,24 +2237,17 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # 26 and continue until the night of 27 September 2009.
 #
 # (in Arabic)
-# 
 # http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850
-# 
 #
-# or
 # (English translation)
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
-# 
 
 # From Steffen Thorsen (2009-08-31):
 # Palestine's Council of Ministers announced that they will revert back to
 # winter time on Friday, 2009-09-04.
 #
 # One news source:
-# 
 # http://www.safa.ps/ara/?action=showdetail&seid=4158
-# 
 # (Palestinian press agency, Arabic),
 # Google translate: "Decided that the Palestinian government in Ramallah
 # headed by Salam Fayyad, the start of work in time for the winter of
@@ -2200,9 +2256,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 #
 # We are not sure if Gaza will do the same, last year they had a different
 # end date, we will keep this page updated:
-# 
 # http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
-# 
 
 # From Alexander Krivenyshev (2009-09-02):
 # Seems that Gaza Strip will go back to Winter Time same date as West Bank.
@@ -2212,51 +2266,35 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 #
 # "Winter time unite the West Bank and Gaza"
 # (from Palestinian National Authority):
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
-# 
 
 # From Alexander Krivenyshev (2010-03-19):
 # According to Voice of Palestine DST will last for 191 days, from March
 # 26, 2010 till "the last Sunday before the tenth day of Tishri
 # (October), each year" (October 03, 2010?)
 #
-# 
 # http://palvoice.org/forums/showthread.php?t=245697
-# 
 # (in Arabic)
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_westbank03.html
-# 
 
 # From Steffen Thorsen (2010-03-24):
 # ...Ma'an News Agency reports that Hamas cabinet has decided it will
 # start one day later, at 12:01am. Not sure if they really mean 12:01am or
 # noon though:
 #
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=271178
-# 
 # (Ma'an News Agency)
 # "At 12:01am Friday, clocks in Israel and the West Bank will change to
 # 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
 
 # From Steffen Thorsen (2010-08-11):
 # According to several sources, including
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
-# 
 # the clocks were set back one hour at 2010-08-11 00:00:00 local time in
 # Gaza and the West Bank.
 # Some more background info:
-# 
 # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
-# 
 
 # From Steffen Thorsen (2011-08-26):
 # Gaza and the West Bank did go back to standard time in the beginning of
@@ -2264,13 +2302,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # 00:00 (so two periods of DST in 2011). The pause was because of
 # Ramadan.
 #
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
-# 
 # Additional info:
-# 
 # http://www.timeanddate.com/news/time/palestine-dst-2011.html
-# 
 
 # From Alexander Krivenyshev (2011-08-27):
 # According to the article in The Jerusalem Post:
@@ -2280,14 +2314,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # The Hamas government said on Saturday that it won't observe summertime after
 # the Muslim feast of Id al-Fitr, which begins on Tuesday..."
 # ...
-# 
 # http://www.jpost.com/MiddleEast/Article.aspx?id=235650
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
-# 
-# The rules for Egypt are stolen from the `africa' file.
+# The rules for Egypt are stolen from the 'africa' file.
 
 # From Steffen Thorsen (2011-09-30):
 # West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
@@ -2295,26 +2324,18 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # So West Bank and Gaza now have the same time again.
 #
 # Many sources, including:
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
-# 
 
 # From Steffen Thorsen (2012-03-26):
 # Palestinian news sources tell that both Gaza and West Bank will start DST
 # on Friday (Thursday midnight, 2012-03-29 24:00).
 # Some of many sources in Arabic:
-# 
 # http://www.samanews.com/index.php?act=Show&id=122638
-# 
 #
-# 
 # http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html
-# 
 #
 # Our brief summary:
-# 
 # http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
-# 
 
 # From Steffen Thorsen (2013-03-26):
 # The following news sources tells that Palestine will "start daylight saving
@@ -2374,10 +2395,10 @@ Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
 			2:00 EgyptAsia	EE%sT	1967 Jun  5
 			2:00	Zion	I%sT	1996
 			2:00	Jordan	EE%sT	1999
-			2:00 Palestine	EE%sT	2008 Aug 29 0:00
+			2:00 Palestine	EE%sT	2008 Aug 29  0:00
 			2:00	-	EET	2008 Sep
 			2:00 Palestine	EE%sT	2010
-			2:00	-	EET	2010 Mar 27 0:01
+			2:00	-	EET	2010 Mar 27  0:01
 			2:00 Palestine	EE%sT	2011 Aug  1
 			2:00	-	EET	2012
 			2:00 Palestine	EE%sT
@@ -2393,25 +2414,27 @@ Zone	Asia/Hebron	2:20:23	-	LMT	1900 Oct
 # no information
 
 # Philippines
-# On 1844-08-16, Narciso Claveria, governor-general of the
+# On 1844-08-16, Narciso Clavería, governor-general of the
 # Philippines, issued a proclamation announcing that 1844-12-30 was to
-# be immediately followed by 1845-01-01.  Robert H. van Gent has a
-# transcript of the decree in .
-# The rest of the data are from Shanks & Pottenger.
+# be immediately followed by 1845-01-01; see R.H. van Gent's
+# History of the International Date Line
+# http://www.staff.science.uu.nl/~gent0113/idl/idl_philippines.htm
+# The rest of the data entries are from Shanks & Pottenger.
 
-# From Paul Eggert (2006-04-25):
-# Tomorrow's Manila Standard reports that the Philippines Department of
-# Trade and Industry is considering adopting DST this June when the
-# rainy season begins.  See
-# .
-# For now, we'll ignore this, since it's not definite and we lack details.
-#
-# From Jesper Norgaard Welen (2006-04-26):
+# From Jesper Nørgaard Welen (2006-04-26):
 # ... claims that Philippines had DST last time in 1990:
 # http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
 # [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
 # but no details]
 
+# From Paul Eggert (2014-08-14):
+# The following source says DST may be instituted November-January and again
+# March-June, but this is not definite.  It also says DST was last proclaimed
+# during the Ramos administration (1992-1998); but again, no details.
+# Carcamo D. PNoy urged to declare use of daylight saving time.
+# Philippine Star 2014-08-05
+# http://www.philstar.com/headlines/2014/08/05/1354152/pnoy-urged-declare-use-daylight-saving-time
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Phil	1936	only	-	Nov	1	0:00	1:00	S
 Rule	Phil	1937	only	-	Feb	1	0:00	0	-
@@ -2428,18 +2451,39 @@ Zone	Asia/Manila	-15:56:00 -	LMT	1844 Dec 31
 
 # Qatar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Qatar	3:26:08 -	LMT	1920	# Al Dawhah / Doha
+Zone	Asia/Qatar	3:26:08 -	LMT	1920     # Al Dawhah / Doha
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
 # Saudi Arabia
+#
+# From Paul Eggert (2014-07-15):
+# Time in Saudi Arabia and other countries in the Arabian peninsula was not
+# standardized until relatively recently; we don't know when, and possibly it
+# has never been made official.  Richard P Hunt, in "Islam city yielding to
+# modern times", New York Times (1961-04-09), p 20, wrote that only airlines
+# observed standard time, and that people in Jeddah mostly observed quasi-solar
+# time, doing so by setting their watches at sunrise to 6 o'clock (or to 12
+# o'clock for "Arab" time).
+#
+# The TZ database cannot represent quasi-solar time; airline time is the best
+# we can do.  The 1946 foreign air news digest of the U.S. Civil Aeronautics
+# Board (OCLC 42299995) reported that the "... Arabian Government, inaugurated
+# a weekly Dhahran-Cairo service, via the Saudi Arabian cities of Riyadh and
+# Jidda, on March 14, 1947".  Shanks & Pottenger guessed 1950; go with the
+# earlier date.
+#
+# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
+# time zones; the other zone, at UTC+4, was in the far eastern part of
+# the country.  Ignore this, as it's before our 1970 cutoff.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Riyadh	3:06:52 -	LMT	1950
+Zone	Asia/Riyadh	3:06:52 -	LMT	1947 Mar 14
 			3:00	-	AST
 
 # Singapore
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# .
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -2465,26 +2509,24 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 
 # From Paul Eggert (1996-09-03):
 # "Sri Lanka advances clock by an hour to avoid blackout"
-# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
+# (, 1996-05-24,
 # no longer available as of 1999-08-17)
-# reported ``the country's standard time will be put forward by one hour at
-# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
+# reported "the country's standard time will be put forward by one hour at
+# midnight Friday (1830 GMT) 'in the light of the present power crisis'."
 #
 # From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
-# by Shamindra in
-# 
-# Daily News - Hot News Section (1996-10-26)
-# :
+# by Shamindra in Daily News - Hot News Section
+#  (1996-10-26):
 # With effect from 12.30 a.m. on 26th October 1996
 # Sri Lanka will be six (06) hours ahead of GMT.
 
-# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
+# From Jesper Nørgaard Welen (2006-04-14), quoting Sri Lanka News Online
 #  (2006-04-13):
 # 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
 # at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
 
 # From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
-# 
+# http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML
 # [The Tamil Tigers] never accepted the original 1996 time change and simply
 # kept their clocks set five and a half hours ahead of Greenwich Mean
 # Time (GMT), in line with neighbor India.
@@ -2498,7 +2540,7 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 # twice in 1996 and probably SL Government or its standardization
 # agencies never declared an abbreviation as a national standard.
 #
-# I recollect before the recent change the government annoucemments
+# I recollect before the recent change the government announcements
 # mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
 # Time and no mention was made about the abbreviation.
 #
@@ -2508,7 +2550,7 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 # item....
 #
 # Within Sri Lanka I think LKT is well known among computer users and
-# adminsitrators.  In my opinion SLT may not be a good choice because the
+# administrators.  In my opinion SLT may not be a good choice because the
 # nation's largest telcom / internet operator Sri Lanka Telcom is well
 # known by that abbreviation - simply as SLT (there IP domains are
 # slt.lk and sltnet.lk).
@@ -2523,13 +2565,13 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
-			5:19:32	-	MMT	1906	# Moratuwa Mean Time
+			5:19:32	-	MMT	1906        # Moratuwa Mean Time
 			5:30	-	IST	1942 Jan  5
 			5:30	0:30	IHST	1942 Sep
-			5:30	1:00	IST	1945 Oct 16 2:00
-			5:30	-	IST	1996 May 25 0:00
-			6:30	-	LKT	1996 Oct 26 0:30
-			6:00	-	LKT	2006 Apr 15 0:30
+			5:30	1:00	IST	1945 Oct 16  2:00
+			5:30	-	IST	1996 May 25  0:00
+			6:30	-	LKT	1996 Oct 26  0:30
+			6:00	-	LKT	2006 Apr 15  0:30
 			5:30	-	IST
 
 # Syria
@@ -2580,7 +2622,7 @@ Rule	Syria	2006	only	-	Sep	22	0:00	0	-
 # Today the AP reported "Syria will switch to summertime at midnight Thursday."
 # http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
 Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
-# From Jesper Norgard (2007-10-27):
+# From Jesper Nørgaard (2007-10-27):
 # The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
 # not take place 1st November at 0:00 o'clock but 1st November at 24:00 or
 # rather Midnight between Thursday and Friday. This does make more sense than
@@ -2589,7 +2631,7 @@ Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
 # it is implemented at midnight of the last workday before weekend...
 #
 # From Steffen Thorsen (2007-10-27):
-# Jesper Norgaard Welen wrote:
+# Jesper Nørgaard Welen wrote:
 #
 # > "Winter local time in Syria will be observed at midnight of Thursday 1
 # > November 2007, and the clock will be put back 1 hour."
@@ -2605,8 +2647,7 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 
 # From Stephen Colebourne (2008-03-17):
 # For everyone's info, I saw an IATA time zone change for [Syria] for
-# this month (March 2008) in the last day or so...This is the data IATA
-# are now using:
+# this month (March 2008) in the last day or so....
 # Country     Time Standard   --- DST Start ---   --- DST End ---  DST
 # Name        Zone Variation   Time    Date        Time    Date
 # Variation
@@ -2618,16 +2659,15 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 # From Arthur David Olson (2008-03-17):
 # Here's a link to English-language coverage by the Syrian Arab News
 # Agency (SANA)...
-# 
 # http://www.sana.sy/eng/21/2008/03/11/165173.htm
-# ...which reads (in part) "The Cabinet approved the suggestion of the
+# ...which reads (in part) "The Cabinet approved the suggestion of the
 # Ministry of Electricity to begin daylight savings time on Friday April
 # 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
 # Since Syria is two hours east of UTC, the 2200 and 2100 transition times
 # shown above match up with midnight in Syria.
 
 # From Arthur David Olson (2008-03-18):
-# My buest guess at a Syrian rule is "the Friday nearest April 1";
+# My best guess at a Syrian rule is "the Friday nearest April 1";
 # coding that involves either using a "Mar Fri>=29" construct that old time zone
 # compilers can't handle  or having multiple Rules (a la Israel).
 # For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
@@ -2640,37 +2680,27 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 # winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
 # clocks back 60 minutes).
 #
-# 
 # http://sana.sy/ara/2/2008/10/07/195459.htm
-# 
 
 # From Steffen Thorsen (2009-03-19):
 # Syria will start DST on 2009-03-27 00:00 this year according to many sources,
 # two examples:
 #
-# 
 # http://www.sana.sy/eng/21/2009/03/17/217563.htm
-# 
 # (English, Syrian Arab News # Agency)
-# 
 # http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
-# 
 # (Arabic, gov-site)
 #
 # We have not found any sources saying anything about when DST ends this year.
 #
 # Our summary
-# 
 # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
-# 
 
 # From Steffen Thorsen (2009-10-27):
 # The Syrian Arab News Network on 2009-09-29 reported that Syria will
 # revert back to winter (standard) time on midnight between Thursday
 # 2009-10-29 and Friday 2009-10-30:
-# 
 # http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
-# 
 
 # From Arthur David Olson (2009-10-28):
 # We'll see if future DST switching times turn out to be end of the last
@@ -2681,23 +2711,17 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 # The "Syrian News Station" reported on 2010-03-16 that the Council of
 # Ministers has decided that Syria will start DST on midnight Thursday
 # 2010-04-01: (midnight between Thursday and Friday):
-# 
 # http://sns.sy/sns/?path=news/read/11421 (Arabic)
-# 
 
 # From Steffen Thorsen (2012-03-26):
 # Today, Syria's government announced that they will start DST early on Friday
 # (00:00). This is a bit earlier than the past two years.
 #
 # From Syrian Arab News Agency, in Arabic:
-# 
 # http://www.sana.sy/ara/2/2012/03/26/408215.htm
-# 
 #
 # Our brief summary:
-# 
 # http://www.timeanddate.com/news/time/syria-dst-2012.html
-# 
 
 # From Arthur David Olson (2012-03-27):
 # Assume last Friday in March going forward XXX.
@@ -2710,7 +2734,7 @@ Rule	Syria	2012	max	-	Mar	lastFri	0:00	1:00	S
 Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
+Zone	Asia/Damascus	2:25:12 -	LMT	1920 # Dimashq
 			2:00	Syria	EE%sT
 
 # Tajikistan
@@ -2718,9 +2742,9 @@ Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
 			5:00	-	DUST	1930 Jun 21 # Dushanbe Time
-			6:00 RussiaAsia DUS%sT	1991 Mar 31 2:00s
-			5:00	1:00	DUSST	1991 Sep  9 2:00s
-			5:00	-	TJT		    # Tajikistan Time
+			6:00 RussiaAsia DUS%sT	1991 Mar 31  2:00s
+			5:00	1:00	DUSST	1991 Sep  9  2:00s
+			5:00	-	TJT	# Tajikistan Time
 
 # Thailand
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2733,9 +2757,9 @@ Zone	Asia/Bangkok	6:42:04	-	LMT	1880
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
 			4:00	-	ASHT	1930 Jun 21 # Ashkhabad Time
-			5:00 RussiaAsia	ASH%sT	1991 Mar 31 2:00
+			5:00 RussiaAsia	ASH%sT	1991 Mar 31  2:00
 			4:00 RussiaAsia	ASH%sT	1991 Oct 27 # independence
-			4:00 RussiaAsia	TM%sT	1992 Jan 19 2:00
+			4:00 RussiaAsia	TM%sT	1992 Jan 19  2:00
 			5:00	-	TMT
 
 # United Arab Emirates
@@ -2744,8 +2768,9 @@ Zone	Asia/Dubai	3:41:12 -	LMT	1920
 			4:00	-	GST
 
 # Uzbekistan
+# Byalokoz 1919 says Uzbekistan was 4:27:53.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
+Zone	Asia/Samarkand	4:27:53 -	LMT	1924 May  2
 			4:00	-	SAMT	1930 Jun 21 # Samarkand Time
 			5:00	-	SAMT	1981 Apr  1
 			5:00	1:00	SAMST	1981 Oct  1
@@ -2753,9 +2778,10 @@ Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
 			5:00 RussiaAsia	SAM%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
-Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
+# Milne says Tashkent was 4:37:10.8; round to nearest.
+Zone	Asia/Tashkent	4:37:11 -	LMT	1924 May  2
 			5:00	-	TAST	1930 Jun 21 # Tashkent Time
-			6:00 RussiaAsia	TAS%sT	1991 Mar 31 2:00
+			6:00 RussiaAsia	TAS%sT	1991 Mar 31  2:00
 			5:00 RussiaAsia	TAS%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
@@ -2769,13 +2795,13 @@ Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
 # and Pottenger.
 
 # From Arthur David Olson (2008-03-18):
-# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
-# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
+# The English-language name of Vietnam's most populous city is "Ho Chi Minh
+# City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters.
 
 # From Shanks & Pottenger:
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
diff --git a/make/data/tzdata/australasia b/make/data/tzdata/australasia
index 94c9adb912c599e62ad8c29e7f4422135bec1a05..52d329041786baa5eddfe7273936d2a199c384f3 100644
--- a/make/data/tzdata/australasia
+++ b/make/data/tzdata/australasia
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -36,13 +35,13 @@
 # Please see the notes below for the controversy about "EST" versus "AEST" etc.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	-
-Rule	Aus	1917	only	-	Mar	25	2:00	0	-
-Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	-
-Rule	Aus	1942	only	-	Mar	29	2:00	0	-
-Rule	Aus	1942	only	-	Sep	27	2:00	1:00	-
-Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	-
-Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
+Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	D
+Rule	Aus	1917	only	-	Mar	25	2:00	0	S
+Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	D
+Rule	Aus	1942	only	-	Mar	29	2:00	0	S
+Rule	Aus	1942	only	-	Sep	27	2:00	1:00	D
+Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	S
+Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	D
 # Go with Whitman and the Australian National Standards Commission, which
 # says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
 # 1944/1945 was just like 1943/1944.
@@ -50,26 +49,26 @@ Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Northern Territory
 Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
-			 9:00	-	CST	1899 May
-			 9:30	Aus	CST
+			 9:00	-	ACST	1899 May
+			 9:30	Aus	AC%sT
 # Western Australia
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1991	only	-	Nov	17	2:00s	1:00	-
-Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	-
-Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	-
-Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	-
+Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1991	only	-	Nov	17	2:00s	1:00	D
+Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	D
+Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	S
+Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	D
 Zone Australia/Perth	 7:43:24 -	LMT	1895 Dec
-			 8:00	Aus	WST	1943 Jul
-			 8:00	AW	WST
+			 8:00	Aus	AW%sT	1943 Jul
+			 8:00	AW	AW%sT
 Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
-			 8:45	Aus	CWST	1943 Jul
-			 8:45	AW	CWST
+			 8:45	Aus	ACW%sT	1943 Jul
+			 8:45	AW	ACW%sT
 
 # Queensland
 #
@@ -85,150 +84,150 @@ Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
 # so use Lindeman.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	-
-Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	-
-Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	-
+Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	S
+Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	D
+Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	S
 Zone Australia/Brisbane	10:12:08 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT
 Zone Australia/Lindeman  9:55:56 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST	1992 Jul
-			10:00	Holiday	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT	1992 Jul
+			10:00	Holiday	AE%sT
 
 # South Australia
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1972	only	-	Feb	27	2:00s	0	-
-Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AS	1991	only	-	Mar	3	2:00s	0	-
-Rule	AS	1992	only	-	Mar	22	2:00s	0	-
-Rule	AS	1993	only	-	Mar	7	2:00s	0	-
-Rule	AS	1994	only	-	Mar	20	2:00s	0	-
-Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2006	only	-	Apr	2	2:00s	0	-
-Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1972	only	-	Feb	27	2:00s	0	S
+Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AS	1991	only	-	Mar	3	2:00s	0	S
+Rule	AS	1992	only	-	Mar	22	2:00s	0	S
+Rule	AS	1993	only	-	Mar	7	2:00s	0	S
+Rule	AS	1994	only	-	Mar	20	2:00s	0	S
+Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2006	only	-	Apr	2	2:00s	0	S
+Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AS	CST
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AS	AC%sT
 
 # Tasmania
 #
 # From Paul Eggert (2005-08-16):
-# 
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
 # says King Island didn't observe DST from WWII until late 1971.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	-
-Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
-Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	-
+Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	S
+Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	D
+Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1967
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT
 Zone Australia/Currie	9:35:28	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1971 Jul
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1971 Jul
+			10:00	AT	AE%sT
 
 # Victoria
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AV	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AV	AE%sT
 
 # New South Wales
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1972	only	-	Feb	27	2:00s	0	-
-Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	-
-Rule	AN	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1972	only	-	Feb	27	2:00s	0	S
+Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	S
+Rule	AN	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AN	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AN	AE%sT
 Zone Australia/Broken_Hill 9:25:48 -	LMT	1895 Feb
-			10:00	-	EST	1896 Aug 23
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AN	CST	2000
-			9:30	AS	CST
+			10:00	-	AEST	1896 Aug 23
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AN	AC%sT	2000
+			9:30	AS	AC%sT
 
 # Lord Howe Island
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	-
-Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	-
-Rule	LH	1986	only	-	Oct	19	2:00	0:30	-
-Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	-
-Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	-
-Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2007	only	-	Mar	lastSun	2:00	0	-
-Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	-
+Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	D
+Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	S
+Rule	LH	1986	only	-	Oct	19	2:00	0:30	D
+Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	S
+Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	D
+Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2007	only	-	Mar	lastSun	2:00	0	S
+Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	D
 Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
-			10:00	-	EST	1981 Mar
-			10:30	LH	LHST
+			10:00	-	AEST	1981 Mar
+			10:30	LH	LH%sT
 
 # Australian miscellany
 #
@@ -244,8 +243,8 @@ Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
 # Permanent occupation (scientific station) 1911-1915 and since 25 March 1948;
 # sealing and penguin oil station operated Nov 1899 to Apr 1919.  See the
 # Tasmania Parks & Wildlife Service history of sealing at Macquarie Island
-# 
-# .
+# http://www.parks.tas.gov.au/index.aspx?base=1828
+# http://www.parks.tas.gov.au/index.aspx?base=1831
 # Guess that it was like Australia/Hobart while inhabited before 2010.
 #
 # From Steffen Thorsen (2010-03-10):
@@ -256,16 +255,16 @@ Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
 #
 # From Arthur David Olson (2013-05-23):
 # The 1919 transition is overspecified below so pre-2013 zics
-# will produce a binary file with an EST-type as the first 32-bit type;
+# will produce a binary file with an [A]EST-type as the first 32-bit type;
 # this is required for correct handling of times before 1916 by
 # pre-2013 versions of localtime.
 Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1919 Apr 1 0:00s
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1919 Apr  1  0:00s
 			0	-	zzz	1948 Mar 25
-			10:00	Aus	EST	1967
-			10:00	AT	EST	2010 Apr 4 3:00
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT	2010 Apr  4  3:00
 			11:00	-	MIST	# Macquarie I Standard Time
 
 # Christmas
@@ -273,24 +272,14 @@ Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
 Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
 			7:00	-	CXT	# Christmas Island Time
 
-# Cook Is
-# From Shanks & Pottenger:
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
-Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
-Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901		# Avarua
-			-10:30	-	CKT	1978 Nov 12	# Cook Is Time
-			-10:00	Cook	CK%sT
-
-# Cocos
+# Cocos (Keeling) Is
 # These islands were ruled by the Ross family from about 1830 to 1978.
 # We don't know when standard time was introduced; for now, we guess 1900.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Cocos	6:27:40	-	LMT	1900
 			6:30	-	CCT	# Cocos Islands Time
 
+
 # Fiji
 
 # Milne gives 11:55:44 for Suva.
@@ -300,20 +289,13 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # from November 29th 2009  to April 25th 2010.
 #
 # "Daylight savings to commence this month"
-# 
 # http://www.radiofiji.com.fj/fullstory.php?id=23719
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_fiji01.html
-# 
 
 # From Steffen Thorsen (2009-11-10):
 # The Fiji Government has posted some more details about the approved
 # amendments:
-# 
 # http://www.fiji.gov.fj/publish/page_16198.shtml
-# 
 
 # From Steffen Thorsen (2010-03-03):
 # The Cabinet in Fiji has decided to end DST about a month early, on
@@ -322,35 +304,24 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # 2011 (last Sunday a good guess?).
 #
 # Official source:
-# 
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166
-# 
 #
 # A bit more background info here:
-# 
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
-# 
 
 # From Alexander Krivenyshev (2010-10-24):
 # According to Radio Fiji and Fiji Times online, Fiji will end DST 3
 # weeks earlier than expected - on March 6, 2011, not March 27, 2011...
 # Here is confirmation from Government of the Republic of the Fiji Islands,
 # Ministry of Information (fiji.gov.fj) web site:
-# 
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
-# 
 
 # From Steffen Thorsen (2011-10-03):
 # Now the dates have been confirmed, and at least our start date
 # assumption was correct (end date was one week wrong).
 #
-# 
-# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
-# 
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
 # which says
 # Members of the public are reminded to change their time to one hour in
 # advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
@@ -360,9 +331,7 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # Another change to the Fiji DST end date. In the TZ database the end date for
 # Fiji DST 2012, is currently Feb 26. This has been changed to Jan 22.
 #
-# 
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155
-# 
 # states:
 #
 # The end of daylight saving scheduled initially for the 26th of February 2012
@@ -400,16 +369,16 @@ Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 Rule	Fiji	2012	2013	-	Jan	Sun>=18	3:00	0	-
 Rule	Fiji	2014	max	-	Jan	Sun>=18	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26	# Suva
+Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26 # Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
 
 # French Polynesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct	# Rikitea
+Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct # Rikitea
 			 -9:00	-	GAMT	# Gambier Time
 Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
 			 -9:30	-	MART	# Marquesas Time
-Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
+Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct # Papeete
 			-10:00	-	TAHT	# Tahiti Time
 # Clipperton (near North America) is administered from French Polynesia;
 # it is uninhabited.
@@ -417,14 +386,14 @@ Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
 # Guam
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
-			 9:39:00 -	LMT	1901		# Agana
-			10:00	-	GST	2000 Dec 23	# Guam
+			 9:39:00 -	LMT	1901        # Agana
+			10:00	-	GST	2000 Dec 23 # Guam
 			10:00	-	ChST	# Chamorro Standard Time
 
 # Kiribati
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Tarawa	 11:32:04 -	LMT	1901		# Bairiki
-			 12:00	-	GILT		 # Gilbert Is Time
+Zone Pacific/Tarawa	 11:32:04 -	LMT	1901 # Bairiki
+			 12:00	-	GILT	# Gilbert Is Time
 Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
 			-12:00	-	PHOT	1979 Oct # Phoenix Is Time
 			-11:00	-	PHOT	1995
@@ -438,7 +407,7 @@ Zone Pacific/Kiritimati	-10:29:20 -	LMT	1901
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
 			 9:43:00 -	LMT	1901
-			 9:00	-	MPT	1969 Oct # N Mariana Is Time
+			 9:00	-	MPT	1969 Oct    # N Mariana Is Time
 			10:00	-	MPT	2000 Dec 23
 			10:00	-	ChST	# Chamorro Standard Time
 
@@ -449,24 +418,24 @@ Zone Pacific/Majuro	11:24:48 -	LMT	1901
 			12:00	-	MHT
 Zone Pacific/Kwajalein	11:09:20 -	LMT	1901
 			11:00	-	MHT	1969 Oct
-			-12:00	-	KWAT	1993 Aug 20	# Kwajalein Time
+			-12:00	-	KWAT	1993 Aug 20 # Kwajalein Time
 			12:00	-	MHT
 
 # Micronesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Chuuk	10:07:08 -	LMT	1901
-			10:00	-	CHUT			# Chuuk Time
-Zone Pacific/Pohnpei	10:32:52 -	LMT	1901		# Kolonia
-			11:00	-	PONT			# Pohnpei Time
+			10:00	-	CHUT	# Chuuk Time
+Zone Pacific/Pohnpei	10:32:52 -	LMT	1901 # Kolonia
+			11:00	-	PONT	# Pohnpei Time
 Zone Pacific/Kosrae	10:51:56 -	LMT	1901
-			11:00	-	KOST	1969 Oct	# Kosrae Time
+			11:00	-	KOST	1969 Oct # Kosrae Time
 			12:00	-	KOST	1999
 			11:00	-	KOST
 
 # Nauru
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15	# Uaobe
-			11:30	-	NRT	1942 Mar 15	# Nauru Time
+Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15 # Uaobe
+			11:30	-	NRT	1942 Mar 15 # Nauru Time
 			9:00	-	JST	1944 Aug 15
 			11:30	-	NRT	1979 May
 			12:00	-	NRT
@@ -479,7 +448,7 @@ Rule	NC	1996	only	-	Dec	 1	2:00s	1:00	S
 # Shanks & Pottenger say the following was at 2:00; go with IATA.
 Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13
+Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13 # Nouméa
 			11:00	NC	NC%sT
 
 
@@ -496,7 +465,8 @@ Rule	NZ	1934	1940	-	Apr	lastSun	2:00	0	M
 Rule	NZ	1934	1940	-	Sep	lastSun	2:00	0:30	S
 Rule	NZ	1946	only	-	Jan	 1	0:00	0	S
 # Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
-# convenient notation for this so we must duplicate the Rule lines.
+# convenient single notation for the date and time of this transition
+# so we must duplicate the Rule lines.
 Rule	NZ	1974	only	-	Nov	Sun>=1	2:00s	1:00	D
 Rule	Chatham	1974	only	-	Nov	Sun>=1	2:45s	1:00	D
 Rule	NZ	1975	only	-	Feb	lastSun	2:00s	0	S
@@ -519,13 +489,14 @@ Rule	Chatham	2008	max	-	Apr	Sun>=1	2:45s	0	S
 Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
 			11:30	NZ	NZ%sT	1946 Jan  1
 			12:00	NZ	NZ%sT
-Zone Pacific/Chatham	12:13:48 -	LMT	1957 Jan  1
+Zone Pacific/Chatham	12:13:48 -	LMT	1868 Nov  2
+			12:15	-	CHAST	1946 Jan  1
 			12:45	Chatham	CHA%sT
 
 Link Pacific/Auckland Antarctica/McMurdo
 
 # Auckland Is
-# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
+# uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers,
 # and scientific personnel have wintered
 
 # Campbell I
@@ -534,48 +505,58 @@ Link Pacific/Auckland Antarctica/McMurdo
 # previously whalers, sealers, pastoralists, and scientific personnel wintered
 # was probably like Pacific/Auckland
 
+# Cook Is
+# From Shanks & Pottenger:
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
+Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
+Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901        # Avarua
+			-10:30	-	CKT	1978 Nov 12 # Cook Is Time
+			-10:00	Cook	CK%sT
+
 ###############################################################################
 
 
 # Niue
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Niue	-11:19:40 -	LMT	1901		# Alofi
-			-11:20	-	NUT	1951	# Niue Time
-			-11:30	-	NUT	1978 Oct 1
+Zone	Pacific/Niue	-11:19:40 -	LMT	1901        # Alofi
+			-11:20	-	NUT	1951        # Niue Time
+			-11:30	-	NUT	1978 Oct  1
 			-11:00	-	NUT
 
 # Norfolk
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Norfolk	11:11:52 -	LMT	1901		# Kingston
-			11:12	-	NMT	1951	# Norfolk Mean Time
-			11:30	-	NFT		# Norfolk Time
+Zone	Pacific/Norfolk	11:11:52 -	LMT	1901 # Kingston
+			11:12	-	NMT	1951 # Norfolk Mean Time
+			11:30	-	NFT	# Norfolk Time
 
 # Palau (Belau)
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Palau	8:57:56 -	LMT	1901		# Koror
+Zone Pacific/Palau	8:57:56 -	LMT	1901 # Koror
 			9:00	-	PWT	# Palau Time
 
 # Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
-			9:48:32	-	PMMT	1895	# Port Moresby Mean Time
-			10:00	-	PGT		# Papua New Guinea Time
+			9:48:32	-	PMMT	1895 # Port Moresby Mean Time
+			10:00	-	PGT	# Papua New Guinea Time
 
 # Pitcairn
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901		# Adamstown
-			-8:30	-	PNT	1998 Apr 27 00:00
+Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901        # Adamstown
+			-8:30	-	PNT	1998 Apr 27  0:00
 			-8:00	-	PST	# Pitcairn Standard Time
 
 # American Samoa
 Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 			-11:22:48 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
-# Samoa
+# Samoa (formerly and also known as Western Samoa)
 
 # From Steffen Thorsen (2009-10-16):
 # We have been in contact with the government of Samoa again, and received
@@ -586,141 +567,80 @@ Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 # Sunday of April 2011."
 #
 # Background info:
-# 
 # http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
-# 
 #
 # Samoa's Daylight Saving Time Act 2009 is available here, but does not
 # contain any dates:
-# 
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
-# 
 
 # From Laupue Raymond Hughes (2010-10-07):
 # Please see
-# 
 # http://www.mcil.gov.ws
-# ,
 # the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
 # September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
 # to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
 # backwards from 1:00am to 12:00am"
 
 # From Laupue Raymond Hughes (2011-03-07):
-# I believe this will be posted shortly on the website
-# 
-# www.mcil.gov.ws
-# 
-#
-# PUBLIC NOTICE ON DAYLIGHT SAVING TIME
+# [http://www.mcil.gov.ws/ftcd/daylight_saving_2011.pdf]
 #
-# Pursuant to the Daylight Saving Act 2009 and Cabinets decision,
-# businesses and the general public are hereby advised that daylight
-# saving time is on the first Saturday of April 2011 (02/04/11).
-#
-# The public is therefore advised that when the standard time strikes
-# the hour of four oclock (4.00am or 0400 Hours) on the 2nd April 2011,
-# then all instruments used to measure standard time are to be
-# adjusted/changed to three oclock (3:00am or 0300Hrs).
-#
-# Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE,
-# INDUSTRY AND LABOUR 28th February 2011
+# ... when the standard time strikes the hour of four o'clock (4.00am
+# or 0400 Hours) on the 2nd April 2011, then all instruments used to
+# measure standard time are to be adjusted/changed to three o'clock
+# (3:00am or 0300Hrs).
 
-# From David Zuelke (2011-05-09):
+# From David Zülke (2011-05-09):
 # Subject: Samoa to move timezone from east to west of international date line
 #
-# 
 # http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
-# 
 
-# From Mark Sim-Smith (2011-08-17):
-# I have been in contact with Leilani Tuala Warren from the Samoa Law
-# Reform Commission, and she has sent me a copy of the Bill that she
-# confirmed has been passed...Most of the sections are about maps rather
-# than the time zone change, but I'll paste the relevant bits below. But
-# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa
-# changes from UTC-11 to UTC+13:
-#
-# International Date Line Bill 2011
-#
-# AN ACT to provide for the change to standard time in Samoa and to make
-# consequential amendments to the position of the International Date
-# Line, and for related purposes.
-#
-# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament
-# assembled as follows:
-#
-# 1. Short title and commencement-(1) This Act may be cited as the
-# International Date Line Act 2011. (2) Except for section 5(3) this Act
-# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3)
-# Section 5(3) commences on the date of assent by the Head of State.
-#
-# [snip]
-#
-# 3. Interpretation - [snip] "Samoa standard time" in this Act and any
-# other statute of Samoa which refers to 'Samoa standard time' means the
-# time 13 hours in advance of Co-ordinated Universal Time.
-#
-# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa
-# standard time shall be set at 13 hours in advance of Co-ordinated
-# Universal Time for the whole of Samoa. (2) All references to Samoa's
-# time zone and to Samoa standard time in Samoa in all legislation and
-# instruments after the commencement of this Act shall be references to
-# Samoa standard time as provided for in this Act. (3) Nothing in this
-# Act affects the provisions of the Daylight Saving Act 2009, except that
-# it defines Samoa standard time....
+# From Paul Eggert (2014-06-27):
+# The International Date Line Act 2011
+# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
+# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# Thursday 29th December 2011".  The International Date Line was adjusted
+# accordingly.
 
 # From Laupue Raymond Hughes (2011-09-02):
-# 
 # http://www.mcil.gov.ws/mcil_publications.html
-# 
 #
 # here is the official website publication for Samoa DST and dateline change
 #
 # DST
-# Year	End	Time	Start	Time
-# 2011	- - -	- - -	24 September	3:00am to 4:00am
-# 2012	01 April	4:00am to 3:00am	- - -	- - -
+# Year  End      Time              Start        Time
+# 2011  - - -    - - -             24 September 3:00am to 4:00am
+# 2012  01 April 4:00am to 3:00am  - - -        - - -
 #
 # Dateline Change skip Friday 30th Dec 2011
 # Thursday 29th December 2011	23:59:59 Hours
 # Saturday 31st December 2011	00:00:00 Hours
 #
-# Clarification by Tim Parenti (2012-01-03):
-# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
-# seasons, there is not yet any indication that this trend will continue on
-# a regular basis. For now, we have explicitly listed the transitions below.
-#
-# From Nicky (2012-09-10):
+# From Nicholas Pereira (2012-09-10):
 # Daylight Saving Time commences on Sunday 30th September 2012 and
-# ends on Sunday 7th of April 2013.
-#
-# Please find link below for more information.
+# ends on Sunday 7th of April 2013....
 # http://www.mcil.gov.ws/mcil_publications.html
 #
-# That publication also includes dates for Summer of 2013/4 as well
-# which give the impression of a pattern in selecting dates for the
-# future, so for now, we will guess this will continue.
+# From Paul Eggert (2014-07-08):
+# That web page currently lists transitions for 2012/3 and 2013/4.
+# Assume the pattern instituted in 2012 will continue indefinitely.
 
-# Western Samoa
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	WS	2010	only	-	Sep	lastSun	0:00	1	D
+Rule	WS	2011	only	-	Apr	Sat>=1	4:00	0	S
+Rule	WS	2011	only	-	Sep	lastSat	3:00	1	D
+Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	S
 Rule	WS	2012	max	-	Sep	lastSun	3:00	1	D
-Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 2 4:00
-			-11:00	-	WST	2011 Sep 24 3:00
-			-11:00	1:00	WSDT	2011 Dec 30
-			 13:00	1:00	WSDT	2012 Apr Sun>=1 4:00
+			-11:30	-	WSST	1950
+			-11:00	WS	S%sT	2011 Dec 29 24:00 # S=Samoa
 			 13:00	WS	WS%sT
 
 # Solomon Is
 # excludes Bougainville, for which see Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
+Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct # Honiara
 			11:00	-	SBT	# Solomon Is Time
 
 # Tokelau Is
@@ -744,7 +664,7 @@ Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
-			-11:00	-	TKT 2011 Dec 30	# Tokelau Time
+			-11:00	-	TKT	2011 Dec 30 # Tokelau Time
 			13:00	-	TKT
 
 # Tonga
@@ -804,8 +724,8 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 # time from Operation Newsreel (Hardtack I/Teak shot, 1958-08-01) to the last
 # Operation Fishbowl shot (Tightrope, 1962-11-04).... [See] Herman Hoerlin,
 # "The United States High-Altitude Test Experience: A Review Emphasizing the
-# Impact on the Environment", Los Alamos LA-6405, Oct 1976
-# .
+# Impact on the Environment", Los Alamos LA-6405, Oct 1976.
+# http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf
 # See the table on page 4 where he lists GMT and local times for the tests; a
 # footnote for the JI tests reads that local time is "JI time = Hawaii Time
 # Minus One Hour".
@@ -820,7 +740,7 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 # From Mark Brader (2005-01-23):
 # [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
 # published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
-# reproduced a Pan American Airways timeables from 1936, for their weekly
+# reproduced a Pan American Airways timetable from 1936, for their weekly
 # "Orient Express" flights between San Francisco and Manila, and connecting
 # flights to Chicago and the US East Coast.  As it uses some time zone
 # designations that I've never seen before:....
@@ -830,9 +750,9 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 Zone Pacific/Midway	-11:49:28 -	LMT	1901
 			-11:00	-	NST	1956 Jun  3
 			-11:00	1:00	NDT	1956 Sep  2
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
 # Palmyra
 # uninhabited since World War II; was probably like Pacific/Kiritimati
@@ -852,7 +772,7 @@ Rule	Vanuatu	1985	1991	-	Sep	Sun>=23	0:00	1:00	S
 Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
 Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13		# Vila
+Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13 # Vila
 			11:00	Vanuatu	VU%sT	# Vanuatu Time
 
 # Wallis and Futuna
@@ -864,9 +784,10 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # NOTES
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 # A good source for time zone historical data outside the U.S. is
@@ -887,165 +808,188 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
-#		std dst
-#		LMT	Local Mean Time
-#	  8:00	WST WST	Western Australia
-#	  8:45	CWST CWST Central Western Australia*
-#	  9:00	JST	Japan
-#	  9:30	CST CST	Central Australia
-#	 10:00	EST EST	Eastern Australia
-#	 10:00	ChST	Chamorro
-#	 10:30	LHST LHST Lord Howe*
-#	 11:30	NZMT NZST New Zealand through 1945
-#	 12:00	NZST NZDT New Zealand 1946-present
-#	 12:45	CHAST CHADT Chatham*
-#	-11:00	SST	Samoa
-#	-10:00	HST	Hawaii
-#	- 8:00	PST	Pitcairn*
-#
-# See the `northamerica' file for Hawaii.
-# See the `southamerica' file for Easter I and the Galapagos Is.
+#		std	dst
+#		LMT		Local Mean Time
+#	  8:00	AWST	AWDT	Western Australia
+#	  8:45	ACWST	ACWDT	Central Western Australia*
+#	  9:00	JST		Japan
+#	  9:30	ACST	ACDT	Central Australia
+#	 10:00	AEST	AEDT	Eastern Australia
+#	 10:00	ChST		Chamorro
+#	 10:30	LHST	LHDT	Lord Howe*
+#	 11:30	NZMT	NZST	New Zealand through 1945
+#	 12:00	NZST	NZDT	New Zealand 1946-present
+#	 12:15	CHAST		Chatham through 1945*
+#	 12:45	CHAST	CHADT	Chatham 1946-present*
+#	 13:00	WSST	WSDT	(western) Samoa 2011-present*
+#	-11:30	WSST		Western Samoa through 1950*
+#	-11:00	SST		Samoa
+#	-10:00	HST		Hawaii
+#	- 8:00	PST		Pitcairn*
+#
+# See the 'northamerica' file for Hawaii.
+# See the 'southamerica' file for Easter I and the Galápagos Is.
 
 ###############################################################################
 
 # Australia
 
+# From Paul Eggert (2014-06-30):
+# Daylight saving time has long been controversial in Australia, pitting
+# region against region, rural against urban, and local against global.
+# For example, in her review of Graeme Davison's _The Unforgiving
+# Minute: how Australians learned to tell the time_ (1993), Perth native
+# Phillipa J Martyr wrote, "The section entitled 'Saving Daylight' was
+# very informative, but was (as can, sadly, only be expected from a
+# Melbourne-based study) replete with the usual chuckleheaded
+# Queenslanders and straw-chewing yokels from the West prattling fables
+# about fading curtains and crazed farm animals."
+# Electronic Journal of Australian and New Zealand History (1997-03-03)
+# http://www.jcu.edu.au/aff/history/reviews/davison.htm
+
 # From Paul Eggert (2005-12-08):
-# 
 # Implementation Dates of Daylight Saving Time within Australia
-#  summarizes daylight saving issues in Australia.
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
+# summarizes daylight saving issues in Australia.
 
 # From Arthur David Olson (2005-12-12):
-# 
 # Lawlink NSW:Daylight Saving in New South Wales
-#  covers New South Wales in particular.
+# http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving
+# covers New South Wales in particular.
 
 # From John Mackin (1991-03-06):
-# We in Australia have _never_ referred to DST as `daylight' time.
-# It is called `summer' time.  Now by a happy coincidence, `summer'
-# and `standard' happen to start with the same letter; hence, the
+# We in Australia have _never_ referred to DST as 'daylight' time.
+# It is called 'summer' time.  Now by a happy coincidence, 'summer'
+# and 'standard' happen to start with the same letter; hence, the
 # abbreviation does _not_ change...
 # The legislation does not actually define abbreviations, at least
 # in this State, but the abbreviation is just commonly taken to be the
 # initials of the phrase, and the legislation here uniformly uses
-# the phrase `summer time' and does not use the phrase `daylight
+# the phrase 'summer time' and does not use the phrase 'daylight
 # time'.
 # Announcers on the Commonwealth radio network, the ABC (for Australian
-# Broadcasting Commission), use the phrases `Eastern Standard Time'
-# or `Eastern Summer Time'.  (Note, though, that as I say in the
+# Broadcasting Commission), use the phrases 'Eastern Standard Time'
+# or 'Eastern Summer Time'.  (Note, though, that as I say in the
 # current australasia file, there is really no such thing.)  Announcers
 # on its overseas service, Radio Australia, use the same phrases
-# prefixed by the word `Australian' when referring to local times;
+# prefixed by the word 'Australian' when referring to local times;
 # time announcements on that service, naturally enough, are made in UTC.
 
-# From Arthur David Olson (1992-03-08):
-# Given the above, what's chosen for year-round use is:
-#	CST	for any place operating at a GMTOFF of 9:30
-#	WST	for any place operating at a GMTOFF of 8:00
-#	EST	for any place operating at a GMTOFF of 10:00
-
-# From Chuck Soper (2006-06-01):
-# I recently found this Australian government web page on time zones:
-# 
-# And this government web page lists time zone names and abbreviations:
-# 
-
-# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
-# versus "AEST" etc.:
-#
-# I see the following points of dispute:
-#
-# * How important are unique time zone abbreviations?
-#
-#   Here I tend to agree with the point (most recently made by Chris
-#   Newman) that unique abbreviations should not be essential for proper
-#   operation of software.  We have other instances of ambiguity
-#   (e.g. "IST" denoting both "Israel Standard Time" and "Indian
-#   Standard Time"), and they are not likely to go away any time soon.
-#   In the old days, some software mistakenly relied on unique
-#   abbreviations, but this is becoming less true with time, and I don't
-#   think it's that important to cater to such software these days.
-#
-#   On the other hand, there is another motivation for unambiguous
-#   abbreviations: it cuts down on human confusion.  This is
-#   particularly true for Australia, where "EST" can mean one thing for
-#   time T and a different thing for time T plus 1 second.
-#
-# * Does the relevant legislation indicate which abbreviations should be used?
-#
-#   Here I tend to think that things are a mess, just as they are in
-#   many other countries.  We Americans are currently disagreeing about
-#   which abbreviation to use for the newly legislated Chamorro Standard
-#   Time, for example.
-#
-#   Personally, I would prefer to use common practice; I would like to
-#   refer to legislation only for examples of common practice, or as a
-#   tiebreaker.
-#
-# * Do Australians more often use "Eastern Daylight Time" or "Eastern
-#   Summer Time"?  Do they typically prefix the time zone names with
-#   the word "Australian"?
-#
-#   My own impression is that both "Daylight Time" and "Summer Time" are
-#   common and are widely understood, but that "Summer Time" is more
-#   popular; and that the leading "A" is also common but is omitted more
-#   often than not.  I just used AltaVista advanced search and got the
-#   following count of page hits:
-#
-#     1,103 "Eastern Summer Time" AND domain:au
-#       971 "Australian Eastern Summer Time" AND domain:au
-#       613 "Eastern Daylight Time" AND domain:au
-#       127 "Australian Eastern Daylight Time" AND domain:au
-#
-#   Here "Summer" seems quite a bit more popular than "Daylight",
-#   particularly when we know the time zone is Australian and not US,
-#   say.  The "Australian" prefix seems to be popular for Eastern Summer
-#   Time, but unpopular for Eastern Daylight Time.
-#
-#   For abbreviations, tools like AltaVista are less useful because of
-#   ambiguity.  Many hits are not really time zones, unfortunately, and
-#   many hits denote US time zones and not Australian ones.  But here
-#   are the hit counts anyway:
-#
-#     161,304 "EST" and domain:au
-#      25,156 "EDT" and domain:au
-#      18,263 "AEST" and domain:au
-#      10,416 "AEDT" and domain:au
-#
-#      14,538 "CST" and domain:au
-#       5,728 "CDT" and domain:au
-#         176 "ACST" and domain:au
-#          29 "ACDT" and domain:au
-#
-#       7,539 "WST" and domain:au
-#          68 "AWST" and domain:au
-#
-#   This data suggest that Australians tend to omit the "A" prefix in
-#   practice.  The situation for "ST" versus "DT" is less clear, given
-#   the ambiguities involved.
-#
-# * How do Australians feel about the abbreviations in the tz database?
-#
-#   If you just count Australians on this list, I count 2 in favor and 3
-#   against.  One of the "against" votes (David Keegel) counseled delay,
-#   saying that both AEST/AEDT and EST/EST are widely used and
-#   understood in Australia.
+# From Paul Eggert (2014-06-30):
+#
+# Inspired by Mackin's remarks quoted above, earlier versions of this
+# file used "EST" for both Eastern Standard Time and Eastern Summer
+# Time in Australia, and similarly for "CST", "CWST", and "WST".
+# However, these abbreviations were confusing and were not common
+# practice among Australians, and there were justifiable complaints
+# about them, so I attempted to survey current Australian usage.
+# For the tz database, the full English phrase is not that important;
+# what matters is the abbreviation.  It's difficult to survey the web
+# directly for abbreviation usage, as there are so many false hits for
+# strings like "EST" and "EDT", so I looked for pages that defined an
+# abbreviation for eastern or central DST in Australia, and got the
+# following numbers of unique hits for the listed Google queries:
+#
+#   10 "Eastern Daylight Time AEST" site:au [some are false hits]
+#   10 "Eastern Summer Time AEST" site:au
+#   10 "Summer Time AEDT" site:au
+#   13 "EDST Eastern Daylight Saving Time" site:au
+#   18 "Summer Time ESST" site:au
+#   28 "Eastern Daylight Saving Time EDST" site:au
+#   39 "EDT Eastern Daylight Time" site:au [some are false hits]
+#   53 "Eastern Daylight Time EDT" site:au [some are false hits]
+#   54 "AEDT Australian Eastern Daylight Time" site:au
+#  182 "Eastern Daylight Time AEDT" site:au
+#
+#   17 "Central Daylight Time CDT" site:au [some are false hits]
+#   46 "Central Daylight Time ACDT" site:au
+#
+# I tried several other variants (e.g., "Eastern Summer Time EST") but
+# they all returned fewer than 10 unique hits.  I also looked for pages
+# mentioning both "western standard time" and an abbreviation, since
+# there is no WST in the US to generate false hits, and found:
+#
+#  156 "western standard time" AWST site:au
+#  226 "western standard time" WST site:au
+#
+# I then surveyed the top ten newspapers in Australia by circulation as
+# listed in Wikipedia, using Google queries like "AEDT site:heraldsun.com.au"
+# and obtaining estimated counts from the initial page of search results.
+# All ten papers greatly preferred "AEDT" to "EDT".  The papers
+# surveyed were the Herald Sun, The Daily Telegraph, The Courier-Mail,
+# The Sydney Morning Herald, The West Australian, The Age, The Advertiser,
+# The Australian, The Financial Review, and The Herald (Newcastle).
+#
+# I also searched for historical usage, to see whether abbreviations
+# like "AEDT" are new.  A Trove search 
+# found only one newspaper (The Canberra Times) with a house style
+# dating back to the 1970s, I expect because other newspapers weren't
+# fully indexed.  The Canberra Times strongly preferred abbreviations
+# like "AEDT".  The first occurrence of "AEDT" was a World Weather
+# column (1971-11-17, page 24), and of "ACDT" was a Scoreboard column
+# (1993-01-24, p 16).  The style was the typical usage but was not
+# strictly enforced; for example, "Welcome to the twilight zones ..."
+# (1994-10-29, p 1) uses the abbreviations AEST/AEDT, CST/CDT, and
+# WST, and goes on to say, "The confusion and frustration some feel
+# about the lack of uniformity among Australia's six states and two
+# territories has prompted one group to form its very own political
+# party -- the Sydney-based Daylight Saving Extension Party."
+#
+# I also surveyed federal government sources.  They did not agree:
+#
+#   The Australian Government (2014-03-26)
+#   http://australia.gov.au/about-australia/our-country/time
+#   (This document was produced by the Department of Finance.)
+#   AEST ACST AWST AEDT ACDT
+#
+#   Bureau of Meteorology (2012-11-08)
+#   http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml
+#   EST CST WST EDT CDT
+#
+#   Civil Aviation Safety Authority (undated)
+#   http://services.casa.gov.au/outnback/inc/pages/episode3/episode-3_time_zones.shtml
+#   EST CST WST (no abbreviations given for DST)
+#
+#   Geoscience Australia (2011-11-24)
+#   http://www.ga.gov.au/geodesy/astro/sunrise.jsp
+#   AEST ACST AWST AEDT ACDT
+#
+#   Parliamentary Library (2008-11-10)
+#   http://www.aph.gov.au/binaries/library/pubs/rp/2008-09/09rp14.pdf
+#   EST CST WST preferred for standard time; AEST AEDT ACST ACDT also used
+#
+#   The Transport Safety Bureau has an extensive series of accident reports,
+#   and investigators seem to use whatever abbreviation they like.
+#   Googling site:atsb.gov.au found the following number of unique hits:
+#   311 "ESuT", 195 "EDT", 26 "AEDT", 83 "CSuT", 46 "CDT".
+#   "_SuT" tended to appear in older reports, and "A_DT" tended to
+#   appear in reports of events with international implications.
+#
+# From the above it appears that there is a working consensus in
+# Australia to use trailing "DT" for daylight saving time; although
+# some sources use trailing "SST" or "ST" or "SuT" they are by far in
+# the minority.  The case for leading "A" is weaker, but since it
+# seems to be preferred in the overall web and is preferred in all
+# the leading newspaper websites and in many government departments,
+# it has a stronger case than omitting the leading "A".  The current
+# version of the database therefore uses abbreviations like "AEST" and
+# "AEDT" for Australian time zones.
 
 # From Paul Eggert (1995-12-19):
 # Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
 # Mark Prior writes that his newspaper
 # reports that NSW's fall 1995 change will occur at 2:00,
 # but Robert Elz says it's been 3:00 in Victoria since 1970
-# and perhaps the newspaper's `2:00' is referring to standard time.
+# and perhaps the newspaper's '2:00' is referring to standard time.
 # For now we'll continue to assume 2:00s for changes since 1960.
 
 # From Eric Ulevik (1998-01-05):
@@ -1055,17 +999,14 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # relevant entries in this database.
 #
 # NSW (including LHI and Broken Hill):
-# 
 # Standard Time Act 1987 (updated 1995-04-04)
-# 
+# http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html
 # ACT
-# 
 # Standard Time and Summer Time Act 1972
-# 
+# http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html
 # SA
-# 
 # Standard Time Act, 1898
-# 
+# http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html
 
 # From David Grosz (2005-06-13):
 # It was announced last week that Daylight Saving would be extended by
@@ -1083,7 +1024,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Victoria: I wasn't able to find anything separate, but the other articles
 # allude to it.
 # But not Queensland
-# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
+# http://www.news.com.au/story/0,10117,15564030-1248,00.html
 
 # Northern Territory
 
@@ -1130,9 +1071,9 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # The 1992 ending date used in the rules is a best guess;
 # it matches what was used in the past.
 
-# 
 # The Australian Bureau of Meteorology FAQ
-#  (1999-09-27) writes that Giles Meteorological Station uses
+# http://www.bom.gov.au/faq/faqgen.htm
+# (1999-09-27) writes that Giles Meteorological Station uses
 # South Australian time even though it's located in Western Australia.
 
 # Queensland
@@ -1173,9 +1114,9 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
 
 # From Christopher Hunt (2006-11-21), after an advance warning
-# from Jesper Norgaard Welen (2006-11-01):
+# from Jesper Nørgaard Welen (2006-11-01):
 # WA are trialing DST for three years.
-# 
+# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf
 
 # From Rives McDow (2002-04-09):
 # The most interesting region I have found consists of three towns on the
@@ -1189,7 +1130,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # From Paul Eggert (2002-04-09):
 # This is confirmed by the section entitled
 # "What's the deal with time zones???" in
-# .
+# http://www.earthsci.unimelb.edu.au/~awatkins/null.html
 #
 # From Alex Livingston (2006-12-07):
 # ... it was just on four years ago that I drove along the Eyre Highway,
@@ -1337,7 +1278,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Based on law library research by John Mackin,
 # who notes:
 #	In Australia, time is not legislated federally, but rather by the
-#	individual states.  Thus, while such terms as ``Eastern Standard Time''
+#	individual states.  Thus, while such terms as "Eastern Standard Time"
 #	[I mean, of course, Australian EST, not any other kind] are in common
 #	use, _they have NO REAL MEANING_, as they are not defined in the
 #	legislation.  This is very important to understand.
@@ -1345,48 +1286,42 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # From Eric Ulevik (1999-05-26):
 # DST will start in NSW on the last Sunday of August, rather than the usual
-# October in 2000.  [See: Matthew Moore,
-# 
-# Two months more daylight saving
-# 
-# Sydney Morning Herald (1999-05-26).]
+# October in 2000.  See: Matthew Moore,
+# Two months more daylight saving, Sydney Morning Herald (1999-05-26).
+# http://www.smh.com.au/news/9905/26/pageone/pageone4.html
 
 # From Paul Eggert (1999-09-27):
 # See the following official NSW source:
-# 
 # Daylight Saving in New South Wales.
-# 
+# http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ
 #
 # Narrabri Shire (NSW) council has announced it will ignore the extension of
 # daylight saving next year.  See:
-# 
 # Narrabri Council to ignore daylight saving
-#  (1999-07-22).  For now, we'll wait to see if this really happens.
+# http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm
+# (1999-07-22).  For now, we'll wait to see if this really happens.
 #
 # Victoria will following NSW.  See:
-# 
-# Vic to extend daylight saving
-#  (1999-07-28).
+# Vic to extend daylight saving (1999-07-28)
+# http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm
 #
 # However, South Australia rejected the DST request.  See:
-# 
-# South Australia rejects Olympics daylight savings request
-#  (1999-07-19).
+# South Australia rejects Olympics daylight savings request (1999-07-19)
+# http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm
 #
 # Queensland also will not observe DST for the Olympics.  See:
-# 
 # Qld says no to daylight savings for Olympics
-#  (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
-# ``Look you've got to remember in my family when this came up last time
+# http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm
+# (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
+# "Look you've got to remember in my family when this came up last time
 # I voted for it, my wife voted against it and she said to me it's all very
 # well for you, you don't have to worry about getting the children out of
 # bed, getting them to school, getting them to sleep at night.
-# I've been through all this argument domestically...my wife rules.''
+# I've been through all this argument domestically...my wife rules."
 #
 # Broken Hill will stick with South Australian time in 2000.  See:
-# 
-# Broken Hill to be behind the times
-#  (1999-07-21).
+# Broken Hill to be behind the times (1999-07-21)
+# http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm
 
 # IATA SSIM (1998-09) says that the spring 2000 change for Australian
 # Capital Territory, New South Wales except Lord Howe Island and Broken
@@ -1402,7 +1337,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Yancowinna
 
 # From John Mackin (1989-01-04):
-# `Broken Hill' means the County of Yancowinna.
+# 'Broken Hill' means the County of Yancowinna.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
@@ -1459,9 +1394,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # summer (southern hemisphere).
 #
 # From
-# 
 # http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
-# 
 # The extended daylight saving period that South Australia has been trialling
 # for over the last year is now set to be ongoing.
 # Daylight saving will continue to start on the first Sunday in October each
@@ -1471,9 +1404,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # the ACT for all 52 weeks of the year...
 #
 # We have a wrap-up here:
-# 
 # http://www.timeanddate.com/news/time/south-australia-extends-dst.html
-# 
 ###############################################################################
 
 # New Zealand
@@ -1482,7 +1413,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # the 1989/90 year was a trial of an extended "daylight saving" period.
 # This trial was deemed successful and the extended period adopted for
 # subsequent years (with the addition of a further week at the start).
-# source -- phone call to Ministry of Internal Affairs Head Office.
+# source - phone call to Ministry of Internal Affairs Head Office.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # The Country of New Zealand   (Australia's east island -) Gee they hate that!
@@ -1524,6 +1455,19 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # that DST will begin on 2007-09-30 2008-04-06.
 # http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
 
+# From Paul Eggert (2014-07-14):
+# Chatham Island time was formally standardized on 1957-01-01 by
+# New Zealand's Standard Time Amendment Act 1956 (1956-10-26).
+# http://www.austlii.edu.au/nz/legis/hist_act/staa19561956n100244.pdf
+# According to Google Books snippet view, a speaker in the New Zealand
+# parliamentary debates in 1956 said "Clause 78 makes provision for standard
+# time in the Chatham Islands.  The time there is 45 minutes in advance of New
+# Zealand time.  I understand that is the time they keep locally, anyhow."
+# For now, assume this practice goes back to the introduction of standard time
+# in New Zealand, as this would make Chatham Islands time almost exactly match
+# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# not observe New Zealand's prewar DST.
+
 ###############################################################################
 
 
@@ -1543,7 +1487,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # From the BBC World Service in
 # http://news.bbc.co.uk/2/hi/asia-pacific/205226.stm (1998-10-31 16:03 UTC):
-# The Fijiian government says the main reasons for the time change is to
+# The Fijian government says the main reasons for the time change is to
 # improve productivity and reduce road accidents.... [T]he move is also
 # intended to boost Fiji's ability to attract tourists to witness the dawning
 # of the new millennium.
@@ -1551,16 +1495,12 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
 # reports that Fiji has discontinued DST.
 
-# Johnston
-
-# Johnston data is from usno1995.
-
 
 # Kiribati
 
 # From Paul Eggert (1996-01-22):
 # Today's _Wall Street Journal_ (page 1) reports that Kiribati
-# ``declared it the same day [throughout] the country as of Jan. 1, 1995''
+# "declared it the same day [throughout] the country as of Jan. 1, 1995"
 # as part of the competition to be first into the 21st century.
 
 
@@ -1575,8 +1515,8 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # N Mariana Is, Guam
 
-# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
-# Philippines and the Ladrones from America,'' and implies that the Ladrones
+# Howse writes (p 153) "The Spaniards, on the other hand, reached the
+# Philippines and the Ladrones from America," and implies that the Ladrones
 # (now called the Marianas) kept American date for quite some time.
 # For now, we assume the Ladrones switched at the same time as the Philippines;
 # see Asia/Manila.
@@ -1590,17 +1530,16 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Micronesia
 
 # Alan Eugene Davis writes (1996-03-16),
-# ``I am certain, having lived there for the past decade, that "Truk"
-# (now properly known as Chuuk) ... is in the time zone GMT+10.''
+# "I am certain, having lived there for the past decade, that 'Truk'
+# (now properly known as Chuuk) ... is in the time zone GMT+10."
 #
 # Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
 # on 1978-10-01; ignore this for now.
 
 # From Paul Eggert (1999-10-29):
 # The Federated States of Micronesia Visitors Board writes in
-# 
-# The Federated States of Micronesia - Visitor Information
-#  (1999-01-26)
+# The Federated States of Micronesia - Visitor Information (1999-01-26)
+# http://www.fsmgov.org/info/clocks.html
 # that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
 # We don't know when Kosrae switched from UTC+12; assume January 1 for now.
 
@@ -1646,27 +1585,34 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Sacramento but it was changed a couple of years ago.
 
 
-# Samoa
+# (Western) Samoa and American Samoa
 
 # Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
 # that in 1879 the King of Samoa decided to change
-# ``the date in his kingdom from the Antipodean to the American system,
-# ordaining -- by a masterpiece of diplomatic flattery -- that
-# the Fourth of July should be celebrated twice in that year.''
-
+# "the date in his kingdom from the Antipodean to the American system,
+# ordaining - by a masterpiece of diplomatic flattery - that
+# the Fourth of July should be celebrated twice in that year."
+
+# Although Shanks & Pottenger says they both switched to UTC-11:30
+# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# for American Samoa, e.g., the US National Bureau of Standards
+# circular "Standard Time Throughout the World", 1932.
+# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# and that after 1950 they agreed until (western) Samoa skipped a
+# day in 2011.  Assume also that the Samoas follow the US and New
+# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
 
 # Tonga
 
 # From Paul Eggert (1996-01-22):
-# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
-# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
+# Today's _Wall Street Journal_ (p 1) reports that "Tonga has been plotting
+# to sneak ahead of [New Zealanders] by introducing daylight-saving time."
 # Since Kiribati has moved the Date Line it's not clear what Tonga will do.
 
 # Don Mundell writes in the 1997-02-20 Tonga Chronicle
-# 
-# How Tonga became `The Land where Time Begins'
-# :
-
+# How Tonga became 'The Land where Time Begins':
+# http://www.tongatapu.net.to/tonga/homeland/timebegins.htm
+#
 # Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
 # 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
 # standard time in 1940s, Tonga had the choice of subtracting from its
@@ -1674,8 +1620,8 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # advancing its time to maintain the differential of 13 degrees
 # (approximately 50 minutes ahead of New Zealand time).
 #
-# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
-# Tungi, preferred to ensure Tonga's title as the land where time
+# Because His Majesty King Tāufaʻāhau Tupou IV, then Crown Prince
+# Tungī, preferred to ensure Tonga's title as the land where time
 # begins, the Legislative Assembly approved the latter change.
 #
 # But some of the older, more conservative members from the outer
@@ -1701,9 +1647,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # * Tonga will introduce DST in November
 #
 # I was given this link by John Letts:
-# 
 # http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
-# 
 #
 # I have not been able to find exact dates for the transition in November
 # yet. By reading this article it seems like Fiji will be 14 hours ahead
@@ -1711,9 +1655,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # (12 + 1 hour DST).
 
 # From Arthur David Olson (1999-09-20):
-# According to 
-# http://www.tongaonline.com/news/sept1799.html
-# :
+# According to :
 # "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
 # and annually thereafter from the first Saturday in October through the
 # third Saturday of April.  Under the system approved by Privy Council on
@@ -1731,7 +1673,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # instead of the original reported date April 16. Unfortunately, the article
 # is no longer available on the site, and I did not make a copy of the
 # text, and I have forgotten to report it here.
-# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
+# (Original URL was )
 
 # From Rives McDow (2000-12-01):
 # Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
@@ -1751,7 +1693,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # From Vernice Anderson, Personal Secretary to Philip Jessup,
 # US Ambassador At Large (oral history interview, 1971-02-02):
 #
-# Saturday, the 14th [of October, 1950] -- ...  The time was all the
+# Saturday, the 14th [of October, 1950] - ...  The time was all the
 # more confusing at that point, because we had crossed the
 # International Date Line, thus getting two Sundays.  Furthermore, we
 # discovered that Wake Island had two hours of daylight saving time
@@ -1796,7 +1738,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # on the high seas.  Whenever a ship was within the territorial waters of any
 # nation it would use that nation's standard time.  The captain was permitted
 # to change his ship's clocks at a time of his choice following his ship's
-# entry into another zone time--he often chose midnight.  These zones were
+# entry into another zone time - he often chose midnight.  These zones were
 # adopted by all major fleets between 1920 and 1925 but not by many
 # independent merchant ships until World War II.
 
@@ -1804,6 +1746,6 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # (2005-03-20):
 #
 # The American Practical Navigator (2002)
-# 
+# http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187
 # talks only about the 180-degree meridian with respect to ships in
 # international waters; it ignores the international date line.
diff --git a/make/data/tzdata/backward b/make/data/tzdata/backward
index 5afe9a317ff7fabc9a4f0d311fcf0f63c6c9ffbd..ba012f45733b46e8fc06f932b8c76d88e4c3f591 100644
--- a/make/data/tzdata/backward
+++ b/make/data/tzdata/backward
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
 
+# Link	TARGET			LINK-NAME
 Link	Africa/Asmara		Africa/Asmera
-Link	Africa/Bamako		Africa/Timbuktu
+Link	Africa/Abidjan		Africa/Timbuktu
 Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
 Link	America/Adak		America/Atka
 Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
@@ -50,8 +50,11 @@ Link	America/Port_of_Spain	America/Virgin
 Link	Pacific/Auckland	Antarctica/South_Pole
 Link	Asia/Ashgabat		Asia/Ashkhabad
 Link	Asia/Kolkata		Asia/Calcutta
-Link	Asia/Chongqing		Asia/Chungking
+Link	Asia/Shanghai		Asia/Chongqing
+Link	Asia/Shanghai		Asia/Chungking
 Link	Asia/Dhaka		Asia/Dacca
+Link	Asia/Shanghai		Asia/Harbin
+Link	Asia/Urumqi		Asia/Kashgar
 Link	Asia/Kathmandu		Asia/Katmandu
 Link	Asia/Macau		Asia/Macao
 Link	Asia/Ho_Chi_Minh	Asia/Saigon
diff --git a/make/data/tzdata/etcetera b/make/data/tzdata/etcetera
index ebaa5fdfc0485682cdfe7b48e8b9e8ab46a9388c..d2fb91c9dd61d63aaaa6277f45c856d5c44f2707 100644
--- a/make/data/tzdata/etcetera
+++ b/make/data/tzdata/etcetera
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -37,7 +36,7 @@ Zone	Etc/UTC		0	-	UTC
 Zone	Etc/UCT		0	-	UCT
 
 # The following link uses older naming conventions,
-# but it belongs here, not in the file `backward',
+# but it belongs here, not in the file 'backward',
 # as functions like gmtime load the "GMT" file to handle leap seconds properly.
 # We want this to work even on installations that omit the other older names.
 Link	Etc/GMT				GMT
diff --git a/make/data/tzdata/europe b/make/data/tzdata/europe
index 226c393a0f2e38573ab264ab11753d025f32d919..0c5f5667da9085eb5879fe9168ea4320f2fbe6fa 100644
--- a/make/data/tzdata/europe
+++ b/make/data/tzdata/europe
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2014-05-31):
 # A good source for time zone historical data outside the U.S. is
 # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
 # San Diego: ACS Publications, Inc. (2003).
@@ -40,6 +40,9 @@
 # published semiannually.  Law sent in several helpful summaries
 # of the IATA's data after 1990.
 #
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
 # Except where otherwise noted, Shanks & Pottenger is the source for
 # entries through 1991, and IATA SSIM is the source for entries afterwards.
 #
@@ -49,9 +52,9 @@
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	
 #	William Willett, The Waste of Daylight, 19th edition
-#	 (1914-03)
+#	
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	.  He writes:
@@ -59,10 +62,20 @@
 #	may be sent to Mr. John Milne, Royal Geographical Society,
 #	Savile Row, London."  Nowadays please email them to tz@iana.org.
 #
-#	Brazil's Departamento Servico da Hora (DSH),
-#	
+#	Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+#	This Russian-language source was consulted by Vladimir Karpinsky; see
+#	http://mm.icann.org/pipermail/tz/2014-August/021320.html
+#	The full Russian citation is:
+#	Бялокоз, Евгений Людвигович. Новый счет времени в течении суток
+#	введенный декретом Совета народных комиссаров для всей России с 1-го
+#	июля 1919 г. / Изд. 2-е Междуведомственной комиссии. - Петроград:
+#	Десятая гос. тип., 1919.
+#	http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf
+#
+#	Brazil's Divisão Serviço da Hora (DSHO),
 #	History of Summer Time
-#	 (1998-09-21, in Portuguese)
+#	
+#	(1998-09-21, in Portuguese)
 
 #
 # I invented the abbreviations marked '*' in the following table;
@@ -81,10 +94,8 @@
 #        1:00       CET CEST CEMT Central Europe
 #        1:00:14    SET           Swedish (1879-1899)*
 #        2:00       EET EEST      Eastern Europe
-#        3:00       MSK MSD       Moscow
-#
-# A reliable and entertaining source about time zones, especially in Britain,
-# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#        3:00       FET           Further-eastern Europe*
+#        3:00       MSK MSD  MSM* Moscow
 
 # From Peter Ilieve (1994-12-04),
 # The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -128,7 +139,7 @@
 # along the towpath within a few yards of it.'
 #
 # I have a one inch to one mile map of London and my estimate of the stone's
-# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
+# position is 51 degrees 28' 30" N, 0 degrees 18' 45" W. The longitude should
 # be within about +-2". The Ordnance Survey grid reference is TQ172761.
 #
 # [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
@@ -160,8 +171,22 @@
 # transition date for London, namely 1847-12-01.  We don't know as much
 # about Dublin, so we use 1880-08-02, the legal transition time.
 
-# From Paul Eggert (2003-09-27):
-# Summer Time was first seriously proposed by William Willett (1857-1915),
+# From Paul Eggert (2014-07-19):
+# The ancients had no need for daylight saving, as they kept time
+# informally or via hours whose length depended on the time of year.
+# Daylight saving time in its modern sense was invented by the
+# New Zealand entomologist George Vernon Hudson (1867-1946),
+# whose day job as a postal clerk led him to value
+# after-hours daylight in which to pursue his research.
+# In 1895 he presented a paper to the Wellington Philosophical Society
+# that proposed a two-hour daylight-saving shift.  See:
+# Hudson GV. On seasonal time-adjustment in countries south of lat. 30 deg.
+# Transactions and Proceedings of the New Zealand Institute. 1895;28:734
+# http://rsnz.natlib.govt.nz/volume/rsnz_28/rsnz_28_00_006110.html
+# Although some interest was expressed in New Zealand, his proposal
+# did not find its way into law and eventually it was almost forgotten.
+#
+# In England, DST was independently reinvented by William Willett (1857-1915),
 # a London builder and member of the Royal Astronomical Society
 # who circulated a pamphlet "The Waste of Daylight" (1907)
 # that proposed advancing clocks 20 minutes on each of four Sundays in April,
@@ -174,7 +199,7 @@
 # A monument to Willett was unveiled on 1927-05-21, in an open space in
 # a 45-acre wood near Chislehurst, Kent that was purchased by popular
 # subscription and open to the public.  On the south face of the monolith,
-# designed by G. W. Miller, is the...William Willett Memorial Sundial,
+# designed by G. W. Miller, is the William Willett Memorial Sundial,
 # which is permanently set to Summer Time.
 
 # From Winston Churchill (1934-04-28):
@@ -183,9 +208,9 @@
 # between 160 and 170 hours more daylight leisure, to a war which
 # plunged Europe into darkness for four years, and shook the
 # foundations of civilization throughout the world.
-#	-- 
-#	"A Silent Toast to William Willett", Pictorial Weekly
-#	
+#	-- "A Silent Toast to William Willett", Pictorial Weekly;
+#	republished in Finest Hour (Spring 2002) 1(114):26
+#	http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
 
 # From Paul Eggert (1996-09-03):
 # The OED Supplement says that the English originally said "Daylight Saving"
@@ -194,7 +219,6 @@
 # proponents (who eventually won the argument) are quoted as using "Summer".
 
 # From Arthur David Olson (1989-01-19):
-#
 # A source at the British Information Office in New York avers that it's
 # known as "British" Summer Time in all parts of the United Kingdom.
 
@@ -221,8 +245,8 @@
 # official designation; the reply of the 21st was that there wasn't
 # but he couldn't think of anything better than the "Double British
 # Summer Time" that the BBC had been using informally.
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
+# http://www.polyomino.org.uk/british-time/bbc-19410418.png
+# http://www.polyomino.org.uk/british-time/ho-19410421.png
 
 # From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
 # [N]o official designation has as far as I know been adopted for the time
@@ -239,23 +263,14 @@
 # the history of summer time legislation in the United Kingdom.
 # Since 1998 Joseph S. Myers has been updating
 # and extending this list, which can be found in
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/
-# 
-# History of legal time in Britain
-# 
-# Rob Crowther (2012-01-04) reports that that URL no longer
-# exists, and the article can now be found at:
-# 
 # http://www.polyomino.org.uk/british-time/
-# 
 
 # From Joseph S. Myers (1998-01-06):
 #
 # The legal time in the UK outside of summer time is definitely GMT, not UTC;
 # see Lord Tanlaw's speech
-# 
-# (Lords Hansard 11 June 1997 columns 964 to 976)
-# .
+# http://www.publications.parliament.uk/pa/ld199798/ldhansrd/vo970611/text/70611-10.htm#70611-10_head0
+# (Lords Hansard 11 June 1997 columns 964 to 976).
 
 # From Paul Eggert (2006-03-22):
 #
@@ -295,8 +310,8 @@
 #   -- James Joyce, Ulysses
 
 # From Joseph S. Myers (2005-01-26):
-# Irish laws are available online at www.irishstatutebook.ie.  These include
-# various relating to legal time, for example:
+# Irish laws are available online at .
+# These include various relating to legal time, for example:
 #
 # ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
 #
@@ -458,25 +473,27 @@ Rule	GB-Eire 1990	1995	-	Oct	Sun>=22	1:00u	0	GMT
 # Use Europe/London for Jersey, Guernsey, and the Isle of Man.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1 0:00s
+Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1  0:00s
 			 0:00	GB-Eire	%s	1968 Oct 27
-			 1:00	-	BST	1971 Oct 31 2:00u
+			 1:00	-	BST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	%s	1996
 			 0:00	EU	GMT/BST
 Link	Europe/London	Europe/Jersey
 Link	Europe/London	Europe/Guernsey
 Link	Europe/London	Europe/Isle_of_Man
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
-			-0:25:21 -	DMT	1916 May 21 2:00
-			-0:25:21 1:00	IST	1916 Oct  1 2:00s
+			-0:25:21 -	DMT	1916 May 21  2:00
+			-0:25:21 1:00	IST	1916 Oct  1  2:00s
 			 0:00	GB-Eire	%s	1921 Dec  6 # independence
-			 0:00	GB-Eire	GMT/IST	1940 Feb 25 2:00
-			 0:00	1:00	IST	1946 Oct  6 2:00
-			 0:00	-	GMT	1947 Mar 16 2:00
-			 0:00	1:00	IST	1947 Nov  2 2:00
-			 0:00	-	GMT	1948 Apr 18 2:00
+			 0:00	GB-Eire	GMT/IST	1940 Feb 25  2:00
+			 0:00	1:00	IST	1946 Oct  6  2:00
+			 0:00	-	GMT	1947 Mar 16  2:00
+			 0:00	1:00	IST	1947 Nov  2  2:00
+			 0:00	-	GMT	1948 Apr 18  2:00
 			 0:00	GB-Eire	GMT/IST	1968 Oct 27
-			 1:00	-	IST	1971 Oct 31 2:00u
+			 1:00	-	IST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	GMT/IST	1996
 			 0:00	EU	GMT/IST
 
@@ -495,10 +512,9 @@ Rule	EU	1979	1995	-	Sep	lastSun	 1:00u	0	-
 Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
 # The most recent directive covers the years starting in 2002.  See:
-# 
 # Directive 2000/84/EC of the European Parliament and of the Council
 # of 19 January 2001 on summer-time arrangements.
-# 
+# http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT
 
 # W-Eur differs from EU only in that W-Eur uses standard time.
 Rule	W-Eur	1977	1980	-	Apr	Sun>=1	 1:00s	1:00	S
@@ -521,18 +537,18 @@ Rule	C-Eur	1943	only	-	Oct	 4	 2:00s	0	-
 Rule	C-Eur	1944	1945	-	Apr	Mon>=1	 2:00s	1:00	S
 # Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
 Rule	C-Eur	1944	only	-	Oct	 2	 2:00s	0	-
-# From Jesper Norgaard Welen (2008-07-13):
+# From Jesper Nørgaard Welen (2008-07-13):
 #
 # I found what is probably a typo of 2:00 which should perhaps be 2:00s
 # in the C-Eur rule from tz database version 2008d (this part was
-# corrected in version 2008d). The circumstancial evidence is simply the
+# corrected in version 2008d). The circumstantial evidence is simply the
 # tz database itself, as seen below:
 #
 # Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15  0:01
 #    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
-#    0:00 France WE%sT 1945 Sep 16 3:00
+#    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Belgrade 1:22:00 - LMT 1884
 #    1:00 1:00 CEST 1945 Sep 16  2:00s
@@ -576,16 +592,16 @@ Rule	E-Eur	1981	max	-	Mar	lastSun	 0:00	1:00	S
 Rule	E-Eur	1996	max	-	Oct	lastSun	 0:00	0	-
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST	# Moscow Summer Time
-Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT	# Moscow Mean Time
-Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST	# Moscow Double Summer Time
+Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST  # Moscow Summer Time
+Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT  # Moscow Mean Time
+Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST # Moscow Double Summer Time
 Rule	Russia	1918	only	-	Sep	16	 1:00	1:00	MST
 Rule	Russia	1919	only	-	May	31	23:00	2:00	MDST
-Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	S
-Rule	Russia	1919	only	-	Aug	16	 0:00	0	-
-Rule	Russia	1921	only	-	Feb	14	23:00	1:00	S
-Rule	Russia	1921	only	-	Mar	20	23:00	2:00	M # Midsummer
-Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	S
+Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	MSD
+Rule	Russia	1919	only	-	Aug	16	 0:00	0	MSK
+Rule	Russia	1921	only	-	Feb	14	23:00	1:00	MSD
+Rule	Russia	1921	only	-	Mar	20	23:00	2:00	MSM  # Midsummer
+Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	MSD
 Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
 # Act No.925 of the Council of Ministers of the USSR (1980-10-24):
 Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
@@ -607,14 +623,10 @@ Rule	Russia	1996	2010	-	Oct	lastSun	 2:00s	0	-
 # According to the law Russia is abolishing daylight saving time.
 #
 # Medvedev signed a law "On the Calculation of Time" (in russian):
-# 
 # http://bmockbe.ru/events/?ID=7583
-# 
 #
 # Medvedev signed a law on the calculation of the time (in russian):
-# 
 # http://www.regnum.ru/news/polit/1413906.html
-# 
 
 # From Arthur David Olson (2011-06-15):
 # Take "abolishing daylight saving time" to mean that time is now considered
@@ -634,10 +646,10 @@ Zone	EET		2:00	EU	EE%sT
 # From Markus Kuhn (1996-07-12):
 # The official German names ... are
 #
-#	Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
-#	Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
+#	Mitteleuropäische Zeit (MEZ)         = UTC+01:00
+#	Mitteleuropäische Sommerzeit (MESZ)  = UTC+02:00
 #
-# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
+# as defined in the German Time Act (Gesetz über die Zeitbestimmung (ZeitG),
 # 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
 # I wrote ... to the German Federal Physical-Technical Institution
 #
@@ -692,7 +704,7 @@ Zone	Europe/Tirane	1:19:20 -	LMT	1914
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Andorra	0:06:04 -	LMT	1901
 			0:00	-	WET	1946 Sep 30
-			1:00	-	CET	1985 Mar 31 2:00
+			1:00	-	CET	1985 Mar 31  2:00
 			1:00	EU	CE%sT
 
 # Austria
@@ -718,9 +730,9 @@ Rule	Austria	1980	only	-	Sep	28	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 			1:00	C-Eur	CE%sT	1920
-			1:00	Austria	CE%sT	1940 Apr  1 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
-			1:00	1:00	CEST	1945 Apr 12 2:00s
+			1:00	Austria	CE%sT	1940 Apr  1  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
+			1:00	1:00	CEST	1945 Apr 12  2:00s
 			1:00	-	CET	1946
 			1:00	Austria	CE%sT	1981
 			1:00	EU	CE%sT
@@ -731,38 +743,29 @@ Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 # GMT+3 without DST (was GMT+2 with DST).
 #
 # Sources (Russian language):
-# 1.
-# 
 # http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
-# 
-# 2.
-# 
 # http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
-# 
-# 3.
-# 
 # http://news.tut.by/society/250578.html
-# 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Minsk	1:50:16 -	LMT	1880
-			1:50	-	MMT	1924 May 2 # Minsk Mean Time
+			1:50	-	MMT	1924 May  2 # Minsk Mean Time
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Jun 28
 			1:00	C-Eur	CE%sT	1944 Jul  3
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
-			2:00	-	EET	1992 Mar 29 0:00s
-			2:00	1:00	EEST	1992 Sep 27 0:00s
-			2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			3:00	-	FET # Further-eastern European Time
+			3:00	-	MSK	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
+			2:00	-	EET	1992 Mar 29  0:00s
+			2:00	1:00	EEST	1992 Sep 27  0:00s
+			2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			3:00	-	FET
 
 # Belgium
 #
 # From Paul Eggert (1997-07-02):
 # Entries from 1918 through 1991 are taken from:
 #	Annuaire de L'Observatoire Royal de Belgique,
-#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
+#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
 #	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
 #	pp 8-9.
 # LMT before 1892 was 0:17:30, according to the official journal of Belgium:
@@ -812,7 +815,7 @@ Rule	Belgium	1946	only	-	May	19	 2:00s	1:00	S
 Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Brussels	0:17:30 -	LMT	1880
-			0:17:30	-	BMT	1892 May  1 12:00 # Brussels MT
+			0:17:30	-	BMT	1892 May  1 12:00  # Brussels MT
 			0:00	-	WET	1914 Nov  8
 			1:00	-	CET	1916 May  1  0:00
 			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
@@ -828,8 +831,8 @@ Zone	Europe/Brussels	0:17:30 -	LMT	1880
 #
 # From Plamen Simenov via Steffen Thorsen (1999-09-09):
 # A document of Government of Bulgaria (No.94/1997) says:
-# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
-# EETDST --> EET is in 04:00 Local time in last Sunday of October
+# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
+# EETDST -> EET is in 04:00 Local time in last Sunday of October
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Bulg	1979	only	-	Mar	31	23:00	1:00	S
@@ -842,7 +845,7 @@ Zone	Europe/Sofia	1:33:16 -	LMT	1880
 			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
 			2:00	-	EET	1942 Nov  2  3:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 Apr 2 3:00
+			1:00	-	CET	1945 Apr  2  3:00
 			2:00	-	EET	1979 Mar 31 23:00
 			2:00	Bulg	EE%sT	1982 Sep 26  2:00
 			2:00	C-Eur	EE%sT	1991
@@ -866,15 +869,15 @@ Rule	Czech	1948	only	-	Apr	18	2:00s	1:00	S
 Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Prague	0:57:44 -	LMT	1850
-			0:57:44	-	PMT	1891 Oct     # Prague Mean Time
-			1:00	C-Eur	CE%sT	1944 Sep 17 2:00s
+			0:57:44	-	PMT	1891 Oct    # Prague Mean Time
+			1:00	C-Eur	CE%sT	1944 Sep 17  2:00s
 			1:00	Czech	CE%sT	1979
 			1:00	EU	CE%sT
 # Use Europe/Prague also for Slovakia.
 
 # Denmark, Faroe Islands, and Greenland
 
-# From Jesper Norgaard Welen (2005-04-26):
+# From Jesper Nørgaard Welen (2005-04-26):
 # http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
 # [introducing standard time] was in effect from 1894-01-01....
 # The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
@@ -884,7 +887,7 @@ Zone	Europe/Prague	0:57:44 -	LMT	1850
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
 #
 # This provoked a new law from 1974 to make possible summer time changes
-# in subsequenet decrees with the law
+# in subsequent decrees with the law
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
 #
 # It seems however that no decree was set forward until 1980.  I have
@@ -899,7 +902,7 @@ Zone	Europe/Prague	0:57:44 -	LMT	1850
 # was suspended on that night):
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
 
-# From Jesper Norgaard Welen (2005-06-11):
+# From Jesper Nørgaard Welen (2005-06-11):
 # The Herning Folkeblad (1980-09-26) reported that the night between
 # Saturday and Sunday the clock is set back from three to two.
 
@@ -923,11 +926,11 @@ Rule	Denmark	1948	only	-	Aug	 8	 2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
 			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
-			 1:00	Denmark	CE%sT	1942 Nov  2 2:00s
-			 1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			 1:00	Denmark	CE%sT	1942 Nov  2  2:00s
+			 1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			 1:00	Denmark	CE%sT	1980
 			 1:00	EU	CE%sT
-Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
+Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11 # Tórshavn
 			 0:00	-	WET	1981
 			 0:00	EU	WE%sT
 #
@@ -939,11 +942,11 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
 # From Paul Eggert (2006-03-22):
 # Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
 # and left the EU on 1985-02-01.  It therefore should have been using EU
-# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthab
+# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthåb
 # used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
 # rules since at least 1991.  Assume EU rules since 1980.
 
-# From Gwillin Law (2001-06-06), citing
+# From Gwillim Law (2001-06-06), citing
 #  (2001-03-15),
 # and with translations corrected by Steffen Thorsen:
 #
@@ -978,16 +981,16 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
 # DPC research station at Zackenberg.
 #
 # Scoresbysund and two small villages nearby keep time UTC-1 and use
-# the same daylight savings time period as in West Greenland (Godthab).
+# the same daylight savings time period as in West Greenland (Godthåb).
 #
-# The rest of Greenland, including Godthab (this area, although it
+# The rest of Greenland, including Godthåb (this area, although it
 # includes central Greenland, is known as west Greenland), keeps time
 # UTC-3, with daylight savings methods according to European rules.
 #
 # It is common procedure to use UTC 0 in the wilderness of East and
 # North Greenland, because it is mainly Icelandic aircraft operators
 # maintaining traffic in these areas.  However, the official status of
-# this area is that it sticks with Godthab time.  This area might be
+# this area is that it sticks with Godthåb time.  This area might be
 # considered a dual time zone in some respects because of this.
 
 # From Rives McDow (2001-11-19):
@@ -996,8 +999,8 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
 
 # From Paul Eggert (2006-03-22):
 # From 1997 on the CIA map shows Danmarkshavn on GMT;
-# the 1995 map as like Godthab.
-# For lack of better info, assume they were like Godthab before 1996.
+# the 1995 map as like Godthåb.
+# For lack of better info, assume they were like Godthåb before 1996.
 # startkart.no says Thule does not observe DST, but this is clearly an error,
 # so go with Shanks & Pottenger for Thule transitions until this year.
 # For 2007 on assume Thule will stay in sync with US DST rules.
@@ -1012,15 +1015,15 @@ Rule	Thule	2007	max	-	Nov	Sun>=1	2:00	0	S
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT	1996
 			0:00	-	GMT
 Zone America/Scoresbysund -1:27:52 -	LMT	1916 Jul 28 # Ittoqqortoormiit
-			-2:00	-	CGT	1980 Apr  6 2:00
+			-2:00	-	CGT	1980 Apr  6  2:00
 			-2:00	C-Eur	CG%sT	1981 Mar 29
 			-1:00	EU	EG%sT
 Zone America/Godthab	-3:26:56 -	LMT	1916 Jul 28 # Nuuk
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT
 Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 			-4:00	Thule	A%sT
@@ -1042,17 +1045,16 @@ Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 # summer time next spring."
 
 # From Peter Ilieve (1998-11-04), heavily edited:
-# 
 # The 1998-09-22 Estonian time law
-# 
+# http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390
 # refers to the Eighth Directive and cites the association agreement between
-# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
+# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22-27, 120).
 #
 # I also asked [my relative] whether they use any standard abbreviation
 # for their standard and summer times. He says no, they use "suveaeg"
 # (summer time) and "talveaeg" (winter time).
 
-# From The Baltic Times (1999-09-09)
+# From The Baltic Times  (1999-09-09)
 # via Steffen Thorsen:
 # This year will mark the last time Estonia shifts to summer time,
 # a council of the ruling coalition announced Sept. 6....
@@ -1070,19 +1072,19 @@ Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 # The Estonian government has changed once again timezone politics.
 # Now we are using again EU rules.
 #
-# From Urmet Jaanes (2002-03-28):
+# From Urmet Jänes (2002-03-28):
 # The legislative reference is Government decree No. 84 on 2002-02-21.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Tallinn	1:39:00	-	LMT	1880
-			1:39:00	-	TMT	1918 Feb # Tallinn Mean Time
+			1:39:00	-	TMT	1918 Feb    # Tallinn Mean Time
 			1:00	C-Eur	CE%sT	1919 Jul
 			1:39:00	-	TMT	1921 May
 			2:00	-	EET	1940 Aug  6
 			3:00	-	MSK	1941 Sep 15
 			1:00	C-Eur	CE%sT	1944 Sep 22
-			3:00	Russia	MSK/MSD	1989 Mar 26 2:00s
-			2:00	1:00	EEST	1989 Sep 24 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
+			2:00	1:00	EEST	1989 Sep 24  2:00s
 			2:00	C-Eur	EE%sT	1998 Sep 22
 			2:00	EU	EE%sT	1999 Nov  1
 			2:00	-	EET	2002 Feb 21
@@ -1104,35 +1106,45 @@ Zone	Europe/Tallinn	1:39:00	-	LMT	1880
 # This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
 # Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
 # Finnish) at
-#
-# 
 # http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
-# 
 #
 # Page 105 (56 in PDF version) has a handy table of all past daylight savings
 # transitions. It is easy enough to interpret without Finnish skills.
 #
 # This is also confirmed by Finnish Broadcasting Company's archive at:
-#
-# 
 # http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
-# 
 #
 # The news clip from 1981 says that "the time between 2 and 3 o'clock does not
 # exist tonight."
 
+# From Konstantin Hyppönen (2014-06-13):
+# [Heikki Oja's book Aikakirja 2013]
+# http://almanakka.helsinki.fi/images/aikakirja/Aikakirja2013kokonaan.pdf
+# pages 104-105, including a scan from a newspaper published on Apr 2 1942
+# say that ... [o]n Apr 2 1942, 24 o'clock (which means Apr 3 1942,
+# 00:00), clocks were moved one hour forward. The newspaper
+# mentions "on the night from Thursday to Friday"....
+# On Oct 4 1942, clocks were moved at 1:00 one hour backwards.
+#
+# From Paul Eggert (2014-06-14):
+# Go with Oja over Shanks.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Finland	1942	only	-	Apr	3	0:00	1:00	S
-Rule	Finland	1942	only	-	Oct	3	0:00	0	-
+Rule	Finland	1942	only	-	Apr	2	24:00	1:00	S
+Rule	Finland	1942	only	-	Oct	4	1:00	0	-
 Rule	Finland	1981	1982	-	Mar	lastSun	2:00	1:00	S
 Rule	Finland	1981	1982	-	Sep	lastSun	3:00	0	-
+
+# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
+# round to nearest.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Helsinki	1:39:52 -	LMT	1878 May 31
-			1:39:52	-	HMT	1921 May    # Helsinki Mean Time
+Zone	Europe/Helsinki	1:39:49 -	LMT	1878 May 31
+			1:39:49	-	HMT	1921 May    # Helsinki Mean Time
 			2:00	Finland	EE%sT	1983
 			2:00	EU	EE%sT
 
-# Aaland Is
+# Åland Is
 Link	Europe/Helsinki	Europe/Mariehamn
 
 
@@ -1140,14 +1152,14 @@ Link	Europe/Helsinki	Europe/Mariehamn
 
 # From Ciro Discepolo (2000-12-20):
 #
-# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
+# Henri Le Corre, Régimes horaires pour le monde entier, Éditions
 # Traditionnelles - Paris 2 books, 1993
 #
-# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
+# Gabriel, Traité de l'heure dans le monde, Guy Trédaniel,
 # Paris, 1991
 #
-# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
-# Guy tredaniel, Paris 1987
+# Françoise Gauquelin, Problèmes de l'heure résolus en astrologie,
+# Guy Trédaniel, Paris 1987
 
 
 #
@@ -1188,16 +1200,16 @@ Rule	France	1939	only	-	Nov	18	23:00s	0	-
 Rule	France	1940	only	-	Feb	25	 2:00	1:00	S
 # The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
 # write that they were used in Monaco and in many French locations.
-# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
-# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
-# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
+# Le Corre writes that the upper limit of the free zone was Arnéguy, Orthez,
+# Mont-de-Marsan, Bazas, Langon, Lamothe-Montravel, Marœuil, La
+# Rochefoucauld, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
 # Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
-# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
+# Paray-le-Monial, Montceau-les-Mines, Chalon-sur-Saône, Arbois,
 # Dole, Morez, St-Claude, and Collonges (Haute-Savoie).
 Rule	France	1941	only	-	May	 5	 0:00	2:00	M # Midsummer
 # Shanks & Pottenger say this transition occurred at Oct 6 1:00,
 # but go with Denis Excoffier (1997-12-12),
-# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
+# who quotes the Ephémérides astronomiques for 1998 from Bureau des Longitudes
 # as saying 5/10/41 22hUT.
 Rule	France	1941	only	-	Oct	 6	 0:00	1:00	S
 Rule	France	1942	only	-	Mar	 9	 0:00	2:00	M
@@ -1218,7 +1230,7 @@ Rule	France	1976	only	-	Sep	26	 1:00	0	-
 # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
-			0:09:21	-	PMT	1911 Mar 11  0:01  # Paris MT
+			0:09:21	-	PMT	1911 Mar 11  0:01 # Paris MT
 # Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
 			0:00	France	WE%sT	1940 Jun 14 23:00
 # Le Corre says Paris stuck with occupied-France time after the liberation;
@@ -1235,15 +1247,13 @@ Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
 # Bundesanstalt contains DST information back to 1916.
 # [See tz-link.htm for the URL.]
 
-# From Joerg Schilling (2002-10-23):
+# From Jörg Schilling (2002-10-23):
 # In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
-# 
-# General [Nikolai] Bersarin.
+# http://www.dhm.de/lemo/html/biografien/BersarinNikolai/
+# General [Nikolai] Bersarin.
 
 # From Paul Eggert (2003-03-08):
-# 
 # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
-# 
 # says that Bersarin issued an order to use Moscow time on May 20.
 # However, Moscow did not observe daylight saving in 1945, so
 # this was equivalent to CEMT (GMT+3), not GMT+4.
@@ -1268,23 +1278,23 @@ Rule SovietZone	1945	only	-	Nov	18	2:00s	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
-			1:00	C-Eur	CE%sT	1945 May 24 2:00
+			1:00	C-Eur	CE%sT	1945 May 24  2:00
 			1:00 SovietZone	CE%sT	1946
 			1:00	Germany	CE%sT	1980
 			1:00	EU	CE%sT
 
 # From Tobias Conradi (2011-09-12):
-# Busingen , surrounded by the Swiss canton
+# Büsingen , surrounded by the Swiss canton
 # Schaffhausen, did not start observing DST in 1980 as the rest of DE
 # (West Germany at that time) and DD (East Germany at that time) did.
 # DD merged into DE, the area is currently covered by code DE in ISO 3166-1,
 # which in turn is covered by the zone Europe/Berlin.
 #
-# Source for the time in Busingen 1980:
+# Source for the time in Büsingen 1980:
 # http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3
 
 # From Arthur David Olson (2012-03-03):
-# Busingen and Zurich have shared clocks since 1970.
+# Büsingen and Zurich have shared clocks since 1970.
 
 Link	Europe/Zurich	Europe/Busingen
 
@@ -1295,8 +1305,8 @@ Link	Europe/Zurich	Europe/Busingen
 
 # Gibraltar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2 0:00s
-			0:00	GB-Eire	%s	1957 Apr 14 2:00
+Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2  0:00s
+			0:00	GB-Eire	%s	1957 Apr 14  2:00
 			1:00	-	CET	1982
 			1:00	EU	CE%sT
 
@@ -1327,7 +1337,7 @@ Rule	Greece	1980	only	-	Apr	 1	0:00	1:00	S
 Rule	Greece	1980	only	-	Sep	28	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
-			1:34:52	-	AMT	1916 Jul 28 0:01     # Athens MT
+			1:34:52	-	AMT	1916 Jul 28  0:01 # Athens MT
 			2:00	Greece	EE%sT	1941 Apr 30
 			1:00	Greece	CE%sT	1944 Apr  4
 			2:00	Greece	EE%sT	1981
@@ -1336,15 +1346,20 @@ Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
 			2:00	EU	EE%sT
 
 # Hungary
+# From Paul Eggert (2014-07-15):
+# Dates for 1916-1945 are taken from:
+# Oross A. Jelen a múlt jövője: a nyári időszámítás Magyarországon 1916-1945.
+# National Archives of Hungary (2012-10-29).
+# http://mnl.gov.hu/a_het_dokumentuma/a_nyari_idoszamitas_magyarorszagon_19161945.html
+# This source does not always give times, which are taken from Shanks
+# & Pottenger (which disagree about the dates).
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Hungary	1918	only	-	Apr	 1	 3:00	1:00	S
-Rule	Hungary	1918	only	-	Sep	29	 3:00	0	-
+Rule	Hungary	1918	only	-	Sep	16	 3:00	0	-
 Rule	Hungary	1919	only	-	Apr	15	 3:00	1:00	S
-Rule	Hungary	1919	only	-	Sep	15	 3:00	0	-
-Rule	Hungary	1920	only	-	Apr	 5	 3:00	1:00	S
-Rule	Hungary	1920	only	-	Sep	30	 3:00	0	-
+Rule	Hungary	1919	only	-	Nov	24	 3:00	0	-
 Rule	Hungary	1945	only	-	May	 1	23:00	1:00	S
-Rule	Hungary	1945	only	-	Nov	 3	 0:00	0	-
+Rule	Hungary	1945	only	-	Nov	 1	 0:00	0	-
 Rule	Hungary	1946	only	-	Mar	31	 2:00s	1:00	S
 Rule	Hungary	1946	1949	-	Oct	Sun>=1	 2:00s	0	-
 Rule	Hungary	1947	1949	-	Apr	Sun>=4	 2:00s	1:00	S
@@ -1360,7 +1375,7 @@ Rule	Hungary	1980	only	-	Apr	 6	 1:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
 			1:00	C-Eur	CE%sT	1918
-			1:00	Hungary	CE%sT	1941 Apr  6  2:00
+			1:00	Hungary	CE%sT	1941 Apr  8
 			1:00	C-Eur	CE%sT	1945
 			1:00	Hungary	CE%sT	1980 Sep 28  2:00s
 			1:00	EU	CE%sT
@@ -1423,7 +1438,7 @@ Rule	Iceland	1967	only	-	Oct	29	 1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
 			-1:27:48 -	RMT	1908 # Reykjavik Mean Time?
-			-1:00	Iceland	IS%sT	1968 Apr 7 1:00s
+			-1:00	Iceland	IS%sT	1968 Apr  7  1:00s
 			 0:00	-	GMT
 
 # Italy
@@ -1438,9 +1453,8 @@ Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
 # From Paul Eggert (2006-03-22):
 # For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
 # F. Pollastri
-# 
 # Day-light Saving Time in Italy (2006-02-03)
-# 
+# http://toi.iriti.cnr.it/uk/ienitlt.html
 # ('FP' below), taken from an Italian National Electrotechnical Institute
 # publication. When the three sources disagree, guess who's right, as follows:
 #
@@ -1500,8 +1514,8 @@ Rule	Italy	1978	only	-	Oct	 1	0:00s	0	-
 Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
-			0:49:56	-	RMT	1893 Nov  1 0:00s # Rome Mean
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
+			0:49:56	-	RMT	1893 Nov  1  0:00s # Rome Mean
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
 			1:00	C-Eur	CE%sT	1944 Jul
 			1:00	Italy	CE%sT	1980
 			1:00	EU	CE%sT
@@ -1548,18 +1562,18 @@ Link	Europe/Rome	Europe/San_Marino
 
 # From Andrei Ivanov (2000-03-06):
 # This year Latvia will not switch to Daylight Savings Time (as specified in
-# 
 # The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79), in Latvian for subscribers only).
+# 29-Feb-2000 (#79) ,
+# in Latvian for subscribers only).
 
-# 
-# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
-# 
+# From RFE/RL Newsline
+# http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html
+# (2001-01-03), noted after a heads-up by Rives McDow:
 # The Latvian government on 2 January decided that the country will
 # institute daylight-saving time this spring, LETA reported.
 # Last February the three Baltic states decided not to turn back their
 # clocks one hour in the spring....
-# Minister of Economy Aigars Kalvitis noted that Latvia had too few
+# Minister of Economy Aigars Kalvītis noted that Latvia had too few
 # daylight hours and thus decided to comply with a draft European
 # Commission directive that provides for instituting daylight-saving
 # time in EU countries between 2002 and 2006. The Latvian government
@@ -1569,18 +1583,23 @@ Link	Europe/Rome	Europe/San_Marino
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Latvia	1989	1996	-	Mar	lastSun	 2:00s	1:00	S
 Rule	Latvia	1989	1996	-	Sep	lastSun	 2:00s	0	-
+
+# Milne 1899 says Riga was 1:36:28 (Polytechnique House time).
+# Byalokoz 1919 says Latvia was 1:36:34.
+# Go with Byalokoz.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Riga	1:36:24	-	LMT	1880
-			1:36:24	-	RMT	1918 Apr 15 2:00 #Riga Mean Time
-			1:36:24	1:00	LST	1918 Sep 16 3:00 #Latvian Summer
-			1:36:24	-	RMT	1919 Apr  1 2:00
-			1:36:24	1:00	LST	1919 May 22 3:00
-			1:36:24	-	RMT	1926 May 11
+Zone	Europe/Riga	1:36:34	-	LMT	1880
+			1:36:34	-	RMT	1918 Apr 15  2:00 # Riga MT
+			1:36:34	1:00	LST	1918 Sep 16  3:00 # Latvian ST
+			1:36:34	-	RMT	1919 Apr  1  2:00
+			1:36:34	1:00	LST	1919 May 22  3:00
+			1:36:34	-	RMT	1926 May 11
 			2:00	-	EET	1940 Aug  5
 			3:00	-	MSK	1941 Jul
 			1:00	C-Eur	CE%sT	1944 Oct 13
-			3:00	Russia	MSK/MSD	1989 Mar lastSun 2:00s
-			2:00	1:00	EEST	1989 Sep lastSun 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar lastSun  2:00s
+			2:00	1:00	EEST	1989 Sep lastSun  2:00s
 			2:00	Latvia	EE%sT	1997 Jan 21
 			2:00	EU	EE%sT	2000 Feb 29
 			2:00	-	EET	2001 Jan  2
@@ -1614,7 +1633,7 @@ Link Europe/Zurich Europe/Vaduz
 # I would like to inform that in this year Lithuanian time zone
 # (Europe/Vilnius) was changed.
 
-# From ELTA No. 972 (2582) (1999-09-29),
+# From ELTA No. 972 (2582) (1999-09-29) ,
 # via Steffen Thorsen:
 # Lithuania has shifted back to the second time zone (GMT plus two hours)
 # to be valid here starting from October 31,
@@ -1623,9 +1642,9 @@ Link Europe/Zurich Europe/Vaduz
 # motion to give up shifting to summer time in spring, as it was
 # already done by Estonia.
 
-# From the 
-# Fact File, Lithuanian State Department of Tourism
-#  (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
+# From the Fact File, Lithuanian State Department of Tourism
+#  (2000-03-27):
+# Local time is GMT+2 hours ..., no daylight saving.
 
 # From a user via Klaus Marten (2003-02-07):
 # As a candidate for membership of the European Union, Lithuania will
@@ -1638,18 +1657,18 @@ Link Europe/Zurich Europe/Vaduz
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vilnius	1:41:16	-	LMT	1880
-			1:24:00	-	WMT	1917	    # Warsaw Mean Time
+			1:24:00	-	WMT	1917        # Warsaw Mean Time
 			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
 			1:00	-	CET	1920 Jul 12
 			2:00	-	EET	1920 Oct  9
 			1:00	-	CET	1940 Aug  3
 			3:00	-	MSK	1941 Jun 24
 			1:00	C-Eur	CE%sT	1944 Aug
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
 			2:00	C-Eur	EE%sT	1998
-			2:00	-	EET	1998 Mar 29 1:00u
-			1:00	EU	CE%sT	1999 Oct 31 1:00u
+			2:00	-	EET	1998 Mar 29  1:00u
+			1:00	EU	CE%sT	1999 Oct 31  1:00u
 			2:00	-	EET	2003 Jan  1
 			2:00	EU	EE%sT
 
@@ -1683,9 +1702,9 @@ Rule	Lux	1929	only	-	Apr	20	23:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
 			1:00	Lux	CE%sT	1918 Nov 25
-			0:00	Lux	WE%sT	1929 Oct  6 2:00s
-			0:00	Belgium	WE%sT	1940 May 14 3:00
-			1:00	C-Eur	WE%sT	1944 Sep 18 3:00
+			0:00	Lux	WE%sT	1929 Oct  6  2:00s
+			0:00	Belgium	WE%sT	1940 May 14  3:00
+			1:00	C-Eur	WE%sT	1944 Sep 18  3:00
 			1:00	Belgium	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1702,9 +1721,9 @@ Rule	Malta	1975	1979	-	Apr	Sun>=15	2:00	1:00	S
 Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
 Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
+Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
 			1:00	Italy	CE%sT	1973 Mar 31
 			1:00	Malta	CE%sT	1981
 			1:00	EU	CE%sT
@@ -1719,7 +1738,7 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
 # In early 1992 there was large-scale interethnic violence in the area
 # and it's possible that some Russophones continued to observe Moscow time.
 # But [two people] separately reported via
-# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
+# Jesper Nørgaard that as of 2001-01-24 Tiraspol was like Chisinau.
 # The Tiraspol entry has therefore been removed for now.
 #
 # From Alexander Krivenyshev (2011-10-17):
@@ -1728,13 +1747,8 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
 # to the Winter Time).
 #
 # News (in Russian):
-# 
 # http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html
-# 
-#
-# 
 # http://www.allmoldova.com/moldova-news/1249064116.html
-# 
 #
 # The substance of this change (reinstatement of the Tiraspol entry)
 # is from a patch from Petr Machata (2011-10-17)
@@ -1752,9 +1766,7 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
 # Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
 # Tiraspol will go back to winter time on October 30, 2011.
 # News from Moldova (in russian):
-# 
 # http://ru.publika.md/link_317061.html
-# 
 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1777,8 +1789,8 @@ Zone	Europe/Chisinau	1:55:20 -	LMT	1880
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	France	WE%sT	1945 Sep 16 3:00
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	France	WE%sT	1945 Sep 16  3:00
 			1:00	France	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1822,8 +1834,8 @@ Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
 # was not until 1866 when they were all required by law to observe
 # Amsterdam mean time.
 
-# The data before 1945 are taken from
-# .
+# The data entries before 1945 are taken from
+# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
@@ -1854,8 +1866,8 @@ Rule	Neth	1945	only	-	Sep	16	2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Amsterdam	0:19:32 -	LMT	1835
 			0:19:32	Neth	%s	1937 Jul  1
-			0:20	Neth	NE%sT	1940 May 16 0:00 # Dutch Time
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			0:20	Neth	NE%sT	1940 May 16  0:00 # Dutch Time
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			1:00	Neth	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1885,14 +1897,14 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 # time they were declared as parts of Norway.  Svalbard was declared
 # as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
 # Mayen by law of 1930-02-27 no 2, section 2. (From
-# http://www.lovdata.no/all/nl-19250717-011.html and
-# http://www.lovdata.no/all/nl-19300227-002.html).  The law/regulation
+#  and
+# ).  The law/regulation
 # for normal/standard time in Norway is from 1894-06-29 no 1 (came
 # into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
 # part of this law since 1925/1930. (From
-# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
+# ) I have not been
 # able to find if Jan Mayen used a different time zone (e.g. -0100)
-# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
+# before 1930. Jan Mayen has only been "inhabited" since 1921 by
 # Norwegian meteorologists and maybe used the same time as Norway ever
 # since 1921.  Svalbard (Arctic/Longyearbyen) has been inhabited since
 # before 1895, and therefore probably changed the local time somewhere
@@ -1907,7 +1919,7 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 #  says that the meteorologists
 # burned down their station in 1940 and left the island, but returned in
 # 1941 with a small Norwegian garrison and continued operations despite
-# frequent air ttacks from Germans.  In 1943 the Americans established a
+# frequent air attacks from Germans.  In 1943 the Americans established a
 # radiolocating station on the island, called "Atlantic City".  Possibly
 # the UT offset changed during the war, but I think it unlikely that
 # Jan Mayen used German daylight-saving rules.
@@ -1918,7 +1930,7 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 #  says that the Germans were
 # expelled on 1942-05-14.  However, small parties of Germans did return,
 # and according to Wilhelm Dege's book "War North of 80" (1954)
-# 
+# http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html
 # the German armed forces at the Svalbard weather station code-named
 # Haudegen did not surrender to the Allies until September 1945.
 #
@@ -1927,6 +1939,10 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 Link	Europe/Oslo	Arctic/Longyearbyen
 
 # Poland
+
+# The 1919 dates and times can be found in Tygodnik Urzędowy nr 1 (1919-03-20),
+#  pp 1-2.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Poland	1918	1919	-	Sep	16	2:00s	0	-
 Rule	Poland	1919	only	-	Apr	15	2:00s	1:00	S
@@ -1937,9 +1953,9 @@ Rule	Poland	1944	only	-	Oct	 4	2:00	0	-
 Rule	Poland	1945	only	-	Apr	29	0:00	1:00	S
 Rule	Poland	1945	only	-	Nov	 1	0:00	0	-
 # For 1946 on the source is Kazimierz Borkowski,
-# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
-# 
-# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
+# Toruń Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
+# http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1
+# Thanks to Przemysław Augustyniak (2005-05-28) for this reference.
 # He also gives these further references:
 # Mon Pol nr 13, poz 162 (1995) 
 # Druk nr 2180 (2003) 
@@ -1959,10 +1975,10 @@ Rule	Poland	1961	1964	-	May	lastSun	1:00s	1:00	S
 Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Warsaw	1:24:00 -	LMT	1880
-			1:24:00	-	WMT	1915 Aug  5   # Warsaw Mean Time
-			1:00	C-Eur	CE%sT	1918 Sep 16 3:00
+			1:24:00	-	WMT	1915 Aug  5 # Warsaw Mean Time
+			1:00	C-Eur	CE%sT	1918 Sep 16  3:00
 			2:00	Poland	EE%sT	1922 Jun
-			1:00	Poland	CE%sT	1940 Jun 23 2:00
+			1:00	Poland	CE%sT	1940 Jun 23  2:00
 			1:00	C-Eur	CE%sT	1944 Oct
 			1:00	Poland	CE%sT	1977
 			1:00	W-Eur	CE%sT	1988
@@ -1970,6 +1986,14 @@ Zone	Europe/Warsaw	1:24:00 -	LMT	1880
 
 # Portugal
 #
+# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
+# According to a Portuguese decree (1911-05-26)
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# Lisbon was at -0:36:44.68, but switched to GMT on 1912-01-01 at 00:00.
+# Round the old offset to -0:36:45.  This agrees with Willett but disagrees
+# with Shanks, who says the transition occurred on 1911-05-24 at 00:00 for
+# Europe/Lisbon, Atlantic/Azores, and Atlantic/Madeira.
+#
 # From Rui Pedro Salgueiro (1992-11-12):
 # Portugal has recently (September, 27) changed timezone
 # (from WET to MET or CET) to harmonize with EEC.
@@ -2049,35 +2073,34 @@ Rule	Port	1979	1982	-	Sep	lastSun	 1:00s	0	-
 Rule	Port	1980	only	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
 Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
-# Willett says 1912-01-01.  Go with Willett.
-Zone	Europe/Lisbon	-0:36:32 -	LMT	1884
-			-0:36:32 -	LMT	1912 Jan  1  # Lisbon Mean Time
-			 0:00	Port	WE%sT	1966 Apr  3 2:00
-			 1:00	-	CET	1976 Sep 26 1:00
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
-			 0:00	W-Eur	WE%sT	1992 Sep 27 1:00s
-			 1:00	EU	CE%sT	1996 Mar 31 1:00u
+Zone	Europe/Lisbon	-0:36:45 -	LMT	1884
+			-0:36:45 -	LMT	1912 Jan  1 # Lisbon Mean Time
+			 0:00	Port	WE%sT	1966 Apr  3  2:00
+			 1:00	-	CET	1976 Sep 26  1:00
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
+			 0:00	W-Eur	WE%sT	1992 Sep 27  1:00s
+			 1:00	EU	CE%sT	1996 Mar 31  1:00u
 			 0:00	EU	WE%sT
-Zone Atlantic/Azores	-1:42:40 -	LMT	1884		# Ponta Delgada
-			-1:54:32 -	HMT	1911 May 24  # Horta Mean Time
-			-2:00	Port	AZO%sT	1966 Apr  3 2:00 # Azores Time
-			-1:00	Port	AZO%sT	1983 Sep 25 1:00s
-			-1:00	W-Eur	AZO%sT	1992 Sep 27 1:00s
-			 0:00	EU	WE%sT	1993 Mar 28 1:00u
+Zone Atlantic/Azores	-1:42:40 -	LMT	1884        # Ponta Delgada
+			-1:54:32 -	HMT	1912 Jan  1 # Horta Mean Time
+			-2:00	Port	AZO%sT	1966 Apr  3  2:00  # Azores Time
+			-1:00	Port	AZO%sT	1983 Sep 25  1:00s
+			-1:00	W-Eur	AZO%sT	1992 Sep 27  1:00s
+			 0:00	EU	WE%sT	1993 Mar 28  1:00u
 			-1:00	EU	AZO%sT
-Zone Atlantic/Madeira	-1:07:36 -	LMT	1884		# Funchal
-			-1:07:36 -	FMT	1911 May 24  # Funchal Mean Time
-			-1:00	Port	MAD%sT	1966 Apr  3 2:00 # Madeira Time
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
+Zone Atlantic/Madeira	-1:07:36 -	LMT	1884        # Funchal
+			-1:07:36 -	FMT	1912 Jan  1 # Funchal Mean Time
+			-1:00	Port	MAD%sT	1966 Apr  3  2:00 # Madeira Time
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
 			 0:00	EU	WE%sT
 
 # Romania
 #
 # From Paul Eggert (1999-10-07):
-# 
-# Nine O'clock (1998-10-23) reports that the switch occurred at
+# Nine O'clock 
+# (1998-10-23) reports that the switch occurred at
 # 04:00 local time in fall 1998.  For lack of better info,
 # assume that Romania and Moldova switched to EU rules in 1997,
 # the same year as Bulgaria.
@@ -2094,32 +2117,28 @@ Rule	Romania	1991	1993	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
-			1:44:24	-	BMT	1931 Jul 24	# Bucharest MT
-			2:00	Romania	EE%sT	1981 Mar 29 2:00s
+			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
+			2:00	Romania	EE%sT	1981 Mar 29  2:00s
 			2:00	C-Eur	EE%sT	1991
 			2:00	Romania	EE%sT	1994
 			2:00	E-Eur	EE%sT	1997
 			2:00	EU	EE%sT
 
+
 # Russia
 
 # From Alexander Krivenyshev (2011-09-15):
 # Based on last Russian Government Decree # 725 on August 31, 2011
 # (Government document
-# 
 # http://www.government.ru/gov/results/16355/print/
-# 
 # in Russian)
 # there are few corrections have to be made for some Russian time zones...
 # All updated Russian Time Zones were placed in table and translated to English
 # by WorldTimeZone.com at the link below:
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
-# 
 
 # From Sanjeev Gupta (2011-09-27):
 # Scans of [Decree #23 of January 8, 1992] are available at:
-# 
 # http://government.consultant.ru/page.aspx?1223966
 # They are in Cyrillic letters (presumably Russian).
 
@@ -2128,16 +2147,12 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 # changed in September 2011:
 #
 # One source is
-# < a href="http://government.ru/gov/results/16355/>
 # http://government.ru/gov/results/16355/
-# 
 # which, according to translate.google.com, begins "Decree of August 31,
 # 2011 No 725" and contains no other dates or "effective date" information.
 #
 # Another source is
-# 
 # http://www.rg.ru/2011/09/06/chas-zona-dok.html
-# 
 # which, according to translate.google.com, begins "Resolution of the
 # Government of the Russian Federation on August 31, 2011 N 725" and also
 # contains "Date first official publication: September 6, 2011 Posted on:
@@ -2145,28 +2160,45 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 # does not contain any "effective date" information.
 #
 # Another source is
-# 
 # http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# 
 # which, in note 8, contains "Resolution #725 of August 31, 2011...
 # Effective as of after 7 days following the day of the official publication"
 # but which does not contain any reference to September 6, 2011.
 #
 # The Wikipedia article refers to
-# 
 # http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896
-# 
 # which seems to copy the text of the government.ru page.
 #
 # Tobias Conradi combines Wikipedia's
 # "as of after 7 days following the day of the official publication"
-# with www.rg.ru's "Date of first official publication: September 6, 2011" to get
-# September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias Conradi notes).
+# with www.rg.ru's "Date of first official publication: September 6, 2011" to
+# get September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias
+# Conradi notes).
 #
 # None of the sources indicates a time of day for changing clocks.
 #
 # Go with 2011-09-13 0:00s.
 
+# From Alexander Krivenyshev (2014-07-01):
+# According to the Russian news (ITAR-TASS News Agency)
+# http://en.itar-tass.com/russia/738562
+# the State Duma has approved ... the draft bill on returning to
+# winter time standard and return Russia 11 time zones.  The new
+# regulations will come into effect on October 26, 2014 at 02:00 ...
+# http://asozd2.duma.gov.ru/main.nsf/%28Spravka%29?OpenAgent&RN=431985-6&02
+# Here is a link where we put together table (based on approved Bill N
+# 431985-6) with proposed 11 Russian time zones and corresponding
+# areas/cities/administrative centers in the Russian Federation (in English):
+# http://www.worldtimezone.com/dst_news/dst_news_russia65.html
+#
+# From Alexander Krivenyshev (2014-07-22):
+# Putin signed the Federal Law 431985-6 ... (in Russian)
+# http://itar-tass.com/obschestvo/1333711
+# http://www.pravo.gov.ru:8080/page.aspx?111660
+# http://www.kremlin.ru/acts/46279
+# From October 26, 2014 the new Russian time zone map will looks like this:
+# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
+
 # From Paul Eggert (2006-03-22):
 # Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
 # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
@@ -2193,9 +2225,9 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 #
 # For Grozny, Chechnya, we have the following story from
 # John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
-# News--often false--is spread by word of mouth.  A rumor that it was
+# News - often false - is spread by word of mouth.  A rumor that it was
 # time to move the clocks back put this whole city out of sync with
-# the rest of Russia for two weeks--even soldiers stationed here began
+# the rest of Russia for two weeks - even soldiers stationed here began
 # enforcing curfew at the wrong time.
 #
 # From Gwillim Law (2001-06-05):
@@ -2206,107 +2238,265 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 # since September 1997....  Although the Kuril Islands are
 # administratively part of Sakhalin oblast', they appear to have
 # remained on UTC+11 along with Magadan.
-#
+
+# From Tim Parenti (2014-07-06):
+# The comments detailing the coverage of each Russian zone are meant to assist
+# with maintenance only and represent our best guesses as to which regions
+# are covered by each zone.  They are not meant to be taken as an authoritative
+# listing.  The region codes listed come from
+# http://en.wikipedia.org/w/?title=Federal_subjects_of_Russia&oldid=611810498
+# and are used for convenience only; no guarantees are made regarding their
+# future stability.  ISO 3166-2:RU codes are also listed for first-level
+# divisions where available.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-#
-# Kaliningradskaya oblast'.
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Kaliningrad covers...
+# 39	RU-KGD	Kaliningrad Oblast
+
 Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
 			 1:00	C-Eur	CE%sT	1945
 			 2:00	Poland	CE%sT	1946
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			 3:00	-	FET # Further-eastern European Time
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Adygeya, Arkhangel'skaya oblast',
-# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
-# Vologodskaya oblast', Voronezhskaya oblast',
-# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
-# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
-# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
-# Respublika Kareliya, Respublika Komi,
-# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
-# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
-# Respublika Mordoviya, Moskva, Moskovskaya oblast',
-# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
-# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
-# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
-# Ryazanskaya oblast', Sankt-Peterburg,
-# Respublika Severnaya Osetiya, Smolenskaya oblast',
-# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
-# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
-# Chechenskaya Respublika, Chuvashskaya oblast',
-# Yaroslavskaya oblast'
-Zone Europe/Moscow	 2:30:20 -	LMT	1880
-			 2:30	-	MMT	1916 Jul  3 # Moscow Mean Time
-			 2:30:48 Russia	%s	1919 Jul  1 2:00
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			 3:00	-	FET	2014 Oct 26  2:00s
+			 2:00	-	EET
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Moscow covers...
+# 01	RU-AD	Adygea, Republic of
+# 05	RU-DA	Dagestan, Republic of
+# 06	RU-IN	Ingushetia, Republic of
+# 07	RU-KB	Kabardino-Balkar Republic
+# 08	RU-KL	Kalmykia, Republic of
+# 09	RU-KC	Karachay-Cherkess Republic
+# 10	RU-KR	Karelia, Republic of
+# 11	RU-KO	Komi Republic
+# 12	RU-ME	Mari El Republic
+# 13	RU-MO	Mordovia, Republic of
+# 15	RU-SE	North Ossetia-Alania, Republic of
+# 16	RU-TA	Tatarstan, Republic of
+# 20	RU-CE	Chechen Republic
+# 21	RU-CU	Chuvash Republic
+# 23	RU-KDA	Krasnodar Krai
+# 26	RU-STA	Stavropol Krai
+# 29	RU-ARK	Arkhangelsk Oblast
+# 31	RU-BEL	Belgorod Oblast
+# 32	RU-BRY	Bryansk Oblast
+# 33	RU-VLA	Vladimir Oblast
+# 35	RU-VLG	Vologda Oblast
+# 36	RU-VOR	Voronezh Oblast
+# 37	RU-IVA	Ivanovo Oblast
+# 40	RU-KLU	Kaluga Oblast
+# 44	RU-KOS	Kostroma Oblast
+# 46	RU-KRS	Kursk Oblast
+# 47	RU-LEN	Leningrad Oblast
+# 48	RU-LIP	Lipetsk Oblast
+# 50	RU-MOS	Moscow Oblast
+# 51	RU-MUR	Murmansk Oblast
+# 52	RU-NIZ	Nizhny Novgorod Oblast
+# 53	RU-NGR	Novgorod Oblast
+# 57	RU-ORL	Oryol Oblast
+# 58	RU-PNZ	Penza Oblast
+# 60	RU-PSK	Pskov Oblast
+# 61	RU-ROS	Rostov Oblast
+# 62	RU-RYA	Ryazan Oblast
+# 67	RU-SMO	Smolensk Oblast
+# 68	RU-TAM	Tambov Oblast
+# 69	RU-TVE	Tver Oblast
+# 71	RU-TUL	Tula Oblast
+# 73	RU-ULY	Ulyanovsk Oblast
+# 76	RU-YAR	Yaroslavl Oblast
+# 77	RU-MOW	Moscow
+# 78	RU-SPE	Saint Petersburg
+# 83	RU-NEN	Nenets Autonomous Okrug
+
+# From Vladimir Karpinsky (2014-07-08):
+# LMT in Moscow (before Jul 3, 1916) is 2:30:17, that was defined by Moscow
+# Observatory (coordinates: 55 deg. 45'29.70", 37 deg. 34'05.30")....
+# LMT in Moscow since Jul 3, 1916 is 2:31:01 as a result of new standard.
+# (The info is from the book by Byalokoz ... p. 18.)
+# The time in St. Petersburg as capital of Russia was defined by
+# Pulkov observatory, near St. Petersburg.  In 1916 LMT Moscow
+# was synchronized with LMT St. Petersburg (+30 minutes), (Pulkov observatory
+# coordinates: 59 deg. 46'18.70", 30 deg. 19'40.70") so 30 deg. 19'40.70" >
+# 2h01m18.7s = 2:01:19.  LMT Moscow = LMT St.Petersburg + 30m 2:01:19 + 0:30 =
+# 2:31:19 ...
+#
+# From Paul Eggert (2014-07-08):
+# Milne does not list Moscow, but suggests that its time might be listed in
+# Résumés mensuels et annuels des observations météorologiques (1895).
+# Presumably this is OCLC 85825704, a journal published with parallel text in
+# Russian and French.  This source has not been located; go with Karpinsky.
+
+Zone Europe/Moscow	 2:30:17 -	LMT	1880
+			 2:30:17 -	MMT	1916 Jul  3 # Moscow Mean Time
+			 2:31:19 Russia	%s	1919 Jul  1  2:00
+			 3:00	Russia	%s	1921 Oct
 			 3:00	Russia	MSK/MSD	1922 Oct
 			 2:00	-	EET	1930 Jun 21
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
-			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
-			 4:00	-	MSK
-#
-# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
-# Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
-# but Wikipedia (2006-05-09) says +0300.  Perhaps it switched after the
-# others?  But we have no data.
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1992 Jan 19  2:00s
+			 3:00	Russia	MSK/MSD	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Simferopol covers...
+# **	****	Crimea, Republic of
+# **	****	Sevastopol
+
+Zone Europe/Simferopol	 2:16:24 -	LMT	1880
+			 2:16	-	SMT	1924 May  2 # Simferopol Mean T
+			 2:00	-	EET	1930 Jun 21
+			 3:00	-	MSK	1941 Nov
+			 1:00	C-Eur	CE%sT	1944 Apr 13
+			 3:00	Russia	MSK/MSD	1990
+			 3:00	-	MSK	1990 Jul  1  2:00
+			 2:00	-	EET	1992
+# Central Crimea used Moscow time 1994/1997.
+#
+# From Paul Eggert (2006-03-22):
+# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
+# from Kiev to Moscow time sometime after the January 1994 elections.
+# Shanks (1999) says "date of change uncertain", but implies that it happened
+# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
+# 1994-09-25 03:00, but that can't be right.  For now, guess it
+# changed in May.
+			 2:00	E-Eur	EE%sT	1994 May
+# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
+			 3:00	E-Eur	MSK/MSD	1996 Mar 31  3:00s
+			 3:00	1:00	MSD	1996 Oct 27  3:00s
+# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
+# Assume it happened in March by not changing the clocks.
+			 3:00	Russia	MSK/MSD	1997
+			 3:00	-	MSK	1997 Mar lastSun  1:00u
+# From Alexander Krivenyshev (2014-03-17):
+# time change at 2:00 (2am) on March 30, 2014
+# http://vz.ru/news/2014/3/17/677464.html
+# From Paul Eggert (2014-03-30):
+# Simferopol and Sevastopol reportedly changed their central town clocks
+# late the previous day, but this appears to have been ceremonial
+# and the discrepancies are small enough to not worry about.
+			 2:00	EU	EE%sT	2014 Mar 30  2:00
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Volgograd covers...
+# 30	RU-AST	Astrakhan Oblast
+# 34	RU-VGG	Volgograd Oblast
+# 43	RU-KIR	Kirov Oblast
+# 64	RU-SAR	Saratov Oblast
+
+# From Paul Eggert (2006-05-09):
+# Shanks & Pottenger say Kirov is still at +0400 but Wikipedia says +0300.
+# Perhaps it switched after the others?  But we have no data.
+
 Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
 			 3:00	-	TSAT	1925 Apr  6 # Tsaritsyn Time
 			 3:00	-	STAT	1930 Jun 21 # Stalingrad Time
 			 4:00	-	STAT	1961 Nov 11
-			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
-			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
-			 4:00	-	VOLT	1992 Mar 29 2:00s
-			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
-			 4:00	-	VOLT
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Samarskaya oblast', Udmyrtskaya respublika
-Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
+			 4:00	Russia	VOL%sT	1989 Mar 26  2:00s # Volgograd T
+			 3:00	Russia	VOL%sT	1991 Mar 31  2:00s
+			 4:00	-	VOLT	1992 Mar 29  2:00s
+			 3:00	Russia	MSK	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Samara covers...
+# 18	RU-UD	Udmurt Republic
+# 63	RU-SAM	Samara Oblast
+
+# Byalokoz 1919 says Samara was 3:20:20.
+
+Zone Europe/Samara	 3:20:20 -	LMT	1919 Jul  1  2:00
 			 3:00	-	SAMT	1930 Jun 21
 			 4:00	-	SAMT	1935 Jan 27
-			 4:00	Russia	KUY%sT	1989 Mar 26 2:00s # Kuybyshev
-			 3:00	Russia	KUY%sT	1991 Mar 31 2:00s
-			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
-			 3:00	-	KUYT	1991 Oct 20 3:00
-			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
-			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
+			 4:00	Russia	KUY%sT	1989 Mar 26  2:00s # Kuybyshev
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1991 Sep 29  2:00s
+			 3:00	-	KUYT	1991 Oct 20  3:00
+			 4:00	Russia	SAM%sT	2010 Mar 28  2:00s # Samara Time
+			 3:00	Russia	SAM%sT	2011 Mar 27  2:00s
 			 4:00	-	SAMT
 
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
-# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
-# Sverdlovskaya oblast', Tyumenskaya oblast',
-# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
-# Yamalo-Nenetskij avtonomnyj okrug.
-Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Yekaterinburg covers...
+# 02	RU-BA	Bashkortostan, Republic of
+# 90	RU-PER	Perm Krai
+# 45	RU-KGN	Kurgan Oblast
+# 56	RU-ORE	Orenburg Oblast
+# 66	RU-SVE	Sverdlovsk Oblast
+# 72	RU-TYU	Tyumen Oblast
+# 74	RU-CHE	Chelyabinsk Oblast
+# 86	RU-KHM	Khanty-Mansi Autonomous Okrug - Yugra
+# 89	RU-YAN	Yamalo-Nenets Autonomous Okrug
+#
+# Note: Effective 2005-12-01, (59) Perm Oblast and (81) Komi-Permyak
+# Autonomous Okrug merged to form (90, RU-PER) Perm Krai.
+
+# Milne says Yekaterinburg was 4:02:32.9; round to nearest.
+# Byalokoz 1919 says its provincial time was based on Perm, at 3:45:05.
+# Assume it switched on 1916-07-03, the time of the new standard.
+# The 1919 and 1930 transitions are from Shanks.
+
+Zone Asia/Yekaterinburg	 4:02:33 -	LMT	1916 Jul  3
+			 3:45:05 -	PMT	1919 Jul 15  4:00
 			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
-			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
-			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
-			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
-			 6:00	-	YEKT	# Yekaterinburg Time
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
-Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
-			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
-			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
-			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
-			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
-			 7:00	-	OMST
-#
+			 5:00	Russia	SVE%sT	1991 Mar 31  2:00s
+			 4:00	Russia	SVE%sT	1992 Jan 19  2:00s
+			 5:00	Russia	YEK%sT	2011 Mar 27  2:00s
+			 6:00	-	YEKT	2014 Oct 26  2:00s
+			 5:00	-	YEKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Omsk covers...
+# 04	RU-AL	Altai Republic
+# 22	RU-ALT	Altai Krai
+# 55	RU-OMS	Omsk Oblast
+
+# Byalokoz 1919 says Omsk was 4:53:30.
+
+Zone Asia/Omsk		 4:53:30 -	LMT	1919 Nov 14
+			 5:00	-	OMST	1930 Jun 21 # Omsk Time
+			 6:00	Russia	OMS%sT	1991 Mar 31  2:00s
+			 5:00	Russia	OMS%sT	1992 Jan 19  2:00s
+			 6:00	Russia	OMS%sT	2011 Mar 27  2:00s
+			 7:00	-	OMST	2014 Oct 26  2:00s
+			 6:00	-	OMST
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novosibirsk covers...
+# 54	RU-NVS	Novosibirsk Oblast
+# 70	RU-TOM	Tomsk Oblast
+
 # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
 # not clear when it switched from +7 to +6.
-# Novosibirskaya oblast', Tomskaya oblast'.
-Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
+
+Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
 			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
-			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
-			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
+			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
+			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
 			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 6:00	-	NOVT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novokuznetsk covers...
+# 42	RU-KEM	Kemerovo Oblast
 
 # From Alexander Krivenyshev (2009-10-13):
 # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
@@ -2319,14 +2509,10 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
 # time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
 #
 # Russian Government web site (Russian language)
-# 
 # http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
-# 
 # or Russian-English translation by WorldTimeZone.com with reference
 # map to local region and new Russia Time Zone map after March 28, 2010
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_russia03.html
-# 
 #
 # Thus, when Russia will switch to DST on the night of March 28, 2010
 # Kemerovo region (Kemerovo oblast') will not change the clock.
@@ -2334,152 +2520,319 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
 # As a result, Kemerovo oblast' will be in the same time zone as
 # Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
 
+# From Tim Parenti (2014-07-02), per Alexander Krivenyshev (2014-07-02):
+# The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
+# realigning itself with KRAT.
+
 Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
-
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Krasnoyarskij kraj,
-# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
-# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
-Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 7:00	-	KRAT	# Krasnoyarsk Time
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Krasnoyarsk covers...
+# 17	RU-TY	Tuva Republic
+# 19	RU-KK	Khakassia, Republic of
+# 24	RU-KYA	Krasnoyarsk Krai
+#
+# Note: Effective 2007-01-01, (88) Evenk Autonomous Okrug and (84) Taymyr
+# Autonomous Okrug were merged into (24, RU-KYA) Krasnoyarsk Krai.
+
+# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
+
+Zone Asia/Krasnoyarsk	 6:11:26 -	LMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
-			 8:00	-	KRAT
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Buryatiya, Irkutskaya oblast',
-# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
-Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
-			 6:57:20 -	IMT	1920 Jan 25 # Irkutsk Mean Time
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2011 Mar 27  2:00s
+			 8:00	-	KRAT	2014 Oct 26  2:00s
+			 7:00	-	KRAT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Irkutsk covers...
+# 03	RU-BU	Buryatia, Republic of
+# 38	RU-IRK	Irkutsk Oblast
+#
+# Note: Effective 2008-01-01, (85) Ust-Orda Buryat Autonomous Okrug was
+# merged into (38, RU-IRK) Irkutsk Oblast.
+
+# Milne 1899 says Irkutsk was 6:57:15.
+# Byalokoz 1919 says Irkutsk was 6:57:05.
+# Go with Byalokoz.
+
+Zone Asia/Irkutsk	 6:57:05 -	LMT	1880
+			 6:57:05 -	IMT	1920 Jan 25 # Irkutsk Mean Time
 			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
-			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
-			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
-			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
-			 9:00	-	IRKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
-# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
-
-# From Oscar van Vlijmen (2009-11-29):
-# ...some regions of [Russia] were merged with others since 2005...
-# Some names were changed, no big deal, except for one instance: a new name.
-# YAK/YAKST: UTC+9 Zabajkal'skij kraj.
-
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
-# Verkhnevilyujskij, Vilyujskij, Gornyj,
-# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
-# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij,
-# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
-# Churapchinskij, Eveno-Bytantajskij Natsional'nij.
-
-Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
+			 8:00	Russia	IRK%sT	1991 Mar 31  2:00s
+			 7:00	Russia	IRK%sT	1992 Jan 19  2:00s
+			 8:00	Russia	IRK%sT	2011 Mar 27  2:00s
+			 9:00	-	IRKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Chita covers...
+# 92	RU-ZAB	Zabaykalsky Krai
+#
+# Note: Effective 2008-03-01, (75) Chita Oblast and (80) Agin-Buryat
+# Autonomous Okrug merged to form (92, RU-ZAB) Zabaykalsky Krai.
+
+Zone Asia/Chita	 7:33:52 -	LMT	1919 Dec 15
+			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Yakutsk covers...
+# 28	RU-AMU	Amur Oblast
+#
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-02	****	Aldansky District
+# 14-04	****	Amginsky District
+# 14-05	****	Anabarsky District
+# 14-06	****	Bulunsky District
+# 14-07	****	Verkhnevilyuysky District
+# 14-10	****	Vilyuysky District
+# 14-11	****	Gorny District
+# 14-12	****	Zhigansky District
+# 14-13	****	Kobyaysky District
+# 14-14	****	Lensky District
+# 14-15	****	Megino-Kangalassky District
+# 14-16	****	Mirninsky District
+# 14-18	****	Namsky District
+# 14-19	****	Neryungrinsky District
+# 14-21	****	Nyurbinsky District
+# 14-23	****	Olenyoksky District
+# 14-24	****	Olyokminsky District
+# 14-26	****	Suntarsky District
+# 14-27	****	Tattinsky District
+# 14-29	****	Ust-Aldansky District
+# 14-32	****	Khangalassky District
+# 14-33	****	Churapchinsky District
+# 14-34	****	Eveno-Bytantaysky National District
+
+# From Tim Parenti (2014-07-03):
+# Our commentary seems to have lost mention of (14-19) Neryungrinsky District.
+# Since the surrounding districts of Sakha are all YAKT, assume this is, too.
+# Also assume its history has been the same as the rest of Asia/Yakutsk.
+
+# Byalokoz 1919 says Yakutsk was 8:38:58.
+
+Zone Asia/Yakutsk	 8:38:58 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
-			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
-			 10:00	-	YAKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
-# [parts of] Respublika Sakha (Yakutiya).
-
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
-Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Vladivostok covers...
+# 25	RU-PRI	Primorsky Krai
+# 27	RU-KHA	Khabarovsk Krai
+# 79	RU-YEV	Jewish Autonomous Oblast
+#
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-09	****	Verkhoyansky District
+# 14-31	****	Ust-Yansky District
+
+# Milne 1899 says Vladivostok was 8:47:33.5.
+# Byalokoz 1919 says Vladivostok was 8:47:31.
+# Go with Byalokoz.
+
+Zone Asia/Vladivostok	 8:47:31 -	LMT	1922 Nov 15
 			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
-			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
-			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT
+			10:00	Russia	VLA%sT	1991 Mar 31  2:00s
+			 9:00	Russia	VLA%sT	1992 Jan 19  2:00s
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Khandyga covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-28	****	Tomponsky District
+# 14-30	****	Ust-Maysky District
 
 # From Arthur David Olson (2012-05-09):
 # Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time
 # in 2011.
-#
+
 # From Paul Eggert (2012-11-25):
 # Shanks and Pottenger (2003) has Khandyga on Yakutsk time.
 # Make a wild guess that it switched to Vladivostok time in 2004.
 # This transition is no doubt wrong, but we have no better info.
-#
+
 Zone Asia/Khandyga	 9:02:13 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
 			 9:00	Russia	YAK%sT	2004
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT	2011 Sep 13 0:00s # Decree 725?
-			10:00	-	YAKT
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2011 Sep 13  0:00s # Decree 725?
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
 
-#
-# Sakhalinskaya oblast'.
-# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
+
+# From Tim Parenti (2014-07-03):
+# Asia/Sakhalin covers...
+# 65	RU-SAK	Sakhalin Oblast
+# ...with the exception of:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
 Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
-			 9:00	-	CJT	1938
+			 9:00	-	JCST	1937 Oct  1
 			 9:00	-	JST	1945 Aug 25
-			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
-			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
-			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
-			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
-			11:00	-	SAKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Magadanskaya oblast', Respublika Sakha (Yakutiya).
-# Probably also: Kuril Islands.
-
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
-# Nizhnekolymskij, ... Srednekolymskij.
+			11:00	Russia	SAK%sT	1991 Mar 31  2:00s # Sakhalin T
+			10:00	Russia	SAK%sT	1992 Jan 19  2:00s
+			11:00	Russia	SAK%sT	1997 Mar lastSun  2:00s
+			10:00	Russia	SAK%sT	2011 Mar 27  2:00s
+			11:00	-	SAKT	2014 Oct 26  2:00s
+			10:00	-	SAKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Magadan covers...
+# 49	RU-MAG	Magadan Oblast
+
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# Magadan Oblast is moving from UTC+12 to UTC+10 on 2014-10-26; however,
+# several districts of Sakha Republic as well as Severo-Kurilsky District of
+# the Sakhalin Oblast (also known as the North Kuril Islands), represented
+# until now by Asia/Magadan, will instead move to UTC+11.  These regions will
+# need their own zone.
+
 Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
 			10:00	-	MAGT	1930 Jun 21 # Magadan Time
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			10:00	-	MAGT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Srednekolymsk covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-01	****	Abyysky District
+# 14-03	****	Allaikhovsky District
+# 14-08	****	Verkhnekolymsky District
+# 14-17	****	Momsky District
+# 14-20	****	Nizhnekolymsky District
+# 14-25	****	Srednekolymsky District
+#
+# ...and parts of (65, RU-SAK) Sakhalin Oblast:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# From Tim Parenti (2014-07-02):
+# Oymyakonsky District of Sakha Republic (represented by Ust-Nera), along with
+# most of Sakhalin Oblast (represented by Sakhalin) will be moving to UTC+10 on
+# 2014-10-26 to stay aligned with VLAT/SAKT; however, Severo-Kurilsky District
+# of the Sakhalin Oblast (also known as the North Kuril Islands, represented by
+# Severo-Kurilsk) will remain on UTC+11.
+
+# From Tim Parenti (2014-07-06):
+# Assume North Kuril Islands have history like Magadan before 2011-03-27.
+# There is a decent chance this is wrong, in which case a new zone
+# Asia/Severo-Kurilsk would become necessary.
+#
+# Srednekolymsk and Zyryanka are the most populous places amongst these
+# districts, but have very similar populations.  In fact, Wikipedia currently
+# lists them both as having 3528 people, exactly 1668 males and 1860 females
+# each!  (Yikes!)
+# http://en.wikipedia.org/w/?title=Srednekolymsky_District&oldid=603435276
+# http://en.wikipedia.org/w/?title=Verkhnekolymsky_District&oldid=594378493
+# Assume this is a mistake, albeit an amusing one.
+#
+# Looking at censuses, the populations of the two municipalities seem to have
+# fluctuated recently.  Zyryanka was more populous than Srednekolymsk in the
+# 1989 and 2002 censuses, but Srednekolymsk was more populous in the most
+# recent (2010) census, 3525 to 3170.  (See pages 195 and 197 of
+# http://www.gks.ru/free_doc/new_site/perepis2010/croc/Documents/Vol1/pub-01-05.pdf
+# in Russian.)  In addition, Srednekolymsk appears to be a much older
+# settlement and the population of Zyryanka seems to be declining.
+# Go with Srednekolymsk.
+#
+# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
+# as the abbreviation.  Use SRET instead.
+
+Zone Asia/Srednekolymsk	10:14:52 -	LMT	1924 May  2
+			10:00	-	MAGT	1930 Jun 21 # Magadan Time
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			11:00	-	SRET	# Srednekolymsk Time
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Ust-Nera covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-22	****	Oymyakonsky District
 
 # From Arthur David Olson (2012-05-09):
-# Ojmyakonskij and the Kuril Islands switched from
+# Ojmyakonskij [and the Kuril Islands] switched from
 # Magadan time to Vladivostok time in 2011.
+#
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# It's unlikely that any of the Kuril Islands were involved in such a switch,
+# as the South and Middle Kurils have been on UTC+11 (SAKT) with the rest of
+# Sakhalin Oblast since at least 2011-09, and the North Kurils have been on
+# UTC+12 since at least then, too.
+
 Zone Asia/Ust-Nera	 9:32:54 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
 			 9:00	Russia	YAKT	1981 Apr  1
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT	2011 Sep 13 0:00s # Decree 725?
-			11:00	-	VLAT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2011 Sep 13  0:00s # Decree 725?
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
 
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Kamchatka covers...
+# 91	RU-KAM	Kamchatka Krai
 #
-# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
+# Note: Effective 2007-07-01, (41) Kamchatka Oblast and (82) Koryak
+# Autonomous Okrug merged to form (91, RU-KAM) Kamchatka Krai.
+
+# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
+# Asia/Petropavlovsk-Kamchatsky, but these are too long.
 Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
 			11:00	-	PETT	1930 Jun 21 # P-K Time
-			12:00	Russia	PET%sT	1991 Mar 31 2:00s
-			11:00	Russia	PET%sT	1992 Jan 19 2:00s
-			12:00	Russia	PET%sT	2010 Mar 28 2:00s
-			11:00	Russia	PET%sT	2011 Mar 27 2:00s
+			12:00	Russia	PET%sT	1991 Mar 31  2:00s
+			11:00	Russia	PET%sT	1992 Jan 19  2:00s
+			12:00	Russia	PET%sT	2010 Mar 28  2:00s
+			11:00	Russia	PET%sT	2011 Mar 27  2:00s
 			12:00	-	PETT
-#
-# Chukotskij avtonomnyj okrug
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Anadyr covers...
+# 87	RU-CHU	Chukotka Autonomous Okrug
+
 Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 			12:00	-	ANAT	1930 Jun 21 # Anadyr Time
-			13:00	Russia	ANA%sT	1982 Apr  1 0:00s
-			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
-			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
-			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
-			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
+			13:00	Russia	ANA%sT	1982 Apr  1  0:00s
+			12:00	Russia	ANA%sT	1991 Mar 31  2:00s
+			11:00	Russia	ANA%sT	1992 Jan 19  2:00s
+			12:00	Russia	ANA%sT	2010 Mar 28  2:00s
+			11:00	Russia	ANA%sT	2011 Mar 27  2:00s
 			12:00	-	ANAT
 
+
 # San Marino
 # See Europe/Rome.
 
@@ -2488,11 +2841,11 @@ Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 Zone	Europe/Belgrade	1:22:00	-	LMT	1884
 			1:00	-	CET	1941 Apr 18 23:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 May 8 2:00s
+			1:00	-	CET	1945 May  8  2:00s
 			1:00	1:00	CEST	1945 Sep 16  2:00s
-# Metod Kozelj reports that the legal date of
+# Metod Koželj reports that the legal date of
 # transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
-# Shanks & Pottenger don't give as much detail, so go with Kozelj.
+# Shanks & Pottenger don't give as much detail, so go with Koželj.
 			1:00	-	CET	1982 Nov 27
 			1:00	EU	CE%sT
 Link Europe/Belgrade Europe/Ljubljana	# Slovenia
@@ -2568,13 +2921,13 @@ Zone	Africa/Ceuta	-0:21:16 -	LMT	1901
 			 0:00	1:00	WEST	1918 Oct  7 23:00
 			 0:00	-	WET	1924
 			 0:00	Spain	WE%sT	1929
-			 0:00 SpainAfrica WE%sT 1984 Mar 16
+			 0:00 SpainAfrica WE%sT	1984 Mar 16
 			 1:00	-	CET	1986
 			 1:00	EU	CE%sT
 Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
-			-1:00	-	CANT	1946 Sep 30 1:00 # Canaries Time
-			 0:00	-	WET	1980 Apr  6 0:00s
-			 0:00	1:00	WEST	1980 Sep 28 0:00s
+			-1:00	-	CANT	1946 Sep 30  1:00 # Canaries T
+			 0:00	-	WET	1980 Apr  6  0:00s
+			 0:00	1:00	WEST	1980 Sep 28  0:00s
 			 0:00	EU	WE%sT
 # IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
 # Ignore this for now, as the Canaries are part of the EU.
@@ -2583,7 +2936,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 
 # From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
 #
-# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
+# The law "Svensk författningssamling 1878, no 14" about standard time in 1879:
 # From the beginning of 1879 (that is 01-01 00:00) the time for all
 # places in the country is "the mean solar time for the meridian at
 # three degrees, or twelve minutes of time, to the west of the
@@ -2594,7 +2947,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 # national standard time as 01:00:14 ahead of GMT....
 #
 # About the beginning of CET in Sweden. The lawtext ("Svensk
-# forfattningssamling 1899, no 44") states, that "from the beginning
+# författningssamling 1899, no 44") states, that "from the beginning
 # of 1900... ... the same as the mean solar time for the meridian at
 # the distance of one hour of time from the meridian of the English
 # observatory at Greenwich, or at 12 minutes 14 seconds to the west
@@ -2602,7 +2955,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 # 1899-06-16.  In short: At 1900-01-01 00:00:00 the new standard time
 # in Sweden is 01:00:00 ahead of GMT.
 #
-# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
+# 1916: The lawtext ("Svensk författningssamling 1916, no 124") states
 # that "1916-05-15 is considered to begin one hour earlier". It is
 # pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
 # Further the law says, that "1916-09-30 is considered to end one hour later".
@@ -2612,7 +2965,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 # not available on the site (to my knowledge they are only available
 # in Swedish):  (type
 # "sommartid" without the quotes in the field "Fritext" and then click
-# the Sok-button).
+# the Sök-button).
 #
 # (2001-05-13):
 #
@@ -2627,9 +2980,9 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
-			1:00:14	-	SET	1900 Jan  1	# Swedish Time
+			1:00:14	-	SET	1900 Jan  1 # Swedish Time
 			1:00	-	CET	1916 May 14 23:00
-			1:00	1:00	CEST	1916 Oct  1 01:00
+			1:00	1:00	CEST	1916 Oct  1  1:00
 			1:00	-	CET	1980
 			1:00	EU	CE%sT
 
@@ -2637,7 +2990,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # From Howse:
 # By the end of the 18th century clocks and watches became commonplace
 # and their performance improved enormously.  Communities began to keep
-# mean time in preference to apparent time -- Geneva from 1780 ....
+# mean time in preference to apparent time - Geneva from 1780 ....
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 # From Whitman (who writes "Midnight?"):
 # Rule	Swiss	1940	only	-	Nov	 2	0:00	1:00	S
@@ -2653,7 +3006,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # to be wrong. This is now verified.
 #
 # I have found copies of the original ruling by the Swiss Federal
-# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss
+# government, in 'Eidgenössische Gesetzessammlung 1941 and 1942' (Swiss
 # federal law collection)...
 #
 # DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am
@@ -2672,7 +3025,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # night as an absolute novelty, because this was the first time that such
 # a thing had happened in Switzerland.
 #
-# I have also checked 1916, because one book source (Gabriel, Traite de
+# I have also checked 1916, because one book source (Gabriel, Traité de
 # l'heure dans le monde) claims that Switzerland had DST in 1916. This is
 # false, no official document could be found. Probably Gabriel got misled
 # by references to Germany, which introduced DST in 1916 for the first time.
@@ -2686,19 +3039,19 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # One further detail for Switzerland, which is probably out of scope for
 # most users of tzdata: The [Europe/Zurich zone] ...
 # describes all of Switzerland correctly, with the exception of
-# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not
+# the Canton de Genève (Geneva, Genf). Between 1848 and 1894 Geneva did not
 # follow Bern Mean Time but kept its own local mean time.
 # To represent this, an extra zone would be needed.
 #
 # From Alois Treindl (2013-09-11):
 # The Federal regulations say
 # http://www.admin.ch/opc/de/classified-compilation/20071096/index.html
-# ... the meridian for Bern mean time ... is 7 degrees 26'22.50".
+# ... the meridian for Bern mean time ... is 7 degrees 26' 22.50".
 # Expressed in time, it is 0h29m45.5s.
 
 # From Pierre-Yves Berger (2013-09-11):
-# the "Circulaire du conseil federal" (December 11 1893)
-#  ...
+# the "Circulaire du conseil fédéral" (December 11 1893)
+# http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353
 # clearly states that the [1894-06-01] change should be done at midnight
 # but if no one is present after 11 at night, could be postponed until one
 # hour before the beginning of service.
@@ -2709,14 +3062,14 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # We can find no reliable source for Shanks's assertion that all of Switzerland
 # except Geneva switched to Bern Mean Time at 00:00 on 1848-09-12.  This book:
 #
-#	Jakob Messerli. Gleichmassig, punktlich, schnell: Zeiteinteilung und
+#	Jakob Messerli. Gleichmässig, pünktlich, schnell. Zeiteinteilung und
 #	Zeitgebrauch in der Schweiz im 19. Jahrhundert. Chronos, Zurich 1995,
 #	ISBN 3-905311-68-2, OCLC 717570797.
 #
 # suggests that the transition was more gradual, and that the Swiss did not
 # agree about civil time during the transition.  The timekeeping it gives the
 # most detail for is postal and telegraph time: here, federal legislation (the
-# "Bundesgesetz uber die Erstellung von elektrischen Telegraphen") passed on
+# "Bundesgesetz über die Erstellung von elektrischen Telegraphen") passed on
 # 1851-11-23, and an official implementation notice was published 1853-07-16
 # (Bundesblatt 1853, Bd. II, S. 859).  On p 72 Messerli writes that in
 # practice since July 1853 Bernese time was used in "all postal and telegraph
@@ -2730,7 +3083,7 @@ Rule	Swiss	1941	1942	-	May	Mon>=1	1:00	1:00	S
 Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
-			0:29:46	-	BMT	1894 Jun # Bern Mean Time
+			0:29:46	-	BMT	1894 Jun    # Bern Mean Time
 			1:00	Swiss	CE%sT	1981
 			1:00	EU	CE%sT
 
@@ -2738,7 +3091,7 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 
 # From Amar Devegowda (2007-01-03):
 # The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at -
+# ... The latest rules are available at:
 # http://www.timeanddate.com/worldclock/timezone.html?n=107
 # From Steffen Thorsen (2007-01-03):
 # I have been able to find press records back to 1996 which all say that
@@ -2763,8 +3116,7 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 # (on a non-government server though) describing dates between 2002 and 2006:
 # http://www.alomaliye.com/bkk_2002_3769.htm
 
-# From Gökdeniz Karadağ (2011-03-10):
-#
+# From Gökdeniz Karadağ (2011-03-10):
 # According to the articles linked below, Turkey will change into summer
 # time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
 # This change is due to a nationwide exam on 27th.
@@ -2777,9 +3129,16 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 # Turkish Local election....
 # http://www.sabah.com.tr/Ekonomi/2014/02/12/yaz-saatinde-onemli-degisiklik
 # ... so Turkey will move clocks forward one hour on March 31 at 3:00 a.m.
-# From Paul Eggert (2014-02-17):
-# Here is an English-language source:
-# http://www.worldbulletin.net/turkey/129016/turkey-switches-to-daylight-saving-time-march-31
+# From Randal L. Schwartz (2014-04-15):
+# Having landed on a flight from the states to Istanbul (via AMS) on March 31,
+# I can tell you that NOBODY (even the airlines) respected this timezone DST
+# change delay.  Maybe the word just didn't get out in time.
+# From Paul Eggert (2014-06-15):
+# The press reported massive confusion, as election officials obeyed the rule
+# change but cell phones (and airline baggage systems) did not.  See:
+# Kostidis M. Eventful elections in Turkey. Balkan News Agency
+# http://www.balkaneu.com/eventful-elections-turkey/ 2014-03-30.
+# I guess the best we can do is document the official time.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Turkey	1916	only	-	May	 1	0:00	1:00	S
@@ -2846,10 +3205,10 @@ Zone	Europe/Istanbul	1:55:52 -	LMT	1880
 			2:00	Turkey	EE%sT	1978 Oct 15
 			3:00	Turkey	TR%sT	1985 Apr 20 # Turkey Time
 			2:00	Turkey	EE%sT	2007
-			2:00	EU	EE%sT	2011 Mar 27 1:00u
-			2:00	-	EET	2011 Mar 28 1:00u
-			2:00	EU	EE%sT	2014 Mar 30 1:00u
-			2:00	-	EET	2014 Mar 31 1:00u
+			2:00	EU	EE%sT	2011 Mar 27  1:00u
+			2:00	-	EET	2011 Mar 28  1:00u
+			2:00	EU	EE%sT	2014 Mar 30  1:00u
+			2:00	-	EET	2014 Mar 31  1:00u
 			2:00	EU	EE%sT
 Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
 
@@ -2870,7 +3229,7 @@ Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
 # Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
 # approval from 266 deputies.
 #
-# Ukraine abolishes transter back to the winter time (in Russian)
+# Ukraine abolishes transfer back to the winter time (in Russian)
 # http://news.mail.ru/politics/6861560/
 #
 # The Ukrainians will no longer change the clock (in Russian)
@@ -2931,12 +3290,12 @@ Zone Europe/Kiev	2:02:04 -	LMT	1880
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Sep 20
 			1:00	C-Eur	CE%sT	1943 Nov  6
-			3:00	Russia	MSK/MSD	1990 Jul  1 2:00
-			2:00	1:00	EEST	1991 Sep 29 3:00
+			3:00	Russia	MSK/MSD	1990 Jul  1  2:00
+			2:00	1:00	EEST	1991 Sep 29  3:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
 # Ruthenia used CET 1990/1991.
-# "Uzhhorod" is the transliteration of the Ukrainian name, but
+# "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but
 # "Uzhgorod" is more common in English.
 Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
 			1:00	-	CET	1940
@@ -2944,8 +3303,8 @@ Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
 			1:00	1:00	CEST	1944 Oct 26
 			1:00	-	CET	1945 Jun 29
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			1:00	-	CET	1991 Mar 31 3:00
+			3:00	-	MSK	1990 Jul  1  2:00
+			1:00	-	CET	1991 Mar 31  3:00
 			2:00	-	EET	1992
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
@@ -2959,42 +3318,9 @@ Zone Europe/Zaporozhye	2:20:40 -	LMT	1880
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Aug 25
 			1:00	C-Eur	CE%sT	1943 Oct 25
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
-# Central Crimea used Moscow time 1994/1997.
-Zone Europe/Simferopol	2:16:24 -	LMT	1880
-			2:16	-	SMT	1924 May  2 # Simferopol Mean T
-			2:00	-	EET	1930 Jun 21
-			3:00	-	MSK	1941 Nov
-			1:00	C-Eur	CE%sT	1944 Apr 13
-			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			2:00	-	EET	1992
-# From Paul Eggert (2006-03-22):
-# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
-# from Kiev to Moscow time sometime after the January 1994 elections.
-# Shanks (1999) says "date of change uncertain", but implies that it happened
-# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
-# 1994-09-25 03:00, but that can't be right.  For now, guess it
-# changed in May.
-			2:00	E-Eur	EE%sT	1994 May
-# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
-			3:00	E-Eur	MSK/MSD	1996 Mar 31 3:00s
-			3:00	1:00	MSD	1996 Oct 27 3:00s
-# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
-# Assume it happened in March by not changing the clocks.
-			3:00	Russia	MSK/MSD	1997
-			3:00	-	MSK	1997 Mar lastSun 1:00u
-# From Alexander Krivenyshev (2014-03-17):
-# time change at 2:00 (2am) on March 30, 2014
-# http://vz.ru/news/2014/3/17/677464.html
-# From Paul Eggert (2014-03-30):
-# Simferopol and Sevastopol reportedly changed their central town clocks
-# late the previous day, but this appears to have been ceremonial
-# and the discrepancies are small enough to not worry about.
-			2:00	EU	EE%sT	2014 Mar 30 2:00
-			4:00	-	MSK
 
 # Vatican City
 # See Europe/Rome.
@@ -3018,7 +3344,7 @@ Zone Europe/Simferopol	2:16:24 -	LMT	1880
 # ...
 #
 # ...the European time rules are...standardized since 1981, when
-# most European coun[tr]ies started DST.  Before that year, only
+# most European countries started DST.  Before that year, only
 # a few countries (UK, France, Italy) had DST, each according
 # to own national rules.  In 1981, however, DST started on
 # 'Apr firstSun', and not on 'Mar lastSun' as in the following
@@ -3026,7 +3352,7 @@ Zone Europe/Simferopol	2:16:24 -	LMT	1880
 # But also since 1981 there are some more national exceptions
 # than listed in 'europe': Switzerland, for example, joined DST
 # one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
-# lastSun' in 1981---I don't know how they handle now.
+# lastSun' in 1981 - I don't know how they handle now.
 #
 # Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
 # Soviet Union (as far as I know).
diff --git a/make/data/tzdata/factory b/make/data/tzdata/factory
index 813d99a1f1f95d0ff89095a2abd446b190872cb1..0a6041db07e8c0751f5c2d01bd4049035ffc9145 100644
--- a/make/data/tzdata/factory
+++ b/make/data/tzdata/factory
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
diff --git a/make/data/tzdata/iso3166.tab b/make/data/tzdata/iso3166.tab
index 28fb64b647ef58ff9919ca184a0590b464adcdf7..63eadcbd0c512e0bd6239151370160d3b8deab57 100644
--- a/make/data/tzdata/iso3166.tab
+++ b/make/data/tzdata/iso3166.tab
@@ -26,21 +26,21 @@
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-05-27):
+# From Paul Eggert (2014-07-18):
+# This file contains a table of two-letter country codes.  Columns are
+# separated by a single tab.  Lines beginning with '#' are comments.
+# Although all text currently uses ASCII encoding, this is planned to
+# change to UTF-8 soon.  The columns of the table are as follows:
 #
-# This file contains a table with the following columns:
 # 1.  ISO 3166-1 alpha-2 country code, current as of
-#     ISO 3166-1 Newsletter VI-15 (2013-05-10).  See: Updates on ISO 3166
+#     ISO 3166-1 Newsletter VI-16 (2013-07-11).  See: Updates on ISO 3166
 #   http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm
 # 2.  The usual English name for the coded region,
 #     chosen so that alphabetic sorting of subsets produces helpful lists.
 #     This is not the same as the English name in the ISO 3166 tables.
 #
-# Columns are separated by a single tab.
 # The table is sorted by country code.
 #
-# Lines beginning with `#' are comments.
-#
 # This table is intended as an aid for users, to help them select time
 # zone data appropriate for their practical needs.  It is not intended
 # to take or endorse any position on legal or territorial claims.
diff --git a/make/data/tzdata/leapseconds b/make/data/tzdata/leapseconds
index b423135b942d092c4a8f24eaac19f3c8db1bf021..d38abd6a4bdde8dd16998d1ea03bc131438fe08f 100644
--- a/make/data/tzdata/leapseconds
+++ b/make/data/tzdata/leapseconds
@@ -21,7 +21,7 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# Allowance for leapseconds added to each timezone file.
+# Allowance for leap seconds added to each time zone file.
 
 # This file is in the public domain.
 
@@ -31,7 +31,7 @@
 # you should be able to pick up leap-seconds.list from a secondary NIST server.
 # For more about leap-seconds.list, please see
 # The NTP Timescale and Leap Seconds
-# .
+# http://www.eecis.udel.edu/~mills/leap.html
 
 # The International Earth Rotation Service periodically uses leap seconds
 # to keep UTC to within 0.9 s of UT1
diff --git a/make/data/tzdata/northamerica b/make/data/tzdata/northamerica
index dc0c2e92cff499a8a1c53d2ce2be86ec84465c2c..0dc714aa92d9cd3b7d59128c1074eeb53ec01f67 100644
--- a/make/data/tzdata/northamerica
+++ b/make/data/tzdata/northamerica
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # also includes Central America and the Caribbean
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (1999-03-22):
 # A reliable and entertaining source about time zones is
@@ -78,13 +78,13 @@
 #	to push people into bed earlier, and get them up earlier, to make
 #	them healthy, wealthy and wise in spite of themselves.
 #
-#	-- Robertson Davies, The diary of Samuel Marchbanks,
+#	 -- Robertson Davies, The diary of Samuel Marchbanks,
 #	   Clarke, Irwin (1947), XIX, Sunday
 #
 # For more about the first ten years of DST in the United States, see
-# Robert Garland's 
-# Ten years of daylight saving from the Pittsburgh standpoint
-# (Carnegie Library of Pittsburgh, 1927).
+# Robert Garland, Ten years of daylight saving from the Pittsburgh standpoint
+# (Carnegie Library of Pittsburgh, 1927).
+# http://www.clpgh.org/exhibit/dst.html
 #
 # Shanks says that DST was called "War Time" in the US in 1918 and 1919.
 # However, DST was imposed by the Standard Time Act of 1918, which
@@ -103,11 +103,11 @@
 # From Arthur David Olson (2000-09-25):
 # Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
 # In the introduction, Oboler spoke of "Eastern Peace Time."
-# An AltaVista search turned up
-# :
+# An AltaVista search turned up:
+# http://rowayton.org/rhs/hstaug45.html
 # "When the time is announced over the radio now, it is 'Eastern Peace
 # Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
-#  (August 1945) by way of confirmation.
+# (August 1945) by way of confirmation.
 
 # From Joseph Gallant citing
 # George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
@@ -205,7 +205,7 @@ Zone	PST8PDT		 -8:00	US	P%sT
 # USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
 # USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
 # USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
-# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
+# USA    "           9 H  BEHIND UTC    APR 3 - OCT 30
 # USA  HAWAII       10 H  BEHIND UTC
 # USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
 
@@ -258,19 +258,19 @@ Zone	PST8PDT		 -8:00	US	P%sT
 # The following was signed into law on 2005-08-08.
 #
 # H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
-#   (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
+#   (a) Amendment.--Section 3(a) of the Uniform Time Act of 1966 (15
 #   U.S.C. 260a(a)) is amended--
-#     (1) by striking 'first Sunday of April' and inserting 'second
-#     Sunday of March'; and
-#     (2) by striking 'last Sunday of October' and inserting 'first
+#     (1) by striking "first Sunday of April" and inserting "second
+#     Sunday of March"; and
+#     (2) by striking "last Sunday of October" and inserting "first
 #     Sunday of November'.
-#   (b) Effective Date- Subsection (a) shall take effect 1 year after the
+#   (b) Effective Date.--Subsection (a) shall take effect 1 year after the
 #   date of enactment of this Act or March 1, 2007, whichever is later.
-#   (c) Report to Congress- Not later than 9 months after the effective
+#   (c) Report to Congress.--Not later than 9 months after the effective
 #   date stated in subsection (b), the Secretary shall report to Congress
 #   on the impact of this section on energy consumption in the United
 #   States.
-#   (d) Right to Revert- Congress retains the right to revert the
+#   (d) Right to Revert.--Congress retains the right to revert the
 #   Daylight Saving Time back to the 2005 time schedules once the
 #   Department study is complete.
 
@@ -292,7 +292,7 @@ Zone	PST8PDT		 -8:00	US	P%sT
 
 # From Paul Eggert (2005-08-26):
 # According to today's Huntsville Times
-# 
+# http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1
 # a few towns on Alabama's "eastern border with Georgia, such as Phenix City
 # in Russell County, Lanett in Chambers County and some towns in Lee County,
 # set their watches and clocks on Eastern time."  It quotes H.H. "Bubba"
@@ -347,15 +347,15 @@ Rule	Chicago	1955	1966	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
 			-6:00	US	C%sT	1920
-			-6:00	Chicago	C%sT	1936 Mar  1 2:00
-			-5:00	-	EST	1936 Nov 15 2:00
+			-6:00	Chicago	C%sT	1936 Mar  1  2:00
+			-5:00	-	EST	1936 Nov 15  2:00
 			-6:00	Chicago	C%sT	1942
 			-6:00	US	C%sT	1946
 			-6:00	Chicago	C%sT	1967
 			-6:00	US	C%sT
 # Oliver County, ND switched from mountain to central time on 1992-10-25.
 Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
-			-7:00	US	M%sT	1992 Oct 25 02:00
+			-7:00	US	M%sT	1992 Oct 25  2:00
 			-6:00	US	C%sT
 # Morton County, ND, switched from mountain to central time on
 # 2003-10-26, except for the area around Mandan which was already central time.
@@ -364,29 +364,26 @@ Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
 # Jones, Mellette, and Todd Counties in South Dakota;
 # but in practice these other counties were already observing central time.
 # See .
-Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
-			-7:00	US	M%sT	2003 Oct 26 02:00
+Zone America/North_Dakota/New_Salem -6:45:39 - LMT	1883 Nov 18 12:14:21
+			-7:00	US	M%sT	2003 Oct 26  2:00
 			-6:00	US	C%sT
 
 # From Josh Findley (2011-01-21):
 # ...it appears that Mercer County, North Dakota, changed from the
 # mountain time zone to the central time zone at the last transition from
 # daylight-saving to standard time (on Nov. 7, 2010):
-# 
 # http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm
-# 
-# 
 # http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html
-# 
 
 # From Andy Lipscomb (2011-01-24):
 # ...according to the Census Bureau, the largest city is Beulah (although
 # it's commonly referred to as Beulah-Hazen, with Hazen being the next
 # largest city in Mercer County).  Google Maps places Beulah's city hall
-# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07".
+# at 47 degrees 15' 51" N, 101 degrees 46' 40" W, which yields an offset
+# of 6h47'07".
 
-Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53
-			-7:00	US	M%sT	2010 Nov  7 2:00
+Zone America/North_Dakota/Beulah -6:47:07 - LMT	1883 Nov 18 12:12:53
+			-7:00	US	M%sT	2010 Nov  7  2:00
 			-6:00	US	C%sT
 
 # US mountain time, represented by Denver
@@ -448,15 +445,18 @@ Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
 # was destroyed in 1805 by a Yakutat-kon war party.)  However, there
 # were nearby inhabitants in some cases and for our purposes perhaps
 # it's best to simply use the official transition.
-#
 
-# From Steve Ferguson (2011-01-31):
-# The author lives in Alaska and many of the references listed are only
-# available to Alaskan residents.
+# From Paul Eggert (2014-07-18):
+# One opinion of the early-1980s turmoil in Alaska over time zones and
+# daylight saving time appeared as graffiti on a Juneau airport wall:
+# "Welcome to Juneau.  Please turn your watch back to the 19th century."
+# See: Turner W. Alaska's four time zones now two. NY Times 1983-11-01.
+# http://www.nytimes.com/1983/11/01/us/alaska-s-four-time-zones-now-two.html
 #
-# 
-# http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98
-# 
+# Steve Ferguson (2011-01-31) referred to the following source:
+# Norris F. Keeping time in Alaska: national directives, local response.
+# Alaska History 2001;16(1-2).
+# http://alaskahistoricalsociety.org/discover-alaska/glimpses-of-the-past/keeping-time-in-alaska/
 
 # From Arthur David Olson (2011-02-01):
 # Here's database-relevant material from the 2001 "Alaska History" article:
@@ -482,12 +482,10 @@ Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
 # From Arthur David Olson (2011-02-09):
 # I just spoke by phone with a staff member at the Metlakatla Indian
 # Community office (using contact information available at
-# 
 # http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla
-# ).
 # It's shortly after 1:00 here on the east coast of the United States;
 # the staffer said it was shortly after 10:00 there. When I asked whether
-# that meant they were on Pacific time, they said no--they were on their
+# that meant they were on Pacific time, they said no - they were on their
 # own time. I asked about daylight saving; they said it wasn't used. I
 # did not inquire about practices in the past.
 
@@ -501,9 +499,9 @@ Zone America/Juneau	 15:02:19 -	LMT	1867 Oct 18
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1980 Apr 27 2:00
-			 -9:00	US	Y%sT	1980 Oct 26 2:00
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1980 Apr 27  2:00
+			 -9:00	US	Y%sT	1980 Oct 26  2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
@@ -511,7 +509,7 @@ Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
@@ -519,8 +517,8 @@ Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
-			 -8:00	-	MeST
+			 -8:00	US	P%sT	1983 Oct 30  2:00
+			 -8:00	-	PST
 Zone America/Yakutat	 14:41:05 -	LMT	1867 Oct 18
 			 -9:18:55 -	LMT	1900 Aug 20 12:00
 			 -9:00	-	YST	1942
@@ -535,7 +533,7 @@ Zone America/Anchorage	 14:00:24 -	LMT	1867 Oct 18
 			-10:00	US	CAT/CAPT 1946 # Peace
 			-10:00	-	CAT	1967 Apr
 			-10:00	-	AHST	1969
-			-10:00	US	AH%sT	1983 Oct 30 2:00
+			-10:00	US	AH%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
@@ -544,7 +542,7 @@ Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
@@ -553,7 +551,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			-10:00	US	AH%sT	1983 Nov 30
 			-10:00	US	HA%sT
 # The following switches don't quite make our 1970 cutoff.
@@ -571,7 +569,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 #  Minutes of the Unalaska City Council Meeting, January 10, 1967:
 #  "Except for St. Paul and Akutan, Unalaska is the only important
 #  location not on Alaska Standard Time.  The following resolution was
-#  made by William Robinson and seconded by Henry Swanson:  Be it
+#  made by William Robinson and seconded by Henry Swanson: Be it
 #  resolved that the City of Unalaska hereby goes to Alaska Standard
 #  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
 #  January 14, Alaska Standard Time.)  This resolution was passed with
@@ -583,9 +581,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 # "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225
 # of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09,
 # the article is available at
-# 
 # http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf
-# 
 # and indicates that standard time was adopted effective noon, January
 # 13, 1896 (page 218), that in "1933, the Legislature decreed daylight
 # saving for the period between the last Sunday of each April and the
@@ -606,7 +602,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 # year, the standard time of this Territory shall be advanced one
 # hour...This Act shall take effect upon its approval. Approved this 26th
 # day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of
-# Hawaii." Page 172:  "Act 163...Act 90 of the Session Laws of 1933 is
+# Hawaii." Page 172: "Act 163...Act 90 of the Session Laws of 1933 is
 # hereby repealed...This Act shall take effect upon its approval, upon
 # which date the standard time of this Territory shall be restored to
 # that existing immediately prior to the taking effect of said Act 90.
@@ -616,14 +612,14 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 # Note that 1933-05-21 was a Sunday.
 # We're left to guess the time of day when Act 163 was approved; guess noon.
 
-Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00 #Schmitt&Cox
-			-10:30	-	HST	1933 Apr 30 2:00 #Laws 1933
-			-10:30	1:00	HDT	1933 May 21 12:00 #Laws 1933+12
-			-10:30	-	HST	1942 Feb 09 2:00 #Schmitt&Cox+2
-			-10:30	1:00	HDT	1945 Sep 30 2:00 #Schmitt&Cox+2
-			-10:30	-	HST	1947 Jun  8 2:00 #Schmitt&Cox+2
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00
+			-10:30	-	HST	1933 Apr 30  2:00
+			-10:30	1:00	HDT	1933 May 21 12:00
+			-10:30	-	HST	1942 Feb  9  2:00
+			-10:30	1:00	HDT	1945 Sep 30  2:00
+			-10:30	-	HST	1947 Jun  8  2:00
 			-10:00	-	HST
-
 Link Pacific/Honolulu Pacific/Johnston
 
 # Now we turn to US areas that have diverged from the consensus since 1970.
@@ -633,9 +629,9 @@ Link Pacific/Honolulu Pacific/Johnston
 # From Paul Eggert (2002-10-20):
 #
 # The information in the rest of this paragraph is derived from the
-# 
-# Daylight Saving Time web page (2002-01-23) maintained by the
-# Arizona State Library, Archives and Public Records.
+# Daylight Saving Time web page
+#  (2002-01-23)
+# maintained by the Arizona State Library, Archives and Public Records.
 # Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
 # time, but by federal law railroads, airlines, bus lines, military
 # personnel, and some engaged in interstate commerce continued to
@@ -649,10 +645,11 @@ Link Pacific/Honolulu Pacific/Johnston
 # Shanks says the 1944 experiment came to an end on 1944-03-17.
 # Go with the Arizona State Library instead.
 
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
-			-7:00	US	M%sT	1944 Jan  1 00:01
-			-7:00	-	MST	1944 Apr  1 00:01
-			-7:00	US	M%sT	1944 Oct  1 00:01
+			-7:00	US	M%sT	1944 Jan  1  0:01
+			-7:00	-	MST	1944 Apr  1  0:01
+			-7:00	US	M%sT	1944 Oct  1  0:01
 			-7:00	-	MST	1967
 			-7:00	US	M%sT	1968 Mar 21
 			-7:00	-	MST
@@ -676,24 +673,22 @@ Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
-			-8:00	US	P%sT	1923 May 13 2:00
+			-8:00	US	P%sT	1923 May 13  2:00
 			-7:00	US	M%sT	1974
-			-7:00	-	MST	1974 Feb  3 2:00
+			-7:00	-	MST	1974 Feb  3  2:00
 			-7:00	US	M%sT
 
 # Indiana
 #
 # For a map of Indiana's time zone regions, see:
-# 
-# What time is it in Indiana?
-#  (2006-03-01)
+# http://en.wikipedia.org/wiki/Time_in_Indiana
 #
 # From Paul Eggert (2007-08-17):
 # Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
 # with the following exceptions:
 #
 # - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
-#   Vandenburgh, and Warrick counties have been like America/Chicago.
+#   Vanderburgh, and Warrick counties have been like America/Chicago.
 #
 # - Dearborn and Ohio counties have been like America/New_York.
 #
@@ -712,22 +707,16 @@ Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
 # that they would be ambiguous if we left them at the 'America' level.
 # So we reluctantly put them all in a subdirectory 'America/Indiana'.
 
-# From Paul Eggert (2005-08-16):
-# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
-
-# From Nathan Stratton Treadway (2006-03-30):
-# http://www.dot.gov/affairs/dot0406.htm [3705 B]
-# From Deborah Goldsmith (2006-01-18):
-# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
-# From Paul Eggert (2006-01-20):
-# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
+# From Paul Eggert (2014-06-26):
+# https://www.federalregister.gov/articles/2006/01/20/06-563/standard-time-zone-boundary-in-the-state-of-indiana
+# says "DOT is relocating the time zone boundary in Indiana to move Starke,
 # Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
 # Eastern Time Zone to the Central Time Zone.... The effective date of
-# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
+# this rule is 2 a.m. EST Sunday, April 2, 2006, which is the
 # changeover date from standard time to Daylight Saving Time."
-# Strictly speaking, this means the affected counties will change their
-# clocks twice that night, but this obviously is in error.  The intent
-# is that 01:59:59 EST be followed by 02:00:00 CDT.
+# Strictly speaking, this meant the affected counties changed their
+# clocks twice that night, but this obviously was in error.  The intent
+# was that 01:59:59 EST be followed by 02:00:00 CDT.
 
 # From Gwillim Law (2007-02-10):
 # The Associated Press has been reporting that Pulaski County, Indiana is
@@ -739,13 +728,13 @@ Rule Indianapolis 1941	only	-	Jun	22	2:00	1:00	D
 Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
 Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
+Zone America/Indiana/Indianapolis -5:44:38 - LMT	1883 Nov 18 12:15:22
 			-6:00	US	C%sT	1920
 			-6:00 Indianapolis C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Indianapolis C%sT	1955 Apr 24 2:00
-			-5:00	-	EST	1957 Sep 29 2:00
-			-6:00	-	CST	1958 Apr 27 2:00
+			-6:00 Indianapolis C%sT	1955 Apr 24  2:00
+			-5:00	-	EST	1957 Sep 29  2:00
+			-6:00	-	CST	1958 Apr 27  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
 			-5:00	-	EST	2006
@@ -761,10 +750,10 @@ Rule	Marengo	1954	1960	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
 			-6:00	US	C%sT	1951
-			-6:00	Marengo	C%sT	1961 Apr 30 2:00
+			-6:00	Marengo	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT	1976
 			-5:00	-	EST	2006
 			-5:00	US	E%sT
@@ -785,11 +774,11 @@ Rule Vincennes	1962	1963	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
 			-6:00	US	C%sT	1946
-			-6:00 Vincennes	C%sT	1964 Apr 26 2:00
+			-6:00 Vincennes	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Perry County, Indiana, switched from eastern to central time in April 2006.
@@ -806,10 +795,10 @@ Rule Perry	1962	1963	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
 			-6:00	US	C%sT	1946
-			-6:00 Perry	C%sT	1964 Apr 26 2:00
+			-6:00 Perry	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pike County, Indiana moved from central to eastern time in 1977,
@@ -822,11 +811,11 @@ Rule	Pike	1961	1964	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
 			-6:00	US	C%sT	1955
-			-6:00	Pike	C%sT	1965 Apr 25 2:00
-			-5:00	-	EST	1966 Oct 30 2:00
-			-6:00	US	C%sT	1977 Oct 30 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-6:00	Pike	C%sT	1965 Apr 25  2:00
+			-5:00	-	EST	1966 Oct 30  2:00
+			-6:00	US	C%sT	1977 Oct 30  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Starke County, Indiana moved from central to eastern time in 1991,
@@ -844,10 +833,10 @@ Rule	Starke	1959	1961	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
 			-6:00	US	C%sT	1947
-			-6:00	Starke	C%sT	1962 Apr 29 2:00
-			-5:00	-	EST	1963 Oct 27 2:00
-			-6:00	US	C%sT	1991 Oct 27 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
+			-6:00	Starke	C%sT	1962 Apr 29  2:00
+			-5:00	-	EST	1963 Oct 27  2:00
+			-6:00	US	C%sT	1991 Oct 27  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pulaski County, Indiana, switched from eastern to central time in
@@ -860,17 +849,17 @@ Rule	Pulaski	1957	1960	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
 			-6:00	US	C%sT	1946
-			-6:00	Pulaski	C%sT	1961 Apr 30 2:00
+			-6:00	Pulaski	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Mar 11 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Mar 11  2:00
 			-5:00	US	E%sT
 #
 # Switzerland County, Indiana, did not observe DST from 1973 through 2005.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
-			-6:00	US	C%sT	1954 Apr 25 2:00
+			-6:00	US	C%sT	1954 Apr 25  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1973
 			-5:00	-	EST	2006
@@ -891,18 +880,17 @@ Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
 			-6:00	US	C%sT	1921
 			-6:00 Louisville C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Louisville C%sT	1961 Jul 23 2:00
+			-6:00 Louisville C%sT	1961 Jul 23  2:00
 			-5:00	-	EST	1968
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT
 #
 # Wayne County, Kentucky
 #
-# From
-# 
-# Lake Cumberland LIFE
-#  (1999-01-29) via WKYM-101.7:
+# From Lake Cumberland LIFE
+# http://www.lake-cumberland.com/life/archive/news990129time.shtml
+# (1999-01-29) via WKYM-101.7:
 # Clinton County has joined Wayne County in asking the DoT to change from
 # the Central to the Eastern time zone....  The Wayne County government made
 # the same request in December.  And while Russell County officials have not
@@ -919,9 +907,8 @@ Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
 #
 # From Paul Eggert (2001-07-16):
 # The final rule was published in the
-# 
-# Federal Register 65, 160 (2000-08-17), page 50154-50158.
-# 
+# Federal Register 65, 160 (2000-08-17), pp 50154-50158.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22
 #
 Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
 			-6:00	US	C%sT	1946
@@ -946,9 +933,8 @@ Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
 # See America/North_Dakota/Center for the Oliver County, ND change.
 # West Wendover, NV officially switched from Pacific to mountain time on
 # 1999-10-31.  See the
-# 
-# Federal Register 64, 203 (1999-10-21), page 56705-56707.
-# 
+# Federal Register 64, 203 (1999-10-21), pp 56705-56707.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15
 # However, the Federal Register says that West Wendover already operated
 # on mountain time, and the rule merely made this official;
 # hence a separate tz entry is not needed.
@@ -986,12 +972,12 @@ Rule	Detroit	1967	only	-	Jun	14	2:00	1:00	D
 Rule	Detroit	1967	only	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Detroit	-5:32:11 -	LMT	1905
-			-6:00	-	CST	1915 May 15 2:00
+			-6:00	-	CST	1915 May 15  2:00
 			-5:00	-	EST	1942
 			-5:00	US	E%sT	1946
 			-5:00	Detroit	E%sT	1973
 			-5:00	US	E%sT	1975
-			-5:00	-	EST	1975 Apr 27 2:00
+			-5:00	-	EST	1975 Apr 27  2:00
 			-5:00	US	E%sT
 #
 # Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
@@ -1004,8 +990,8 @@ Rule Menominee	1966	only	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 			-6:00	US	C%sT	1946
-			-6:00 Menominee	C%sT	1969 Apr 27 2:00
-			-5:00	-	EST	1973 Apr 29 2:00
+			-6:00 Menominee	C%sT	1969 Apr 27  2:00
+			-5:00	-	EST	1973 Apr 29  2:00
 			-6:00	US	C%sT
 
 # Navassa
@@ -1042,9 +1028,9 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	
 #	William Willett, The Waste of Daylight, 19th edition
-#	 (1914-03)
+#	
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	.
@@ -1053,11 +1039,11 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 
 # Canada
 
-# From Alain LaBont (1994-11-14):
+# From Alain LaBonté (1994-11-14):
 # I post here the time zone abbreviations standardized in Canada
 # for both English and French in the CAN/CSA-Z234.4-89 standard....
 #
-#	UTC	Standard time	Daylight savings time
+#	UTC	Standard time	Daylight saving time
 #	offset	French	English	French	English
 #	-2:30	-	-	HAT	NDT
 #	-3	-	-	HAA	ADT
@@ -1070,7 +1056,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 #	-9	HNY	YST	-	-
 #
 #	HN: Heure Normale	ST: Standard Time
-#	HA: Heure Avance	DT: Daylight saving Time
+#	HA: Heure Avancée	DT: Daylight saving Time
 #
 #	A: de l'Atlantique	Atlantic
 #	C: du Centre		Central
@@ -1085,7 +1071,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 # From Paul Eggert (1994-11-22):
 # Alas, this sort of thing must be handled by localization software.
 
-# Unless otherwise specified, the data for Canada are all from Shanks
+# Unless otherwise specified, the data entries for Canada are all from Shanks
 # & Pottenger.
 
 # From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
@@ -1134,15 +1120,15 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 
 # From Paul Eggert (2006-04-25):
 # H. David Matthews and Mary Vincent's map
-# 
 # "It's about TIME", _Canadian Geographic_ (September-October 1998)
-#  contains detailed boundaries for regions observing nonstandard
+# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
+# contains detailed boundaries for regions observing nonstandard
 # time and daylight saving time arrangements in Canada circa 1998.
 #
-# INMS, the Institute for National Measurement Standards in Ottawa, has 
+# INMS, the Institute for National Measurement Standards in Ottawa, has
 # information about standard and daylight saving time zones in Canada.
-#  (updated periodically).
+# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php
+# (updated periodically).
 # Its unofficial information is often taken from Matthews and Vincent.
 
 # From Paul Eggert (2006-06-27):
@@ -1151,9 +1137,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 
 # From Chris Walton (2011-12-01)
 # In the first of Tammy Hardwick's articles
-# 
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# 
 # she quotes the Friday November 1/1918 edition of the Creston Review.
 # The quote includes these two statements:
 # 'Sunday the CPR went back to the old system of time...'
@@ -1221,9 +1205,7 @@ Rule	StJohns	1960	1986	-	Oct	lastSun	2:00	0	S
 # Time to Standard Time and from Standard Time to Daylight Savings Time
 # now occurs at 2:00AM.
 # ...
-# 
 # http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
-# 
 # ...
 # MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
 # Office of the Chief Information Officer
@@ -1259,7 +1241,7 @@ Zone America/Goose_Bay	-4:01:40 -	LMT	1884 # Happy Valley-Goose Bay
 			-3:30	-	NST	1936
 			-3:30	StJohns	N%sT	1942 May 11
 			-3:30	Canada	N%sT	1946
-			-3:30	StJohns	N%sT	1966 Mar 15 2:00
+			-3:30	StJohns	N%sT	1966 Mar 15  2:00
 			-4:00	StJohns	A%sT	2011 Nov
 			-4:00	Canada	A%sT
 
@@ -1320,7 +1302,7 @@ Rule	Halifax	1962	1973	-	Oct	lastSun	2:00	0	S
 Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
 			-4:00	Halifax	A%sT	1918
 			-4:00	Canada	A%sT	1919
-			-4:00	Halifax	A%sT	1942 Feb  9 2:00s
+			-4:00	Halifax	A%sT	1942 Feb  9  2:00s
 			-4:00	Canada	A%sT	1946
 			-4:00	Halifax	A%sT	1974
 			-4:00	Canada	A%sT
@@ -1379,7 +1361,7 @@ Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
 # meridian is supposed to observe AST, but residents as far east as
 # Natashquan use EST/EDT, and residents east of Natashquan use AST.
 # The Quebec department of justice writes in
-# "The situation in Minganie and Basse-Cote-Nord"
+# "The situation in Minganie and Basse-Côte-Nord"
 # http://www.justice.gouv.qc.ca/english/publications/generale/temps-minganie-a.htm
 # that the coastal strip from just east of Natashquan to Blanc-Sablon
 # observes Atlantic standard time all year round.
@@ -1387,7 +1369,6 @@ Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
 # says this common practice was codified into law as of 2007.
 # For lack of better info, guess this practice began around 1970, contra to
 # Shanks & Pottenger who have this region observing AST/ADT.
-# for post-1970 data America/Puerto_Rico.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
@@ -1401,18 +1382,10 @@ Rule	Mont	1922	only	-	Apr	30	2:00	1:00	D
 Rule	Mont	1924	only	-	May	17	2:00	1:00	D
 Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
 Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
-# The 1927-to-1937 rules can be expressed more simply as
-# Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
-# Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
-# The rules below avoid use of 24:00
-# (which pre-1998 versions of zic cannot handle).
-Rule	Mont	1927	only	-	May	1	0:00	1:00	D
-Rule	Mont	1927	1932	-	Sep	lastSun	0:00	0	S
-Rule	Mont	1928	1931	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1932	only	-	May	1	0:00	1:00	D
-Rule	Mont	1933	1940	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1933	only	-	Oct	1	0:00	0	S
-Rule	Mont	1934	1939	-	Sep	lastSun	0:00	0	S
+Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
+Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
+Rule	Mont	1938	1940	-	Apr	lastSun	0:00	1:00	D
+Rule	Mont	1938	1939	-	Sep	lastSun	0:00	0	S
 Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
 Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
 Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
@@ -1426,7 +1399,7 @@ Zone America/Blanc-Sablon -3:48:28 -	LMT	1884
 Zone America/Montreal	-4:54:16 -	LMT	1884
 			-5:00	Mont	E%sT	1918
 			-5:00	Canada	E%sT	1919
-			-5:00	Mont	E%sT	1942 Feb  9 2:00s
+			-5:00	Mont	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Mont	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1448,7 +1421,7 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # have already done so.  In Orillia DST was to run until Saturday,
 # 1912-08-31 (no time mentioned), but it was met with considerable
 # hostility from certain segments of the public, and was revoked after
-# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
+# only two weeks - I copied it as Saturday, 1912-07-07, 22:00, but
 # presumably that should be -07-06.  (1912-06-19, -07-12; also letters
 # earlier in June).
 #
@@ -1458,10 +1431,8 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # Mark Brader writes that an article in the 1997-10-14 Toronto Star
 # says that Atikokan, Ontario currently does not observe DST,
 # but will vote on 11-10 whether to use EST/EDT.
-# He also writes that the
-# 
-# Ontario Time Act (1990, Chapter T.9)
-# 
+# He also writes that the Ontario Time Act (1990, Chapter T.9)
+# http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html
 # says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
 # Officially Atikokan is therefore on CST/CDT, and most likely this report
 # concerns a non-official time observed as a matter of local practice.
@@ -1540,9 +1511,7 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # The Journal of The Royal Astronomical Society of Canada,
 # volume 26, number 2 (February 1932) and, as of 2010-07-17,
 # was available at
-# 
 # http://adsabs.harvard.edu/full/1932JRASC..26...49S
-# 
 #
 # It includes the text below (starting on page 57):
 #
@@ -1553,26 +1522,26 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # ing in 1930. The information for the province of Quebec is definite,
 # for the other provinces only approximate:
 #
-# 	Province	Daylight saving time used
+#	Province	Daylight saving time used
 # Prince Edward Island	Not used.
 # Nova Scotia		In Halifax only.
 # New Brunswick		In St. John only.
 # Quebec		In the following places:
-# 			Montreal	Lachine
-# 			Quebec		Mont-Royal
-# 			Levis		Iberville
-# 			St. Lambert	Cap de la Madeleine
-# 			Verdun		Loretteville
-# 			Westmount	Richmond
-# 			Outremont	St. Jerome
-# 			Longueuil	Greenfield Park
-# 			Arvida		Waterloo
-# 			Chambly-Canton	Beaulieu
-# 			Melbourne	La Tuque
-# 			St. Theophile	Buckingham
+#			Montreal	Lachine
+#			Quebec		Mont-Royal
+#			Lévis		Iberville
+#			St. Lambert	Cap de la Madelèine
+#			Verdun		Loretteville
+#			Westmount	Richmond
+#			Outremont	St. Jérôme
+#			Longueuil	Greenfield Park
+#			Arvida		Waterloo
+#			Chambly-Canton	Beaulieu
+#			Melbourne	La Tuque
+#			St. Théophile	Buckingham
 # Ontario		Used generally in the cities and towns along
-# 			the southerly part of the province. Not
-# 			used in the northwesterlhy part.
+#			the southerly part of the province. Not
+#			used in the northwesterly part.
 # Manitoba		Not used.
 # Saskatchewan		In Regina only.
 # Alberta		Not used.
@@ -1641,7 +1610,7 @@ Rule	Toronto	1957	1973	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Toronto	-5:17:32 -	LMT	1895
 			-5:00	Canada	E%sT	1919
-			-5:00	Toronto	E%sT	1942 Feb  9 2:00s
+			-5:00	Toronto	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Toronto	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1654,16 +1623,16 @@ Zone America/Thunder_Bay -5:57:00 -	LMT	1895
 			-5:00	Canada	E%sT
 Zone America/Nipigon	-5:53:04 -	LMT	1895
 			-5:00	Canada	E%sT	1940 Sep 29
-			-5:00	1:00	EDT	1942 Feb  9 2:00s
+			-5:00	1:00	EDT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT
 Zone America/Rainy_River -6:18:16 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
 			-6:00	Canada	C%sT
 Zone America/Atikokan	-6:06:28 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
-			-6:00	Canada	C%sT	1945 Sep 30 2:00
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
+			-6:00	Canada	C%sT	1945 Sep 30  2:00
 			-5:00	-	EST
 
 
@@ -1676,7 +1645,7 @@ Zone America/Atikokan	-6:06:28 -	LMT	1895
 # the first Sunday of April of each year and two o'clock Central
 # Standard Time in the morning of the last Sunday of October next
 # following, one hour in advance of Central Standard Time."...
-# I believe that the English legislation [of the old time act] had =
+# I believe that the English legislation [of the old time act] had
 # been assented to (March 22, 1967)....
 # Also, as far as I can tell, there was no order-in-council varying
 # the time of Daylight Saving Time for 2005 and so the provisions of
@@ -1799,12 +1768,12 @@ Rule	Swift	1959	only	-	Oct	lastSun	2:00	0	S
 Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Regina	-6:58:36 -	LMT	1905 Sep
-			-7:00	Regina	M%sT	1960 Apr lastSun 2:00
+			-7:00	Regina	M%sT	1960 Apr lastSun  2:00
 			-6:00	-	CST
 Zone America/Swift_Current -7:11:20 -	LMT	1905 Sep
-			-7:00	Canada	M%sT	1946 Apr lastSun 2:00
+			-7:00	Canada	M%sT	1946 Apr lastSun  2:00
 			-7:00	Regina	M%sT	1950
-			-7:00	Swift	M%sT	1972 Apr lastSun 2:00
+			-7:00	Swift	M%sT	1972 Apr lastSun  2:00
 			-6:00	-	CST
 
 
@@ -1854,9 +1823,7 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 # Earlier this year I stumbled across a detailed article about the time
 # keeping history of Creston; it was written by Tammy Hardwick who is the
 # manager of the Creston & District Museum. The article was written in May 2009.
-# 
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# 
 # According to the article, Creston has not changed its clocks since June 1918.
 # i.e. Creston has been stuck on UTC-7 for 93 years.
 # Dawson Creek, on the other hand, changed its clocks as recently as April 1972.
@@ -1864,18 +1831,16 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 # Unfortunately the exact date for the time change in June 1918 remains
 # unknown and will be difficult to ascertain.  I e-mailed Tammy a few months
 # ago to ask if Sunday June 2 was a reasonable guess.  She said it was just
-# as plausible as any other date (in June).  She also said that after writing the
-# article she had discovered another time change in 1916; this is the subject
-# of another article which she wrote in October 2010.
-# 
+# as plausible as any other date (in June).  She also said that after writing
+# the article she had discovered another time change in 1916; this is the
+# subject of another article which she wrote in October 2010.
 # http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56
-# 
 
 # Here is a summary of the three clock change events in Creston's history:
 # 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
 # Exact date unknown
 # 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
-# Exact date in October unknown;  Sunday October 1 is a reasonable guess.
+# Exact date in October unknown; Sunday October 1 is a reasonable guess.
 # 3. June 1918: switch to Pacific Daylight Time (GMT-7)
 # Exact date in June unknown; Sunday June 2 is a reasonable guess.
 # note#1:
@@ -1888,9 +1853,7 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 # There is no guarantee that Creston will remain on Mountain Standard Time
 # (UTC-7) forever.
 # The subject was debated at least once this year by the town Council.
-# 
 # http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html
-# 
 
 # During a period WWII, summer time (Daylight saying) was mandatory in Canada.
 # In Creston, that was handled by shifting the area to PST (-8:00) then applying
@@ -1917,7 +1880,7 @@ Zone America/Vancouver	-8:12:28 -	LMT	1884
 			-8:00	Canada	P%sT
 Zone America/Dawson_Creek -8:00:56 -	LMT	1884
 			-8:00	Canada	P%sT	1947
-			-8:00	Vanc	P%sT	1972 Aug 30 2:00
+			-8:00	Vanc	P%sT	1972 Aug 30  2:00
 			-7:00	-	MST
 Zone America/Creston	-7:46:04 -	LMT	1884
 			-7:00	-	MST	1916 Oct 1
@@ -1944,18 +1907,17 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 
 # From Rives McDow (1999-09-04):
 # Nunavut ... moved ... to incorporate the whole territory into one time zone.
-# 
 # Nunavut moves to single time zone Oct. 31
-# 
+# http://www.nunatsiaq.com/nunavut/nvt90903_13.html
 #
 # From Antoine Leca (1999-09-06):
 # We then need to create a new timezone for the Kitikmeot region of Nunavut
 # to differentiate it from the Yellowknife region.
 
 # From Paul Eggert (1999-09-20):
-# 
 # Basic Facts: The New Territory
-#  (1999) reports that Pangnirtung operates on eastern time,
+# http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html
+# (1999) reports that Pangnirtung operates on eastern time,
 # and that Coral Harbour does not observe DST.  We don't know when
 # Pangnirtung switched to eastern time; we'll guess 1995.
 
@@ -1983,8 +1945,8 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 # the current state of affairs.
 
 # From Michaela Rodrigue, writing in the
-# 
-# Nunatsiaq News (1999-11-19):
+# Nunatsiaq News (1999-11-19):
+# http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html
 # Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
 # central - or Nunavut time - for government offices, and eastern time
 # for municipal offices and schools....  Igloolik [was similar but then]
@@ -2002,10 +1964,8 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 # Central Time and Southampton Island [in the Central zone] is not
 # required to use daylight savings.
 
-# From
-# 
-# Nunavut now has two time zones
-#  (2000-11-10):
+# From 
+# Nunavut now has two time zones (2000-11-10):
 # The Nunavut government would allow its employees in Kugluktuk and
 # Cambridge Bay to operate on central time year-round, putting them
 # one hour behind the rest of Nunavut for six months during the winter.
@@ -2096,9 +2056,7 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 # used to be the mayor of Resolute Bay and he apparently owns half the
 # businesses including "South Camp Inn." This website has some info on
 # Aziz:
-# 
 # http://www.uphere.ca/node/493
-# 
 #
 # I sent Aziz an e-mail asking when Resolute Bay had stopped using
 # Eastern Standard Time.
@@ -2136,47 +2094,47 @@ Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
 Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
-			-4:00	NT_YK	A%sT	1995 Apr Sun>=1 2:00
-			-5:00	Canada	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
+			-5:00	Canada	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # formerly Frobisher Bay
 Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
-			-5:00	NT_YK	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # aka Qausuittuq
 Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
-			-6:00	Canada	C%sT	2006 Oct 29 2:00
-			-5:00	-	EST	2007 Mar 11 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
+			-6:00	Canada	C%sT	2006 Oct 29  2:00
+			-5:00	-	EST	2007 Mar 11  3:00
 			-6:00	Canada	C%sT
 # aka Kangiqiniq
 Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT
 # aka Iqaluktuuttiaq
 Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
-			-7:00	NT_YK	M%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2000 Nov  5 0:00
-			-6:00	-	CST	2001 Apr  1 3:00
+			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2000 Nov  5  0:00
+			-6:00	-	CST	2001 Apr  1  3:00
 			-7:00	Canada	M%sT
 Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
-			-8:00	NT_YK	P%sT	1979 Apr lastSun 2:00
+			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Whitehorse	-9:00:12 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1966 Jul 1 2:00
+			-9:00	NT_YK	Y%sT	1966 Jul  1  2:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1973 Oct 28 0:00
+			-9:00	NT_YK	Y%sT	1973 Oct 28  0:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 
@@ -2188,9 +2146,8 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # From Paul Eggert (2001-03-05):
 # The Investigation and Analysis Service of the
 # Mexican Library of Congress (MLoC) has published a
-# 
 # history of Mexican local time (in Spanish)
-# .
+# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
 #
 # Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
 # (In all cases we go with the MLoC.)
@@ -2235,9 +2192,8 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # -------------- End Forwarded Message --------------
 # From Paul Eggert (1996-06-12):
 # For an English translation of the decree, see
-# 
 # "Diario Oficial: Time Zone Changeover" (1996-01-04).
-# 
+# http://mexico-travel.com/extra/timezone_eng.html
 
 # From Rives McDow (1998-10-08):
 # The State of Quintana Roo has reverted back to central STD and DST times
@@ -2249,7 +2205,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # savings time so as to stay on the same time zone as the southern part of
 # Arizona year round.
 
-# From Jesper Norgaard, translating
+# From Jesper Nørgaard, translating
 #  (2001-01-17):
 # In Oaxaca, the 55.000 teachers from the Section 22 of the National
 # Syndicate of Education Workers, refuse to apply daylight saving each
@@ -2262,7 +2218,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
 # that Summer Time will be reduced from seven to five months, starting
 # this year....
-# 
+# http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001
 # [translated], says "summer time will ... take effect on the first Sunday
 # in May, and end on the last Sunday of September.
 
@@ -2270,23 +2226,22 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # The 2001-01-24 traditional Washington Post contained the page one
 # story "Timely Issue Divides Mexicans."...
 # http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
-# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
+# ... Mexico City Mayor López Obrador "...is threatening to keep
 # Mexico City and its 20 million residents on a different time than
-# the rest of the country..." In particular, Lopez Obrador would abolish
+# the rest of the country..." In particular, López Obrador would abolish
 # observation of Daylight Saving Time.
 
-# 
 # Official statute published by the Energy Department
-#  (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
-# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
+# http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre
+# (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
+# and Sonora with no DST.  This was reported by Jesper Nørgaard (2001-02-03).
 
 # From Paul Eggert (2001-03-03):
 #
-# 
+# http://www.latimes.com/news/nation/20010303/t000018766.html
 # James F. Smith writes in today's LA Times
-# 
 # * Sonora will continue to observe standard time.
-# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
+# * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
 #   the Federal District will not adopt DST.
 # * 4 of 16 district leaders announced they'll ignore the decree.
 # * The decree does not affect federal-controlled facilities including
@@ -2294,7 +2249,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 #
 # For now we'll assume that the Federal District will bow to federal rules.
 
-# From Jesper Norgaard (2001-04-01):
+# From Jesper Nørgaard (2001-04-01):
 # I found some references to the Mexican application of daylight
 # saving, which modifies what I had already sent you, stating earlier
 # that a number of northern Mexican states would go on daylight
@@ -2303,7 +2258,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # saving all year) will follow the original decree of president
 # Vicente Fox, starting daylight saving May 6, 2001 and ending
 # September 30, 2001.
-# References: "Diario de Monterrey" 
+# References: "Diario de Monterrey" 
 # Palabra  (2001-03-31)
 
 # From Reuters (2001-09-04):
@@ -2315,7 +2270,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # standard time. "This is so residents of the Federal District are not
 # subject to unexpected time changes," a statement from the court said.
 
-# From Jesper Norgaard Welen (2002-03-12):
+# From Jesper Nørgaard Welen (2002-03-12):
 # ... consulting my local grocery store(!) and my coworkers, they all insisted
 # that a new decision had been made to reinstate US style DST in Mexico....
 # http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
@@ -2329,48 +2284,36 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # > the United States.
 # Now this has passed both the Congress and the Senate, so starting from
 # 2010, some border regions will be the same:
-# 
 # http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/
-# 
-# 
 # http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939
-# 
 # (Spanish)
 #
 # Could not find the new law text, but the proposed law text changes are here:
-# 
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf
-# 
 # (Gaceta Parlamentaria)
 #
 # There is also a list of the votes here:
-# 
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html
-# 
 #
 # Our page:
-# 
 # http://www.timeanddate.com/news/time/north-mexico-dst-change.html
-# 
 
 # From Arthur David Olson (2010-01-20):
 # The page
-# 
 # http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010
-# 
 # includes this text:
 # En los municipios fronterizos de Tijuana y Mexicali en Baja California;
-# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
-# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
-# Tamaulipas, la aplicación de este horario estacional surtirá efecto
-# desde las dos horas del segundo domingo de marzo y concluirá a las dos
+# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
+# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
+# Tamaulipas, la aplicación de este horario estacional surtirá efecto
+# desde las dos horas del segundo domingo de marzo y concluirá a las dos
 # horas del primer domingo de noviembre.
 # En los municipios fronterizos que se encuentren ubicados en la franja
-# fronteriza norte en el territorio comprendido entre la línea
-# internacional y la línea paralela ubicada a una distancia de veinte
-# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
-# interior del país, la aplicación de este horario estacional surtirá
-# efecto desde las dos horas del segundo domingo de marzo y concluirá a
+# fronteriza norte en el territorio comprendido entre la línea
+# internacional y la línea paralela ubicada a una distancia de veinte
+# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
+# interior del país, la aplicación de este horario estacional surtirá
+# efecto desde las dos horas del segundo domingo de marzo y concluirá a
 # las dos horas del primer domingo de noviembre.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -2389,39 +2332,39 @@ Rule	Mexico	2001	only	-	Sep	lastSun	2:00	0	S
 Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
 Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Quintana Roo
+# Quintana Roo; represented by Cancún
 Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
 			-6:00	-	CST	1981 Dec 23
 			-5:00	Mexico	E%sT	1998 Aug  2  2:00
 			-6:00	Mexico	C%sT
-# Campeche, Yucatan
+# Campeche, Yucatán; represented by Mérida
 Zone America/Merida	-5:58:28 -	LMT	1922 Jan  1  0:01:32
 			-6:00	-	CST	1981 Dec 23
 			-5:00	-	EST	1982 Dec  2
 			-6:00	Mexico	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (near US border)
 Zone America/Matamoros	-6:40:00 -	LMT	1921 Dec 31 23:20:00
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT	2010
 			-6:00	US	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (away from US border)
 Zone America/Monterrey	-6:41:16 -	LMT	1921 Dec 31 23:18:44
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT
 # Central Mexico
-Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1 0:23:24
+Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1  0:23:24
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
 			-6:00	-	CST	1931 Oct
 			-7:00	-	MST	1932 Apr  1
-			-6:00	Mexico	C%sT	2001 Sep 30 02:00
+			-6:00	Mexico	C%sT	2001 Sep 30  2:00
 			-6:00	-	CST	2002 Feb 20
 			-6:00	Mexico	C%sT
 # Chihuahua (near US border)
-Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
+Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan  1  0:02:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
@@ -2429,7 +2372,7 @@ Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT	2010
 			-7:00	US	M%sT
 # Chihuahua (away from US border)
@@ -2441,7 +2384,7 @@ Zone America/Chihuahua	-7:04:20 -	LMT	1921 Dec 31 23:55:40
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT
 # Sonora
 Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
@@ -2457,42 +2400,33 @@ Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
 			-7:00	-	MST
 
 # From Alexander Krivenyshev (2010-04-21):
-# According to news, Bahía de Banderas (Mexican state of Nayarit)
+# According to news, Bahía de Banderas (Mexican state of Nayarit)
 # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
 # share the same time zone as nearby city Puerto Vallarta, Jalisco).
 #
 # (Spanish)
-# Bahía de Banderas homologa su horario al del centro del
-# país, a partir de este domingo
-# 
+# Bahía de Banderas homologa su horario al del centro del
+# país, a partir de este domingo
 # http://www.nayarit.gob.mx/notes.asp?id=20748
-# 
 #
-# Bahía de Banderas homologa su horario con el del Centro del
-# País
-# 
-# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
-# 
+# Bahía de Banderas homologa su horario con el del Centro del
+# País
+# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50
 #
 # (English)
-# Puerto Vallarta and Bahía de Banderas: One Time Zone
-# 
+# Puerto Vallarta and Bahía de Banderas: One Time Zone
 # http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
-# 
-#
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
-# 
 #
 # "Mexico's Senate approved the amendments to the Mexican Schedule System that
-# will allow Bahía de Banderas and Puerto Vallarta to share the same time
+# will allow Bahía de Banderas and Puerto Vallarta to share the same time
 # zone ..."
 # Baja California Sur, Nayarit, Sinaloa
 
 # From Arthur David Olson (2010-05-01):
 # Use "Bahia_Banderas" to keep the name to fourteen characters.
 
+# Mazatlán
 Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2504,6 +2438,7 @@ Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
 			-8:00	-	PST	1970
 			-7:00	Mexico	M%sT
 
+# Bahía de Banderas
 Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2513,7 +2448,7 @@ Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
 			-6:00	-	CST	1942 Apr 24
 			-7:00	-	MST	1949 Jan 14
 			-8:00	-	PST	1970
-			-7:00	Mexico	M%sT	2010 Apr 4 2:00
+			-7:00	Mexico	M%sT	2010 Apr  4  2:00
 			-6:00	Mexico	C%sT
 
 # Baja California (near US border)
@@ -2560,7 +2495,7 @@ Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
 # America/Tijuana only in that it did not observe DST from 1976
 # through 1995.  This was as per Shanks (1999).  But Shanks & Pottenger say
 # Ensenada did not observe DST from 1948 through 1975.  Guy Harris reports
-# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
+# that the 1987 OAG says "Only Ensenada, Mexicali, San Felipe and
 # Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
 # DST-observance was a town-by-town matter back then.  This concerns
 # data after 1970 so most likely there should be at least one Zone
@@ -2573,7 +2508,7 @@ Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
 ###############################################################################
 
 # Anguilla
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Antigua and Barbuda
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2609,8 +2544,8 @@ Rule	Barb	1978	1980	-	Apr	Sun>=15	2:00	1:00	D
 Rule	Barb	1979	only	-	Sep	30	2:00	0	S
 Rule	Barb	1980	only	-	Sep	25	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Barbados	-3:58:29 -	LMT	1924		# Bridgetown
-			-3:58:29 -	BMT	1932	  # Bridgetown Mean Time
+Zone America/Barbados	-3:58:29 -	LMT	1924 # Bridgetown
+			-3:58:29 -	BMT	1932 # Bridgetown Mean Time
 			-4:00	Barb	A%sT
 
 # Belize
@@ -2640,20 +2575,20 @@ Zone	America/Belize	-5:52:48 -	LMT	1912 Apr
 # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1 2:00    # Hamilton
-			-4:00	-	AST	1974 Apr 28 2:00
+Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1  2:00 # Hamilton
+			-4:00	-	AST	1974 Apr 28  2:00
 			-4:00	Canada	A%sT	1976
 			-4:00	US	A%sT
 
 # Cayman Is
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Cayman	-5:25:32 -	LMT	1890		# Georgetown
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
+Zone	America/Cayman	-5:25:32 -	LMT	1890     # Georgetown
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
 			-5:00	-	EST
 
 # Costa Rica
 
-# Milne gives -5:36:13.3 as San Jose mean time; round to nearest.
+# Milne gives -5:36:13.3 as San José mean time; round to nearest.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	CR	1979	1980	-	Feb	lastSun	0:00	1:00	D
@@ -2663,10 +2598,10 @@ Rule	CR	1991	1992	-	Jan	Sat>=15	0:00	1:00	D
 # go with Shanks & Pottenger.
 Rule	CR	1991	only	-	Jul	 1	0:00	0	S
 Rule	CR	1992	only	-	Mar	15	0:00	0	S
-# There are too many San Joses elsewhere, so we'll use 'Costa Rica'.
+# There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
-			-5:36:13 -	SJMT	1921 Jan 15 # San Jose Mean Time
+Zone America/Costa_Rica	-5:36:13 -	LMT	1890        # San José
+			-5:36:13 -	SJMT	1921 Jan 15 # San José Mean Time
 			-6:00	CR	C%sT
 # Coco
 # no information; probably like America/Costa_Rica
@@ -2685,8 +2620,8 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # During the game, play-by-play announcer Jim Hunter noted that
 # "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
 # Time today."  (The "two hour" remark referred to losing one hour of
-# sleep on 1999-03-28--when the announcers were in Cuba as it switched
-# to DST--and one more hour on 1999-04-04--when the announcers will have
+# sleep on 1999-03-28 - when the announcers were in Cuba as it switched
+# to DST - and one more hour on 1999-04-04 - when the announcers will have
 # returned to Baltimore, which switches on that date.)
 
 # From Steffen Thorsen (2013-11-11):
@@ -2708,16 +2643,16 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # adjustment in Cuba.  We will stay in daylight saving time:
 # http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
 
-# From Jesper Norgaard Welen (2006-10-21):
+# From Jesper Nørgaard Welen (2006-10-21):
 # An article in GRANMA INTERNACIONAL claims that Cuba will end
 # the 3 years of permanent DST next weekend, see
 # http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
 # "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
-# watches should be set back one hour -- going back to 00:00 hours -- returning
+# watches should be set back one hour - going back to 00:00 hours - returning
 # to the normal schedule....
 
 # From Paul Eggert (2007-03-02):
-# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
+# , dated yesterday,
 # says Cuban clocks will advance at midnight on March 10.
 # For lack of better information, assume Cuba will use US rules,
 # except that it switches at midnight standard time as usual.
@@ -2731,10 +2666,10 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
 # http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
 #
-# From Alex Kryvenishev (2007-10-25):
+# From Alex Krivenyshev (2007-10-25):
 # Here is also article from Granma (Cuba):
 #
-# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
+# Regirá el Horario Normal desde el próximo domingo 28 de octubre
 # http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
 #
 # http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
@@ -2742,23 +2677,18 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # From Arthur David Olson (2008-03-09):
 # I'm in Maryland which is now observing United States Eastern Daylight
 # Time. At 9:44 local time I used RealPlayer to listen to
-# 
 # http://media.enet.cu/radioreloj
-# , a Cuban information station, and heard
+# a Cuban information station, and heard
 # the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
 # indicating that Cuba is still on standard time.
 
 # From Steffen Thorsen (2008-03-12):
 # It seems that Cuba will start DST on Sunday, 2007-03-16...
 # It was announced yesterday, according to this source (in Spanish):
-# 
 # http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
-# 
 #
 # Some more background information is posted here:
-# 
 # http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
-# 
 #
 # The article also says that Cuba has been observing DST since 1963,
 # while Shanks (and tzdata) has 1965 as the first date (except in the
@@ -2768,18 +2698,14 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # change some historic records as well.
 #
 # One example:
-# 
 # http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
-# 
 
-# From Jesper Norgaard Welen (2008-03-13):
+# From Jesper Nørgaard Welen (2008-03-13):
 # The Cuban time change has just been confirmed on the most authoritative
 # web site, the Granma.  Please check out
-# 
 # http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
-# 
 #
-# Basically as expected after Steffen Thorsens information, the change
+# Basically as expected after Steffen Thorsen's information, the change
 # will take place midnight between Saturday and Sunday.
 
 # From Arthur David Olson (2008-03-12):
@@ -2790,18 +2716,14 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
 # not on midnight March 14 / March 15 as previously thought.
 #
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
 # (in Spanish)
-# 
 
 # From Arthur David Olson (2009-03-09)
 # I listened over the Internet to
-# 
 # http://media.enet.cu/readioreloj
-# 
 # this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
-# the time was announced as "diez cinco"--the same time as here, indicating
+# the time was announced as "diez cinco" - the same time as here, indicating
 # that has indeed switched to DST. Assume second Sunday from 2009 forward.
 
 # From Steffen Thorsen (2011-03-08):
@@ -2810,42 +2732,30 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # changed at all).
 #
 # Source:
-# 
 # http://granma.co.cu/2011/03/08/nacional/artic01.html
-# 
 #
 # Our info:
-# 
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html
-# 
 #
 # From Steffen Thorsen (2011-10-30)
 # Cuba will end DST two weeks later this year. Instead of going back
 # tonight, it has been delayed to 2011-11-13 at 01:00.
 #
 # One source (Spanish)
-# 
 # http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html
-# 
 #
 # Our page:
-# 
 # http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
-# 
 #
 # From Steffen Thorsen (2012-03-01)
 # According to Radio Reloj, Cuba will start DST on Midnight between March
 # 31 and April 1.
 #
 # Radio Reloj has the following info (Spanish):
-# 
 # http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
-# 
 #
 # Our info on it:
-# 
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
-# 
 
 # From Steffen Thorsen (2012-11-03):
 # Radio Reloj and many other sources report that Cuba is changing back
@@ -2901,7 +2811,7 @@ Zone	America/Havana	-5:29:28 -	LMT	1890
 			-5:00	Cuba	C%sT
 
 # Dominica
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Dominican Republic
 
@@ -2934,8 +2844,8 @@ Rule	DR	1972	1974	-	Jan	21	0:00	0	S
 Zone America/Santo_Domingo -4:39:36 -	LMT	1890
 			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
 			-5:00	DR	E%sT	1974 Oct 27
-			-4:00	-	AST	2000 Oct 29 02:00
-			-5:00	US	E%sT	2000 Dec  3 01:00
+			-4:00	-	AST	2000 Oct 29  2:00
+			-5:00	US	E%sT	2000 Dec  3  1:00
 			-4:00	-	AST
 
 # El Salvador
@@ -2946,20 +2856,20 @@ Rule	Salv	1987	1988	-	Sep	lastSun	0:00	0	S
 # There are too many San Salvadors elsewhere, so use America/El_Salvador
 # instead of America/San_Salvador.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
+Zone America/El_Salvador -5:56:48 -	LMT	1921 # San Salvador
 			-6:00	Salv	C%sT
 
 # Grenada
 # Guadeloupe
-# St Barthelemy
+# St Barthélemy
 # St Martin (French part)
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Guatemala
 #
 # From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
 # Diario Co Latino, at
-# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
+# ,
 # says in an article dated 2006-04-19 that the Guatemalan government had
 # decided on that date to advance official time by 60 minutes, to lessen the
 # impact of the elevated cost of oil....  Daylight saving time will last from
@@ -2967,7 +2877,7 @@ Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
 # From Paul Eggert (2006-06-22):
 # The Ministry of Energy and Mines, press release CP-15/2006
 # (2006-04-19), says DST ends at 24:00.  See
-# .
+# http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Guat	1973	only	-	Nov	25	0:00	1:00	D
@@ -2984,11 +2894,10 @@ Zone America/Guatemala	-6:02:04 -	LMT	1918 Oct 5
 
 # Haiti
 # From Gwillim Law (2005-04-15):
-# Risto O. Nykanen wrote me that Haiti is now on DST.
-# I searched for confirmation, and I found a
-#  press release
+# Risto O. Nykänen wrote me that Haiti is now on DST.
+# I searched for confirmation, and I found a press release
 # on the Web page of the Haitian Consulate in Chicago (2005-03-31),
-# .  Translated from French, it says:
+# .  Translated from French, it says:
 #
 #  "The Prime Minister's Communication Office notifies the public in general
 #   and the press in particular that, following a decision of the Interior
@@ -3065,14 +2974,14 @@ Zone America/Port-au-Prince -4:49:20 -	LMT	1890
 #  that Manuel Zelaya, the president
 # of Honduras, refused to back down on this.
 
-# From Jesper Norgaard Welen (2006-08-08):
+# From Jesper Nørgaard Welen (2006-08-08):
 # It seems that Honduras has returned from DST to standard time this Monday at
 # 00:00 hours (prolonging Sunday to 25 hours duration).
 # http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
 
 # From Paul Eggert (2006-08-08):
-# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
-# .
+# Also see Diario El Heraldo, The country returns to standard time (2006-08-08).
+# http://www.elheraldo.hn/nota.php?nid=54941&sec=12
 # It mentions executive decree 18-2006.
 
 # From Steffen Thorsen (2006-08-17):
@@ -3100,22 +3009,22 @@ Zone America/Tegucigalpa -5:48:52 -	LMT	1921 Apr
 # unspecified official document, and says "This time is used throughout the
 # island".  Go with Milne.  Round to the nearest second as required by zic.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Jamaica	-5:07:11 -	LMT	1890		# Kingston
+Zone	America/Jamaica	-5:07:11 -	LMT	1890        # Kingston
 			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	-	EST	1974 Apr 28 2:00
+			-5:00	-	EST	1974 Apr 28  2:00
 			-5:00	US	E%sT	1984
 			-5:00	-	EST
 
 # Martinique
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
-			-4:04:20 -	FFMT	1911 May     # Fort-de-France MT
+Zone America/Martinique	-4:04:20 -      LMT	1890        # Fort-de-France
+			-4:04:20 -	FFMT	1911 May    # Fort-de-France MT
 			-4:00	-	AST	1980 Apr  6
 			-4:00	1:00	ADT	1980 Sep 28
 			-4:00	-	AST
 
 # Montserrat
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Nicaragua
 #
@@ -3138,27 +3047,27 @@ Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
 # From Gwillim Law (2005-04-21):
 # The Associated Press story on the time change, which can be found at
 # http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
-# and elsewhere, says (fifth paragraph, translated from Spanish):  "The last
+# and elsewhere, says (fifth paragraph, translated from Spanish): "The last
 # time that a change of clocks was applied to save energy was in the year 2000
-# during the Arnoldo Aleman administration."...
+# during the Arnoldo Alemán administration."...
 # The northamerica file says that Nicaragua has been on UTC-6 continuously
 # since December 1998.  I wasn't able to find any details of Nicaraguan time
 # changes in 2000.  Perhaps a note could be added to the northamerica file, to
 # the effect that we have indirect evidence that DST was observed in 2000.
 #
-# From Jesper Norgaard Welen (2005-11-02):
+# From Jesper Nørgaard Welen (2005-11-02):
 # Nicaragua left DST the 2005-10-02 at 00:00 (local time).
 # http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
 # (2005-09-26)
 #
-# From Jesper Norgaard Welen (2006-05-05):
+# From Jesper Nørgaard Welen (2006-05-05):
 # http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
 # (my informal translation)
-# By order of the president of the republic, Enrique Bolanos, Nicaragua
+# By order of the president of the republic, Enrique Bolaños, Nicaragua
 # advanced by sixty minutes their official time, yesterday at 2 in the
-# morning, and will stay that way until 30.th. of september.
+# morning, and will stay that way until 30th of September.
 #
-# From Jesper Norgaard Welen (2006-09-30):
+# From Jesper Nørgaard Welen (2006-09-30):
 # http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
 # My informal translation runs:
 # The natural sun time is restored in all the national territory, in that the
@@ -3176,7 +3085,7 @@ Zone	America/Managua	-5:45:08 -	LMT	1890
 			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
 			-6:00	-	CST	1973 May
 			-5:00	-	EST	1975 Feb 16
-			-6:00	Nic	C%sT	1992 Jan  1 4:00
+			-6:00	Nic	C%sT	1992 Jan  1  4:00
 			-5:00	-	EST	1992 Sep 24
 			-6:00	-	CST	1993
 			-5:00	-	EST	1997
@@ -3185,36 +3094,36 @@ Zone	America/Managua	-5:45:08 -	LMT	1890
 # Panama
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Panama	-5:18:08 -	LMT	1890
-			-5:19:36 -	CMT	1908 Apr 22   # Colon Mean Time
+			-5:19:36 -	CMT	1908 Apr 22 # Colón Mean Time
 			-5:00	-	EST
 
 # Puerto Rico
 # There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00    # San Juan
+Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00 # San Juan
 			-4:00	-	AST	1942 May  3
 			-4:00	US	A%sT	1946
 			-4:00	-	AST
 
 # St Kitts-Nevis
 # St Lucia
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # St Pierre and Miquelon
 # There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
+Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15 # St Pierre
 			-4:00	-	AST	1980 May
 			-3:00	-	PMST	1987 # Pierre & Miquelon Time
 			-3:00	Canada	PM%sT
 
 # St Vincent and the Grenadines
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Turks and Caicos
 #
 # From Chris Dunn in
-# 
+# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007
 # (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
 # daylight saving dates for time changes have been adjusted to match
 # the recent U.S. change of dates.
@@ -3227,21 +3136,23 @@ Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
 # Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
 # indicating that the normal ET rules are followed.
 #
-# From Paul Eggert (2006-05-01):
-# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
-# says they switch at midnight.  Go with Shanks & Pottenger.
+# From Paul Eggert (2014-08-19):
+# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round.  See:
+# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
+# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
 #
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	TC	1979	1986	-	Apr	lastSun	2:00	1:00	D
-Rule	TC	1979	2006	-	Oct	lastSun	2:00	0	S
-Rule	TC	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
-Rule	TC	2007	max	-	Mar	Sun>=8	2:00	1:00	D
-Rule	TC	2007	max	-	Nov	Sun>=1	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Grand_Turk	-4:44:32 -	LMT	1890
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	TC	E%sT
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
+			-5:00	-	EST	1979
+			-5:00	US	E%sT	2014 Nov  2  2:00
+			-4:00	-	AST
 
 # British Virgin Is
 # Virgin Is
-# See 'southamerica'.
+# See America/Port_of_Spain.
+
+
+# Local Variables:
+# coding: utf-8
+# End:
diff --git a/make/data/tzdata/pacificnew b/make/data/tzdata/pacificnew
index 09000c3457a9333a19a8207c57644cfc4d117621..9b9257a45fea207e960f5745b24e8a816be16e9d 100644
--- a/make/data/tzdata/pacificnew
+++ b/make/data/tzdata/pacificnew
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
diff --git a/make/data/tzdata/southamerica b/make/data/tzdata/southamerica
index 02bf3bb633268d7eb403183746a3b44e21888aca..398ec0e4f064f68105ed43bd50f56f479a59d1eb 100644
--- a/make/data/tzdata/southamerica
+++ b/make/data/tzdata/southamerica
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2006-03-22):
 # A good source for time zone historical data outside the U.S. is
@@ -35,8 +35,8 @@
 # San Diego: ACS Publications, Inc. (2003).
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # Gwillim Law writes that a good source
 # for recent time zone data is the International Air Transport
@@ -53,24 +53,24 @@
 #	I suggest the use of _Summer time_ instead of the more cumbersome
 #	_daylight-saving time_.  _Summer time_ seems to be in general use
 #	in Europe and South America.
-#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
+#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
 #	H L Mencken, _The American Language: Supplement I_ (1960), p 466
 #
 # Earlier editions of these tables also used the North American style
 # for time zones in Brazil, but this was incorrect, as Brazilians say
-# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
+# "summer time".  Reinaldo Goulart, a São Paulo businessman active in
 # the railroad sector, writes (1999-07-06):
 #	The subject of time zones is currently a matter of discussion/debate in
-#	Brazil.  Let's say that "the Brasilia time" is considered the
-#	"official time" because Brasilia is the capital city.
-#	The other three time zones are called "Brasilia time "minus one" or
+#	Brazil.  Let's say that "the Brasília time" is considered the
+#	"official time" because Brasília is the capital city.
+#	The other three time zones are called "Brasília time "minus one" or
 #	"plus one" or "plus two".  As far as I know there is no such
 #	name/designation as "Eastern Time" or "Central Time".
 # So I invented the following (English-language) abbreviations for now.
 # Corrections are welcome!
 #		std	dst
 #	-2:00	FNT	FNST	Fernando de Noronha
-#	-3:00	BRT	BRST	Brasilia
+#	-3:00	BRT	BRST	Brasília
 #	-4:00	AMT	AMST	Amazon
 #	-5:00	ACT	ACST	Acre
 
@@ -84,7 +84,7 @@
 # Argentina: first Sunday in October to first Sunday in April since 1976.
 # Double Summer time from 1969 to 1974.  Switches at midnight.
 
-# From U. S. Naval Observatory (1988-01-199):
+# From U. S. Naval Observatory (1988-01-19):
 # ARGENTINA           3 H BEHIND   UTC
 
 # From Hernan G. Otero (1995-06-26):
@@ -118,7 +118,7 @@ Rule	Arg	1988	only	-	Dec	 1	0:00	1:00	S
 # From Hernan G. Otero (1995-06-26):
 # These corrections were contributed by InterSoft Argentina S.A.,
 # obtaining the data from the:
-# Talleres de Hidrografia Naval Argentina
+# Talleres de Hidrografía Naval Argentina
 # (Argentine Naval Hydrography Institute)
 Rule	Arg	1989	1993	-	Mar	Sun>=1	0:00	0	-
 Rule	Arg	1989	1992	-	Oct	Sun>=15	0:00	1:00	S
@@ -140,13 +140,13 @@ Rule	Arg	1999	only	-	Oct	Sun>=1	0:00	1:00	S
 Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 #
 # From Peter Gradelski via Steffen Thorsen (2000-03-01):
-# We just checked with our Sao Paulo office and they say the government of
+# We just checked with our São Paulo office and they say the government of
 # Argentina decided not to become one of the countries that go on or off DST.
 # So Buenos Aires should be -3 hours from GMT at all times.
 #
-# From Fabian L. Arce Jofre (2000-04-04):
+# From Fabián L. Arce Jofré (2000-04-04):
 # The law that claimed DST for Argentina was derogated by President Fernando
-# de la Rua on March 2, 2000, because it would make people spend more energy
+# de la Rúa on March 2, 2000, because it would make people spend more energy
 # in the winter time, rather than less.  The change took effect on March 3.
 #
 # From Mariano Absatz (2001-06-06):
@@ -179,15 +179,13 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 # that Argentina will use DST next year as well, from October to
 # March, although exact rules are not given.
 #
-# From Jesper Norgaard Welen (2007-12-26)
+# From Jesper Nørgaard Welen (2007-12-26)
 # The last hurdle of Argentina DST is over, the proposal was approved in
-# the lower chamber too (Deputados) with a vote 192 for and 2 against.
+# the lower chamber too (Diputados) with a vote 192 for and 2 against.
 # By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
 # the original scanned proposal, where the dates and the zero hours are
 # clear and unambiguous...This is the article about final approval:
-# 
 # http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
-# 
 #
 # From Paul Eggert (2007-12-22):
 # For dates after mid-2008, the following rules are my guesses and
@@ -197,13 +195,8 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 # As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
 # Argentina will start DST on Sunday October 19, 2008.
 #
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
-# 
-# OR
-# 
 # http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
-# 
 
 # From Rodrigo Severo (2008-10-06):
 # Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
@@ -212,48 +205,39 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 # Hi, there is a problem with timezone-data-2008e and maybe with
 # timezone-data-2008f
 # Argentinian law [Number] 25.155 is no longer valid.
-# 
 # http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# 
 # The new one is law [Number] 26.350
-# 
 # http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
-# 
 # So there is no summer time in Argentina for now.
 
 # From Mariano Absatz (2008-10-20):
-# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina
-# From 2008-10-19 until 2009-03-15
-# 
+# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST
+# in Argentina from 2008-10-19 until 2009-03-15.
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01
-# 
 #
-# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009:
-# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz
-# and Tierra del Fuego
-# 
+
+# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer
+# 2008/2009: Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La
+# Pampa, Neuquén, Rio Negro, Chubut, Santa Cruz and Tierra del Fuego
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01
-# 
 #
-# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying
-# it will not apply DST either (even when it was not included in Decree 1705/2008)
-# 
+# Press release 235 dated Saturday October 18th, from the Government of the
+# Province of Jujuy saying it will not apply DST either (even when it was not
+# included in Decree 1705/2008).
 # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
-# 
 
 # From fullinet (2009-10-18):
 # As announced in
-# 
 # http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
-# 
-# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
+# (an official .gob.ar) under title: "Sin Cambio de Hora"
+# (English: "No hour change").
 #
-# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
-# oficial, decision que estaba en estudio para su implementacion el
-# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
-# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
-# la modificacion del huso horario, ya que 2009 nos encuentra con
-# crecimiento en la produccion y distribucion energetica."
+# "Por el momento, el Gobierno Nacional resolvió no modificar la hora
+# oficial, decisión que estaba en estudio para su implementación el
+# domingo 18 de octubre. Desde el Ministerio de Planificación se anunció
+# que la Argentina hoy, en estas condiciones meteorológicas, no necesita
+# la modificación del huso horario, ya que 2009 nos encuentra con
+# crecimiento en la producción y distribución energética."
 
 Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
 Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
@@ -267,10 +251,10 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # It's Law No. 7,210.  This change is due to a public power emergency, so for
 # now we'll assume it's for this year only.
 #
-# From Paul Eggert (2006-03-22):
-# 
-# Hora de verano para la Republica Argentina (2003-06-08)
-#  says that standard time in Argentina from 1894-10-31
+# From Paul Eggert (2014-08-09):
+# Hora de verano para la República Argentina
+# http://buenasiembra.com.ar/esoterismo/astrologia/hora-de-verano-de-la-republica-argentina-27.html
+# says that standard time in Argentina from 1894-10-31
 # to 1920-05-01 was -4:16:48.25.  Go with this more-precise value
 # over Shanks & Pottenger.
 #
@@ -285,10 +269,10 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # time in October 17th.
 #
 # Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
-# Tierra del Fuego, Tucuman.
+# Tierra del Fuego, Tucumán.
 #
 # From Mariano Absatz (2004-06-14):
-# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
+# ... this weekend, the Province of Tucumán decided it'd go back to UTC-03:00
 # yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
 # annoyance with the change is much higher than the power savings obtained....
 #
@@ -323,49 +307,38 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # Here are articles that Argentina Province San Luis is planning to end DST
 # as earlier as upcoming Monday January 21, 2008 or February 2008:
 #
-# Provincia argentina retrasa reloj y marca diferencia con resto del pais
+# Provincia argentina retrasa reloj y marca diferencia con resto del país
 # (Argentine Province delayed clock and mark difference with the rest of the
 # country)
-# 
 # http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
-# 
 #
 # Es inminente que en San Luis atrasen una hora los relojes
 # (It is imminent in San Luis clocks one hour delay)
-# 
-# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
-# 
-#
-# 
+# http://www.lagaceta.com.ar/nota/253414/Economia/Es-inminente-que-en-San-Luis-atrasen-una-hora-los-relojes.html
 # http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
-# 
 
-# From Jesper Norgaard Welen (2008-01-18):
+# From Jesper Nørgaard Welen (2008-01-18):
 # The page of the San Luis provincial government
-# 
 # http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
-# 
 # confirms what Alex Krivenyshev has earlier sent to the tz
 # emailing list about that San Luis plans to return to standard
 # time much earlier than the rest of the country. It also
 # confirms that upon request the provinces San Juan and Mendoza
 # refused to follow San Luis in this change.
 #
-# The change is supposed to take place Monday the 21.st at 0:00
+# The change is supposed to take place Monday the 21st at 0:00
 # hours. As far as I understand it if this goes ahead, we need
 # a new timezone for San Luis (although there are also documented
 # independent changes in the southamerica file of San Luis in
 # 1990 and 1991 which has not been confirmed).
 
-# From Jesper Norgaard Welen (2008-01-25):
+# From Jesper Nørgaard Welen (2008-01-25):
 # Unfortunately the below page has become defunct, about the San Luis
 # time change. Perhaps because it now is part of a group of pages "Most
 # important pages of 2008."
 #
 # You can use
-# 
 # http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
-# 
 # instead it seems. Or use "Buscador" from the main page of the San Luis
 # government, and fill in "huso" and click OK, and you will get 3 pages
 # from which the first one is identical to the above.
@@ -385,9 +358,9 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # back in 2004, when these provinces changed to UTC-4 for a few days, I
 # mailed them personally and never got an answer).
 
-# From Paul Eggert (2008-06-30):
-# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
-# from the IATA otherwise.  As noted below, Shanks & Pottenger say that
+# From Paul Eggert (2014-08-12):
+# Unless otherwise specified, data entries are from Shanks & Pottenger through
+# 1992, from the IATA otherwise.  As noted below, Shanks & Pottenger say that
 # America/Cordoba split into 6 subregions during 1991/1992, one of which
 # was America/San_Luis, but we haven't verified this yet so for now we'll
 # keep America/Cordoba a single region rather than splitting it into the
@@ -399,14 +372,9 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # to utc-04:00 until the second Saturday in October...
 #
 # The press release is at
-# 
 # http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
-# 
-# (I couldn't find the decree, but
-# 
-# www.sanluis.gov.ar
-# 
-# is the official page for the Province Government).
+# (I couldn't find the decree, but www.sanluis.gov.ar
+# is the official page for the Province Government.)
 #
 # There's also a note in only one of the major national papers ...
 # http://www.lanacion.com.ar/nota.asp?nota_id=1107912
@@ -423,9 +391,7 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # ...the Province of San Luis is a case in itself.
 #
 # The Law at
-# 
 # is ambiguous because establishes a calendar from the 2nd Sunday in
 # October at 0:00 thru the 2nd Saturday in March at 24:00 and the
 # complement of that starting on the 2nd Sunday of March at 0:00 and
@@ -454,19 +420,15 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # ...
 
 # From Alexander Krivenyshev (2010-04-09):
-# According to news reports from El Diario de la Republica Province San
+# According to news reports from El Diario de la República Province San
 # Luis, Argentina (standard time UTC-04) will keep Daylight Saving Time
-# after April 11, 2010--will continue to have same time as rest of
+# after April 11, 2010 - will continue to have same time as rest of
 # Argentina (UTC-3) (no DST).
 #
-# Confirmaron la prórroga del huso horario de verano (Spanish)
-# 
+# Confirmaron la prórroga del huso horario de verano (Spanish)
 # http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9
-# 
 # or (some English translation):
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_argentina08.html
-# 
 
 # From Mariano Absatz (2010-04-12):
 # yes...I can confirm this...and given that San Luis keeps calling
@@ -478,7 +440,7 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # Perhaps San Luis operates on the legal fiction that it is at UTC-4
 # with perpetual summer time, but ordinary usage typically seems to
 # just say it's at UTC-3; see, for example,
-# .
+# http://es.wikipedia.org/wiki/Hora_oficial_argentina
 # We've documented similar situations as being plain changes to
 # standard time, so let's do that here too.  This does not change UTC
 # offsets, only tm_isdst and the time zone abbreviations.  One minor
@@ -486,20 +448,20 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # setting for time stamps past 2038.
 
 # From Paul Eggert (2013-02-21):
-# Milne says Cordoba time was -4:16:48.2.  Round to the nearest second.
+# Milne says Córdoba time was -4:16:48.2.  Round to the nearest second.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 #
 # Buenos Aires (BA), Capital Federal (CF),
-Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Buenos_Aires -3:53:48 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN),
+# Córdoba (CB), Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN),
 # Chaco (CC), Formosa (FM), Santiago del Estero (SE)
 #
 # Shanks & Pottenger also make the following claims, which we haven't verified:
@@ -519,7 +481,7 @@ Zone America/Argentina/Cordoba -4:16:48 - LMT	1894 Oct 31
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
+# Salta (SA), La Pampa (LP), Neuquén (NQ), Rio Negro (RN)
 Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -531,7 +493,7 @@ Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tucuman (TM)
+# Tucumán (TM)
 Zone America/Argentina/Tucuman -4:20:52 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -642,8 +604,8 @@ Zone America/Argentina/San_Luis -4:25:24 - LMT	1894 Oct 31
 			-3:00	-	ART
 #
 # Santa Cruz (SC)
-Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -653,9 +615,9 @@ Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
-Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+# Tierra del Fuego, Antártida e Islas del Atlántico Sur (TF)
+Zone America/Argentina/Ushuaia -4:33:12 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -686,13 +648,13 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From IATA SSIM (1996-02):
 # _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
-# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
-# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
+# Santa Catarina (SC), Paraná (PR), São Paulo (SP), Rio de Janeiro (RJ),
+# Espírito Santo (ES), Minas Gerais (MG), Bahia (BA), Goiás (GO),
 # Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
 # [The last three states are new to this issue of the IATA SSIM.]
 
 # From Gwillim Law (1996-10-07):
-# Geography, history (Tocantins was part of Goias until 1989), and other
+# Geography, history (Tocantins was part of Goiás until 1989), and other
 # sources of time zone information lead me to believe that AL, SE, and TO were
 # always in BR1, and so the only change was whether or not they observed DST....
 # The earliest issue of the SSIM I have is 2/91.  Each issue from then until
@@ -706,16 +668,14 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # However, some conclusions can be drawn from another IATA manual: the Airline
 # Coding Directory, which lists close to 400 airports in Brazil.  For each
 # airport it gives a time zone which is coded to the SSIM.  From that
-# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
-# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
-# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
+# information, I'm led to conclude that the states of Amapá (AP), Ceará (CE),
+# Maranhão (MA), Paraíba (PR), Pernambuco (PE), Piauí (PI), and Rio Grande do
+# Norte (RN), and the eastern part of Pará (PA) are all in BR1 without DST.
 
 # From Marcos Tadeu (1998-09-27):
-# 
-# Brazilian official page
-# 
+# Brazilian official page 
 
-# From Jesper Norgaard (2000-11-03):
+# From Jesper Nørgaard (2000-11-03):
 # [For an official list of which regions in Brazil use which time zones, see:]
 # http://pcdsh01.on.br/Fusbr.htm
 # http://pcdsh01.on.br/Fusbrhv.htm
@@ -748,13 +708,13 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Paul Schulze (2008-06-24):
 # ...by law number 11.662 of April 24, 2008 (published in the "Diario
-# Oficial da Uniao"...) in Brazil there are changes in the timezones,
+# Oficial da União"...) in Brazil there are changes in the timezones,
 # effective today (00:00am at June 24, 2008) as follows:
 #
-# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
+# a) The timezone UTC+5 is extinguished, with all the Acre state and the
 # part of the Amazonas state that had this timezone now being put to the
 # timezone UTC+4
-# b) The whole Para state now is put at timezone UTC+3, instead of just
+# b) The whole Pará state now is put at timezone UTC+3, instead of just
 # part of it, as was before.
 #
 # This change follows a proposal of senator Tiao Viana of Acre state, that
@@ -767,13 +727,11 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Rodrigo Severo (2008-06-24):
 # Just correcting the URL:
-# 
 # https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
-# 
 #
 # As a result of the above Decree I believe the America/Rio_Branco
 # timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
-# be created to represent the...west side of the Para State. I
+# be created to represent the...west side of the Pará State. I
 # suggest this new timezone be called Santarem as the most
 # important/populated city in the affected area.
 #
@@ -782,19 +740,16 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Alex Krivenyshev (2008-06-24):
 # This is a quick reference page for New and Old Brazil Time Zones map.
-# 
 # http://www.worldtimezone.com/brazil-time-new-old.php
-# 
 #
-# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
-# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
-# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
+# - 4 time zones replaced by 3 time zones - eliminating time zone UTC-05
+# (state Acre and the part of the Amazonas will be UTC/GMT-04) - western
+# part of Par state is moving to one timezone UTC-03 (from UTC-04).
 
 # From Paul Eggert (2002-10-10):
 # The official decrees referenced below are mostly taken from
-# 
-# Decretos sobre o Horario de Verao no Brasil
-# .
+# Decretos sobre o Horário de Verão no Brasil.
+# http://pcdsh01.on.br/DecHV.html
 
 # From Steffen Thorsen (2008-08-29):
 # As announced by the government and many newspapers in Brazil late
@@ -806,25 +761,17 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # It has not yet been posted to http://pcdsh01.on.br/DecHV.html
 #
 # An official page about it:
-# 
 # http://www.mme.gov.br/site/news/detail.do?newsId=16722
-# 
 # Note that this link does not always work directly, but must be accessed
 # by going to
-# 
 # http://www.mme.gov.br/first
-# 
 #
 # One example link that works directly:
-# 
 # http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
 # (Portuguese)
-# 
 #
 # We have a written a short article about it as well:
-# 
 # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
-# 
 #
 # From Alexander Krivenyshev (2011-10-04):
 # State Bahia will return to Daylight savings time this year after 8 years off.
@@ -832,17 +779,12 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # television station in Salvador.
 
 # In Portuguese:
-# 
 # http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
-#  and
-# 
 # http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
-# 
 
 # From Guilherme Bernardes Rodrigues (2011-10-07):
 # There is news in the media, however there is still no decree about it.
-# I just send a e-mail to Zulmira Brandao at
-# http://pcdsh01.on.br/ the
+# I just send a e-mail to Zulmira Brandao at http://pcdsh01.on.br/ the
 # official agency about time in Brazil, and she confirmed that the old rule is
 # still in force.
 
@@ -854,9 +796,7 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 #
 # DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
 # Link :
-# 
 # http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
-# 
 
 # From Kelley Cook (2012-10-16):
 # The governor of state of Bahia in Brazil announced on Thursday that
@@ -884,42 +824,42 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # For now, assume western Amazonas will change as well.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Decree 20,466 (1931-10-01)
-# Decree 21,896 (1932-01-10)
+# Decree 20,466  (1931-10-01)
+# Decree 21,896  (1932-01-10)
 Rule	Brazil	1931	only	-	Oct	 3	11:00	1:00	S
 Rule	Brazil	1932	1933	-	Apr	 1	 0:00	0	-
 Rule	Brazil	1932	only	-	Oct	 3	 0:00	1:00	S
-# Decree 23,195 (1933-10-10)
+# Decree 23,195  (1933-10-10)
 # revoked DST.
-# Decree 27,496 (1949-11-24)
-# Decree 27,998 (1950-04-13)
+# Decree 27,496  (1949-11-24)
+# Decree 27,998  (1950-04-13)
 Rule	Brazil	1949	1952	-	Dec	 1	 0:00	1:00	S
 Rule	Brazil	1950	only	-	Apr	16	 1:00	0	-
 Rule	Brazil	1951	1952	-	Apr	 1	 0:00	0	-
-# Decree 32,308 (1953-02-24)
+# Decree 32,308  (1953-02-24)
 Rule	Brazil	1953	only	-	Mar	 1	 0:00	0	-
-# Decree 34,724 (1953-11-30)
+# Decree 34,724  (1953-11-30)
 # revoked DST.
-# Decree 52,700 (1963-10-18)
+# Decree 52,700  (1963-10-18)
 # established DST from 1963-10-23 00:00 to 1964-02-29 00:00
 # in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
-# Decree 53,071 (1963-12-03)
+# Decree 53,071  (1963-12-03)
 # extended the above decree to all of the national territory on 12-09.
 Rule	Brazil	1963	only	-	Dec	 9	 0:00	1:00	S
-# Decree 53,604 (1964-02-25)
+# Decree 53,604  (1964-02-25)
 # extended summer time by one day to 1964-03-01 00:00 (start of school).
 Rule	Brazil	1964	only	-	Mar	 1	 0:00	0	-
-# Decree 55,639 (1965-01-27)
+# Decree 55,639  (1965-01-27)
 Rule	Brazil	1965	only	-	Jan	31	 0:00	1:00	S
 Rule	Brazil	1965	only	-	Mar	31	 0:00	0	-
-# Decree 57,303 (1965-11-22)
+# Decree 57,303  (1965-11-22)
 Rule	Brazil	1965	only	-	Dec	 1	 0:00	1:00	S
-# Decree 57,843 (1966-02-18)
+# Decree 57,843  (1966-02-18)
 Rule	Brazil	1966	1968	-	Mar	 1	 0:00	0	-
 Rule	Brazil	1966	1967	-	Nov	 1	 0:00	1:00	S
-# Decree 63,429 (1968-10-15)
+# Decree 63,429  (1968-10-15)
 # revoked DST.
-# Decree 91,698 (1985-09-27)
+# Decree 91,698  (1985-09-27)
 Rule	Brazil	1985	only	-	Nov	 2	 0:00	1:00	S
 # Decree 92,310 (1986-01-21)
 # Decree 92,463 (1986-03-13)
@@ -927,42 +867,42 @@ Rule	Brazil	1986	only	-	Mar	15	 0:00	0	-
 # Decree 93,316 (1986-10-01)
 Rule	Brazil	1986	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1987	only	-	Feb	14	 0:00	0	-
-# Decree 94,922 (1987-09-22)
+# Decree 94,922  (1987-09-22)
 Rule	Brazil	1987	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1988	only	-	Feb	 7	 0:00	0	-
-# Decree 96,676 (1988-09-12)
+# Decree 96,676  (1988-09-12)
 # except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
 Rule	Brazil	1988	only	-	Oct	16	 0:00	1:00	S
 Rule	Brazil	1989	only	-	Jan	29	 0:00	0	-
-# Decree 98,077 (1989-08-21)
+# Decree 98,077  (1989-08-21)
 # with the same exceptions
 Rule	Brazil	1989	only	-	Oct	15	 0:00	1:00	S
 Rule	Brazil	1990	only	-	Feb	11	 0:00	0	-
-# Decree 99,530 (1990-09-17)
+# Decree 99,530  (1990-09-17)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
 # Decree 99,629 (1990-10-19) adds BA, MT.
 Rule	Brazil	1990	only	-	Oct	21	 0:00	1:00	S
 Rule	Brazil	1991	only	-	Feb	17	 0:00	0	-
-# Unnumbered decree (1991-09-25)
+# Unnumbered decree  (1991-09-25)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
 Rule	Brazil	1991	only	-	Oct	20	 0:00	1:00	S
 Rule	Brazil	1992	only	-	Feb	 9	 0:00	0	-
-# Unnumbered decree (1992-10-16)
+# Unnumbered decree  (1992-10-16)
 # adopted by same states.
 Rule	Brazil	1992	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1993	only	-	Jan	31	 0:00	0	-
-# Decree 942 (1993-09-28)
+# Decree 942  (1993-09-28)
 # adopted by same states, plus AM.
-# Decree 1,252 (1994-09-22;
+# Decree 1,252  (1994-09-22;
 # web page corrected 2004-01-07) adopted by same states, minus AM.
-# Decree 1,636 (1995-09-14)
+# Decree 1,636  (1995-09-14)
 # adopted by same states, plus MT and TO.
-# Decree 1,674 (1995-10-13)
+# Decree 1,674  (1995-10-13)
 # adds AL, SE.
 Rule	Brazil	1993	1995	-	Oct	Sun>=11	 0:00	1:00	S
 Rule	Brazil	1994	1995	-	Feb	Sun>=15	 0:00	0	-
 Rule	Brazil	1996	only	-	Feb	11	 0:00	0	-
-# Decree 2,000 (1996-09-04)
+# Decree 2,000  (1996-09-04)
 # adopted by same states, minus AL, SE.
 Rule	Brazil	1996	only	-	Oct	 6	 0:00	1:00	S
 Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
@@ -975,53 +915,51 @@ Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
 #
 # Decree 2,317 (1997-09-04), adopted by same states.
 Rule	Brazil	1997	only	-	Oct	 6	 0:00	1:00	S
-# Decree 2,495
+# Decree 2,495 
 # (1998-02-10)
 Rule	Brazil	1998	only	-	Mar	 1	 0:00	0	-
-# Decree 2,780 (1998-09-11)
+# Decree 2,780  (1998-09-11)
 # adopted by the same states as before.
 Rule	Brazil	1998	only	-	Oct	11	 0:00	1:00	S
 Rule	Brazil	1999	only	-	Feb	21	 0:00	0	-
-# Decree 3,150
+# Decree 3,150 
 # (1999-08-23) adopted by same states.
-# Decree 3,188 (1999-09-30)
+# Decree 3,188  (1999-09-30)
 # adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
 Rule	Brazil	1999	only	-	Oct	 3	 0:00	1:00	S
 Rule	Brazil	2000	only	-	Feb	27	 0:00	0	-
-# Decree 3,592 (2000-09-06)
+# Decree 3,592  (2000-09-06)
 # adopted by the same states as before.
-# Decree 3,630 (2000-10-13)
+# Decree 3,630  (2000-10-13)
 # repeals DST in PE and RR, effective 2000-10-15 00:00.
-# Decree 3,632 (2000-10-17)
+# Decree 3,632  (2000-10-17)
 # repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
-# Decree 3,916
+# Decree 3,916 
 # (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
 Rule	Brazil	2000	2001	-	Oct	Sun>=8	 0:00	1:00	S
 Rule	Brazil	2001	2006	-	Feb	Sun>=15	 0:00	0	-
 # Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
-# 4,399
+# 4,399 
 Rule	Brazil	2002	only	-	Nov	 3	 0:00	1:00	S
 # Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
-# 4,844
+# 4,844 
 Rule	Brazil	2003	only	-	Oct	19	 0:00	1:00	S
 # Decree 5,223 (2004-10-01) reestablishes DST in MT.
-# 5,223
+# 5,223 
 Rule	Brazil	2004	only	-	Nov	 2	 0:00	1:00	S
-# Decree 5,539 (2005-09-19),
+# Decree 5,539  (2005-09-19),
 # adopted by the same states as before.
 Rule	Brazil	2005	only	-	Oct	16	 0:00	1:00	S
-# Decree 5,920 (2006-10-03),
+# Decree 5,920  (2006-10-03),
 # adopted by the same states as before.
 Rule	Brazil	2006	only	-	Nov	 5	 0:00	1:00	S
 Rule	Brazil	2007	only	-	Feb	25	 0:00	0	-
-# Decree 6,212 (2007-09-26),
+# Decree 6,212  (2007-09-26),
 # adopted by the same states as before.
 Rule	Brazil	2007	only	-	Oct	Sun>=8	 0:00	1:00	S
 # From Frederico A. C. Neves (2008-09-10):
 # According to this decree
-# 
 # http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
-# 
 # [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
 # 3rd Feb Sunday. There is an exception on the return date when this is
 # the Carnival Sunday then the return date will be the next Sunday...
@@ -1056,29 +994,29 @@ Zone America/Noronha	-2:09:40 -	LMT	1914
 			-2:00	Brazil	FN%sT	2002 Oct  1
 			-2:00	-	FNT
 # Other Atlantic islands have no permanent settlement.
-# These include Trindade and Martin Vaz (administratively part of ES),
-# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
+# These include Trindade and Martim Vaz (administratively part of ES),
+# Rocas Atoll (RN), and the St Peter and St Paul Archipelago (PE).
 # Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
 # it also included the Penedos.
 #
-# Amapa (AP), east Para (PA)
-# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
-# The division between east and west Para is the river Xingu.
+# Amapá (AP), east Pará (PA)
+# East Pará includes Belém, Marabá, Serra Norte, and São Félix do Xingu.
+# The division between east and west Pará is the river Xingu.
 # In the north a very small part from the river Javary (now Jari I guess,
-# the border with Amapa) to the Amazon, then to the Xingu.
+# the border with Amapá) to the Amazon, then to the Xingu.
 Zone America/Belem	-3:13:56 -	LMT	1914
 			-3:00	Brazil	BR%sT	1988 Sep 12
 			-3:00	-	BRT
 #
-# west Para (PA)
-# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
+# west Pará (PA)
+# West Pará includes Altamira, Óbidos, Prainha, Oriximiná, and Santarém.
 Zone America/Santarem	-3:38:48 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
-			-4:00	-	AMT	2008 Jun 24 00:00
+			-4:00	-	AMT	2008 Jun 24  0:00
 			-3:00	-	BRT
 #
-# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
-# Paraiba (PB)
+# Maranhão (MA), Piauí (PI), Ceará (CE), Rio Grande do Norte (RN),
+# Paraíba (PB)
 Zone America/Fortaleza	-2:34:00 -	LMT	1914
 			-3:00	Brazil	BR%sT	1990 Sep 17
 			-3:00	-	BRT	1999 Sep 30
@@ -1125,11 +1063,11 @@ Zone America/Bahia	-2:34:04 -	LMT	1914
 			-3:00	Brazil	BR%sT	2012 Oct 21
 			-3:00	-	BRT
 #
-# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
-# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
+# Goiás (GO), Distrito Federal (DF), Minas Gerais (MG),
+# Espírito Santo (ES), Rio de Janeiro (RJ), São Paulo (SP), Paraná (PR),
 # Santa Catarina (SC), Rio Grande do Sul (RS)
 Zone America/Sao_Paulo	-3:06:28 -	LMT	1914
-			-3:00	Brazil	BR%sT	1963 Oct 23 00:00
+			-3:00	Brazil	BR%sT	1963 Oct 23  0:00
 			-3:00	1:00	BRST	1964
 			-3:00	Brazil	BR%sT
 #
@@ -1143,7 +1081,7 @@ Zone America/Cuiaba	-3:44:20 -	LMT	1914
 			-4:00	-	AMT	2004 Oct  1
 			-4:00	Brazil	AM%sT
 #
-# Rondonia (RO)
+# Rondônia (RO)
 Zone America/Porto_Velho -4:15:36 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
 			-4:00	-	AMT
@@ -1155,7 +1093,7 @@ Zone America/Boa_Vista	-4:02:40 -	LMT	1914
 			-4:00	Brazil	AM%sT	2000 Oct 15
 			-4:00	-	AMT
 #
-# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
+# east Amazonas (AM): Boca do Acre, Jutaí, Manaus, Floriano Peixoto
 # The great circle line from Tabatinga to Porto Acre divides
 # east from west Amazonas.
 Zone America/Manaus	-4:00:04 -	LMT	1914
@@ -1165,19 +1103,19 @@ Zone America/Manaus	-4:00:04 -	LMT	1914
 			-4:00	-	AMT
 #
 # west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
-#	Eirunepe, Envira, Ipixuna
+#	Eirunepé, Envira, Ipixuna
 Zone America/Eirunepe	-4:39:28 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
 			-5:00	-	ACT	1993 Sep 28
 			-5:00	Brazil	AC%sT	1994 Sep 22
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 #
 # Acre (AC)
 Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 
@@ -1198,66 +1136,54 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 # From Oscar van Vlijmen (2006-10-08):
 # http://www.horaoficial.cl/cambio.htm
 
-# From Jesper Norgaard Welen (2006-10-08):
+# From Jesper Nørgaard Welen (2006-10-08):
 # I think that there are some obvious mistakes in the suggested link
 # from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
 # ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
 # (they should have been 1990-09-15 and 1990-09-16 respectively), but
 # anyhow it clears up some doubts too.
 
-# From Paul Eggert (2006-12-27):
-# The following data for Chile and America/Santiago are from
+# From Paul Eggert (2014-08-12):
+# The following data entries for Chile and America/Santiago are from
 #  (2006-09-20), transcribed by
-# Jesper Norgaard Welen.  The data for Pacific/Easter are from Shanks
+# Jesper Nørgaard Welen.  The data entries for Pacific/Easter are from Shanks
 # & Pottenger, except with DST transitions after 1932 cloned from
-# America/Santiago.  The pre-1980 Pacific/Easter data are dubious,
+# America/Santiago.  The pre-1980 Pacific/Easter data entries are dubious,
 # but we have no other source.
 
-# From German Poo-Caaman~o (2008-03-03):
+# From Germán Poo-Caamaño (2008-03-03):
 # Due to drought, Chile extends Daylight Time in three weeks.  This
 # is one-time change (Saturday 3/29 at 24:00 for America/Santiago
 # and Saturday 3/29 at 22:00 for Pacific/Easter)
 # The Supreme Decree is located at
-# 
 # http://www.shoa.cl/servicios/supremo316.pdf
-# 
 # and the instructions for 2008 are located in:
-# 
 # http://www.horaoficial.cl/cambio.htm
-# .
 
-# From Jose Miguel Garrido (2008-03-05):
+# From José Miguel Garrido (2008-03-05):
 # ...
 # You could see the announces of the change on
-# 
 # http://www.shoa.cl/noticias/2008/04hora/hora.htm
-# .
 
 # From Angel Chiang (2010-03-04):
 # Subject: DST in Chile exceptionally extended to 3 April due to earthquake
-# 
 # http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098
-# 
 # (in Spanish, last paragraph).
 #
 # This is breaking news. There should be more information available later.
 
-# From Arthur Daivd Olson (2010-03-06):
+# From Arthur David Olson (2010-03-06):
 # Angel Chiang's message confirmed by Julio Pacheco; Julio provided a patch.
 
-# From Glenn Eychaner (2011-03-02): [geychaner@mac.com]
+# From Glenn Eychaner (2011-03-02):
 # It appears that the Chilean government has decided to postpone the
 # change from summer time to winter time again, by three weeks to April
 # 2nd:
-# 
 # http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651
-# 
 #
 # This is not yet reflected in the official "cambio de hora" site, but
 # probably will be soon:
-# 
 # http://www.horaoficial.cl/cambio.htm
-# 
 
 # From Arthur David Olson (2011-03-02):
 # The emol.com article mentions a water shortage as the cause of the
@@ -1265,9 +1191,7 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 
 # From Glenn Eychaner (2011-03-28):
 # The article:
-# 
 # http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}
-# 
 #
 # In English:
 # Chile's clocks will go back an hour this year on the 7th of May instead
@@ -1298,7 +1222,7 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 # start date is 2013-09-08 00:00....
 # http://www.gob.cl/informa/2013/02/15/gobierno-anuncia-fechas-de-cambio-de-hora-para-el-ano-2013.htm
 
-# From Jose Miguel Garrido (2014-02-19):
+# From José Miguel Garrido (2014-02-19):
 # Today appeared in the Diario Oficial a decree amending the time change
 # dates to 2014.
 # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC)
@@ -1352,7 +1276,7 @@ Rule	Chile	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 # (1996-09) says 1998-03-08.  Ignore these.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Santiago	-4:42:46 -	LMT	1890
-			-4:42:46 -	SMT	1910 	    # Santiago Mean Time
+			-4:42:46 -	SMT	1910        # Santiago Mean Time
 			-5:00	-	CLT	1916 Jul  1 # Chile Time
 			-4:42:46 -	SMT	1918 Sep  1 # Santiago Mean Time
 			-4:00	-	CLT	1919 Jul  1 # Chile Time
@@ -1361,16 +1285,16 @@ Zone America/Santiago	-4:42:46 -	LMT	1890
 			-4:00	Chile	CL%sT
 Zone Pacific/Easter	-7:17:44 -	LMT	1890
 			-7:17:28 -	EMT	1932 Sep    # Easter Mean Time
-			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter I Time
+			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter Time
 			-6:00	Chile	EAS%sT
 #
-# Sala y Gomez Island is like Pacific/Easter.
-# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
-# San Felix, and Antarctic bases, are like America/Santiago.
+# Salas y Gómez Island is uninhabited.
+# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
+# and Antarctic bases, are like America/Santiago.
 
 # Colombia
 
-# Milne gives 4:56:16.4 for Bogota time in 1899; round to nearest.  He writes,
+# Milne gives 4:56:16.4 for Bogotá time in 1899; round to nearest.  He writes,
 # "A variation of fifteen minutes in the public clocks of Bogota is not rare."
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1378,37 +1302,37 @@ Rule	CO	1992	only	-	May	 3	0:00	1:00	S
 Rule	CO	1993	only	-	Apr	 4	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Bogota	-4:56:16 -	LMT	1884 Mar 13
-			-4:56:16 -	BMT	1914 Nov 23 # Bogota Mean Time
+			-4:56:16 -	BMT	1914 Nov 23 # Bogotá Mean Time
 			-5:00	CO	CO%sT	# Colombia Time
 # Malpelo, Providencia, San Andres
 # no information; probably like America/Bogota
 
-# Curacao
+# Curaçao
 
-# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
+# Milne gives 4:35:46.9 for Curaçao mean time; round to nearest.
 #
 # From Paul Eggert (2006-03-22):
 # Shanks & Pottenger say that The Bottom and Philipsburg have been at
 # -4:00 since standard time was introduced on 1912-03-02; and that
 # Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
 # 1912-02-02 to 1965-01-01.  The former is dubious, since S&P also say
-# Saba Island has been like Curacao.
+# Saba Island has been like Curaçao.
 # This all predates our 1970 cutoff, though.
 #
-# By July 2007 Curacao and St Maarten are planned to become
+# By July 2007 Curaçao and St Maarten are planned to become
 # associated states within the Netherlands, much like Aruba;
 # Bonaire, Saba and St Eustatius would become directly part of the
 # Netherlands as Kingdom Islands.  This won't affect their time zones
 # though, as far as we know.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12	# Willemstad
+Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12 # Willemstad
 			-4:30	-	ANT	1965 # Netherlands Antilles Time
 			-4:00	-	AST
 
 # From Arthur David Olson (2011-06-15):
 # use links for places with new iso3166 codes.
-# The name "Lower Prince's Quarter" is both longer than fourteen charaters
+# The name "Lower Prince's Quarter" is both longer than fourteen characters
 # and contains an apostrophe; use "Lower_Princes" below.
 
 Link	America/Curacao	America/Lower_Princes	# Sint Maarten
@@ -1416,7 +1340,7 @@ Link	America/Curacao	America/Kralendijk	# Caribbean Netherlands
 
 # Ecuador
 #
-# Milne says the Sentral and South American Telegraph Company used -5:24:15.
+# Milne says the Central and South American Telegraph Company used -5:24:15.
 #
 # From Paul Eggert (2007-03-04):
 # Apparently Ecuador had a failed experiment with DST in 1992.
@@ -1427,10 +1351,10 @@ Link	America/Curacao	America/Kralendijk	# Caribbean Netherlands
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Guayaquil	-5:19:20 -	LMT	1890
 			-5:14:00 -	QMT	1931 # Quito Mean Time
-			-5:00	-	ECT	     # Ecuador Time
+			-5:00	-	ECT	# Ecuador Time
 Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 			-5:00	-	ECT	1986
-			-6:00	-	GALT	     # Galapagos Time
+			-6:00	-	GALT	# Galápagos Time
 
 # Falklands
 
@@ -1439,7 +1363,7 @@ Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 # the IATA gives 1996-09-08.  Go with Shanks & Pottenger.
 
 # From Falkland Islands Government Office, London (2001-01-22)
-# via Jesper Norgaard:
+# via Jesper Nørgaard:
 # ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
 # April 2001 and advance one hour to summer time at 2 am on Sunday 2
 # September.  It is anticipated that the clocks will revert back at 2
@@ -1488,9 +1412,7 @@ Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 # daylight saving time.
 #
 # One source:
-# 
 # http://www.falklandnews.com/public/story.cfm?get=5914&source=3
-# 
 #
 # We have gotten this confirmed by a clerk of the legislative assembly:
 # Normally the clocks revert to Local Mean Time (UTC/GMT -4 hours) on the
@@ -1531,10 +1453,10 @@ Rule	Falk	2001	2010	-	Apr	Sun>=15	2:00	0	-
 Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
-			-3:51:24 -	SMT	1912 Mar 12  # Stanley Mean Time
-			-4:00	Falk	FK%sT	1983 May     # Falkland Is Time
+			-3:51:24 -	SMT	1912 Mar 12 # Stanley Mean Time
+			-4:00	Falk	FK%sT	1983 May    # Falkland Is Time
 			-3:00	Falk	FK%sT	1985 Sep 15
-			-4:00	Falk	FK%sT	2010 Sep 5 02:00
+			-4:00	Falk	FK%sT	2010 Sep  5  2:00
 			-3:00	-	FKST
 
 # French Guiana
@@ -1545,7 +1467,7 @@ Zone America/Cayenne	-3:29:20 -	LMT	1911 Jul
 
 # Guyana
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
+Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar    # Georgetown
 			-3:45	-	GBGT	1966 May 26 # Br Guiana Time
 			-3:45	-	GYT	1975 Jul 31 # Guyana Time
 			-3:00	-	GYT	1991
@@ -1555,8 +1477,8 @@ Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
 # Paraguay
 #
 # From Paul Eggert (2006-03-22):
-# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
-# and autumn transitions are from 00:00 -> 23:00.  Go with pre-1999
+# Shanks & Pottenger say that spring transitions are 01:00 -> 02:00,
+# and autumn transitions are 00:00 -> 23:00.  Go with pre-1999
 # editions of Shanks, and with the IATA, who say transitions occur at 00:00.
 #
 # From Waldemar Villamayor-Venialbo (2013-09-20):
@@ -1582,9 +1504,8 @@ Rule	Para	1996	only	-	Mar	 1	0:00	0	-
 # (10-01).
 #
 # Translated by Gwillim Law (2001-02-27) from
-# 
-# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
-# :
+# Noticias, a daily paper in Asunción, Paraguay (2000-10-01):
+# http://www.diarionoticias.com.py/011000/nacional/naciona1.htm
 # Starting at 0:00 today, the clock will be set forward 60 minutes, in
 # fulfillment of Decree No. 7,273 of the Executive Power....  The time change
 # system has been operating for several years.  Formerly there was a separate
@@ -1605,21 +1526,18 @@ Rule	Para	1998	2001	-	Mar	Sun>=1	0:00	0	-
 Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
 Rule	Para	2002	2003	-	Sep	Sun>=1	0:00	1:00	S
 #
-# From Jesper Norgaard Welen (2005-01-02):
+# From Jesper Nørgaard Welen (2005-01-02):
 # There are several sources that claim that Paraguay made
 # a timezone rule change in autumn 2004.
 # From Steffen Thorsen (2005-01-05):
 # Decree 1,867 (2004-03-05)
-# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
-# 
+# From Carlos Raúl Perasso via Jesper Nørgaard Welen (2006-10-13)
+# http://www.presidencia.gov.py/decretos/D1867.pdf
 Rule	Para	2004	2009	-	Oct	Sun>=15	0:00	1:00	S
 Rule	Para	2005	2009	-	Mar	Sun>=8	0:00	0	-
-# From Carlos Raul Perasso (2010-02-18):
-# By decree number 3958 issued yesterday (
-# 
+# From Carlos Raúl Perasso (2010-02-18):
+# By decree number 3958 issued yesterday
 # http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf
-# 
-# )
 # Paraguay changes its DST schedule, postponing the March rule to April and
 # modifying the October date. The decree reads:
 # ...
@@ -1635,25 +1553,25 @@ Rule	Para	2010	2012	-	Apr	Sun>=8	0:00	0	-
 # Paraguay will end DST on 2013-03-24 00:00....
 # http://www.ande.gov.py/interna.php?id=1075
 #
-# From Carlos Raul Perasso (2013-03-15):
+# From Carlos Raúl Perasso (2013-03-15):
 # The change in Paraguay is now final.  Decree number 10780
 # http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.pdf
-# From Carlos Raul Perasso (2014-02-28):
+# From Carlos Raúl Perasso (2014-02-28):
 # Decree 1264 can be found at:
 # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
 Rule	Para	2013	max	-	Mar	Sun>=22	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Asuncion	-3:50:40 -	LMT	1890
-			-3:50:40 -	AMT	1931 Oct 10 # Asuncion Mean Time
-			-4:00	-	PYT	1972 Oct # Paraguay Time
+			-3:50:40 -	AMT	1931 Oct 10 # Asunción Mean Time
+			-4:00	-	PYT	1972 Oct    # Paraguay Time
 			-3:00	-	PYT	1974 Apr
 			-4:00	Para	PY%sT
 
 # Peru
 #
-# 
-# From Evelyn C. Leeper via Mark Brader (2003-10-26):
+# From Evelyn C. Leeper via Mark Brader (2003-10-26)
+# :
 # When we were in Peru in 1985-1986, they apparently switched over
 # sometime between December 29 and January 3 while we were on the Amazon.
 #
@@ -1679,7 +1597,7 @@ Zone	America/Lima	-5:08:12 -	LMT	1890
 
 # South Georgia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
+Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890 # Grytviken
 			-2:00	-	GST	# South Georgia Time
 
 # South Sandwich Is
@@ -1689,9 +1607,9 @@ Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Paramaribo	-3:40:40 -	LMT	1911
 			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
-			-3:40:36 -	PMT	1945 Oct # The capital moved?
+			-3:40:36 -	PMT	1945 Oct    # The capital moved?
 			-3:30	-	NEGT	1975 Nov 20 # Dutch Guiana Time
-			-3:30	-	SRT	1984 Oct # Suriname Time
+			-3:30	-	SRT	1984 Oct    # Suriname Time
 			-3:00	-	SRT
 
 # Trinidad and Tobago
@@ -1706,7 +1624,7 @@ Link America/Port_of_Spain America/Grenada
 Link America/Port_of_Spain America/Guadeloupe
 Link America/Port_of_Spain America/Marigot	# St Martin (French part)
 Link America/Port_of_Spain America/Montserrat
-Link America/Port_of_Spain America/St_Barthelemy
+Link America/Port_of_Spain America/St_Barthelemy # St Barthélemy
 Link America/Port_of_Spain America/St_Kitts	# St Kitts & Nevis
 Link America/Port_of_Spain America/St_Lucia
 Link America/Port_of_Spain America/St_Thomas	# Virgin Islands (US)
@@ -1765,7 +1683,7 @@ Rule	Uruguay	1990	1991	-	Oct	Sun>=21	 0:00	1:00	S
 Rule	Uruguay	1992	only	-	Oct	18	 0:00	1:00	S
 Rule	Uruguay	1993	only	-	Feb	28	 0:00	0	-
 # From Eduardo Cota (2004-09-20):
-# The uruguayan government has decreed a change in the local time....
+# The Uruguayan government has decreed a change in the local time....
 # http://www.presidencia.gub.uy/decretos/2004091502.htm
 Rule	Uruguay	2004	only	-	Sep	19	 0:00	1:00	S
 # From Steffen Thorsen (2005-03-11):
@@ -1779,14 +1697,14 @@ Rule	Uruguay	2005	only	-	Mar	27	 2:00	0	-
 # 02:00 local time, official time in Uruguay will be at GMT -2.
 Rule	Uruguay	2005	only	-	Oct	 9	 2:00	1:00	S
 Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
-# From Jesper Norgaard Welen (2006-09-06):
+# From Jesper Nørgaard Welen (2006-09-06):
 # http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
 Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
 Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
-			-3:44:44 -	MMT	1920 May  1	# Montevideo MT
-			-3:30	Uruguay	UY%sT	1942 Dec 14	# Uruguay Time
+			-3:44:44 -	MMT	1920 May  1 # Montevideo MT
+			-3:30	Uruguay	UY%sT	1942 Dec 14 # Uruguay Time
 			-3:00	Uruguay	UY%sT
 
 # Venezuela
@@ -1794,14 +1712,14 @@ Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
 # From John Stainforth (2007-11-28):
 # ... the change for Venezuela originally expected for 2007-12-31 has
 # been brought forward to 2007-12-09.  The official announcement was
-# published today in the "Gaceta Oficial de la Republica Bolivariana
-# de Venezuela, numero 38.819" (official document for all laws or
+# published today in the "Gaceta Oficial de la República Bolivariana
+# de Venezuela, número 38.819" (official document for all laws or
 # resolution publication)
 # http://www.globovision.com/news.php?nid=72208
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
 			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
-			-4:30	-	VET	1965	     # Venezuela Time
-			-4:00	-	VET	2007 Dec  9 03:00
+			-4:30	-	VET	1965        # Venezuela Time
+			-4:00	-	VET	2007 Dec  9  3:00
 			-4:30	-	VET
diff --git a/make/data/tzdata/systemv b/make/data/tzdata/systemv
index f909f9c76dbd4cfc8f9b8fa9ac1de182dfc61dcc..c7b9a888e8834e515a02f242fb633d2e09669f38 100644
--- a/make/data/tzdata/systemv
+++ b/make/data/tzdata/systemv
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
diff --git a/make/data/tzdata/zone.tab b/make/data/tzdata/zone.tab
index 7cec627fd95862053bc8c9cd5e991a1309a42f6d..45351ca848654a8c4c76ad96e0e8ed6f0495371b 100644
--- a/make/data/tzdata/zone.tab
+++ b/make/data/tzdata/zone.tab
@@ -21,39 +21,27 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# TZ zone descriptions
+# tz zone descriptions (deprecated version)
 #
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-08-14):
+# From Paul Eggert (2014-07-31):
+# This file is intended as a backward-compatibility aid for older programs.
+# New programs should use zone1970.tab.  This file is like zone1970.tab (see
+# zone1970.tab's comments), but with the following additional restrictions:
 #
-# This file contains a table where each row stands for an area that is
-# the intersection of a region identified by a country code and of a
-# zone where civil clocks have agreed since 1970.  The columns of the
-# table are as follows:
+# 1.  This file contains only ASCII characters.
+# 2.  The first data column contains exactly one country code.
 #
-# 1.  ISO 3166 2-character country code.  See the file 'iso3166.tab'.
-# 2.  Latitude and longitude of the area's principal location
-#     in ISO 6709 sign-degrees-minutes-seconds format,
-#     either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
-#     first latitude (+ is north), then longitude (+ is east).
-# 3.  Zone name used in value of TZ environment variable.
-#     Please see the 'Theory' file for how zone names are chosen.
-#     If multiple zones overlap a country, each has a row in the
-#     table, with column 1 being duplicated.
-# 4.  Comments; present if and only if the country has multiple rows.
-#
-# Columns are separated by a single tab.
-# The table is sorted first by country, then an order within the country that
-# (1) makes some geographical sense, and
-# (2) puts the most populous areas first, where that does not contradict (1).
-#
-# Lines beginning with '#' are comments.
+# Because of (2), each row stands for an area that is the intersection
+# of a region identified by a country code and of a zone where civil
+# clocks have agreed since 1970; this is a narrower definition than
+# that of zone1970.tab.
 #
 # This table is intended as an aid for users, to help them select time
-# zone data appropriate for their practical needs.  It is not intended
-# to take or endorse any position on legal or territorial claims.
+# zone data entries appropriate for their practical needs.  It is not
+# intended to take or endorse any position on legal or territorial claims.
 #
 #country-
 #code	coordinates	TZ			comments
@@ -72,7 +60,7 @@ AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
 AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
-AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
+AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Adelie Land
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-720041+0023206	Antarctica/Troll	Troll Station, Queen Maud Land
 AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
@@ -151,7 +139,7 @@ CA	+4901-08816	America/Nipigon	Eastern Time - Ontario & Quebec - places that did
 CA	+4823-08915	America/Thunder_Bay	Eastern Time - Thunder Bay, Ontario
 CA	+6344-06828	America/Iqaluit	Eastern Time - east Nunavut - most locations
 CA	+6608-06544	America/Pangnirtung	Eastern Time - Pangnirtung, Nunavut
-CA	+744144-0944945	America/Resolute	Central Standard Time - Resolute, Nunavut
+CA	+744144-0944945	America/Resolute	Central Time - Resolute, Nunavut
 CA	+484531-0913718	America/Atikokan	Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
 CA	+624900-0920459	America/Rankin_Inlet	Central Time - central Nunavut
 CA	+4953-09709	America/Winnipeg	Central Time - Manitoba & west Ontario
@@ -176,13 +164,10 @@ CH	+4723+00832	Europe/Zurich
 CI	+0519-00402	Africa/Abidjan
 CK	-2114-15946	Pacific/Rarotonga
 CL	-3327-07040	America/Santiago	most locations
-CL	-2709-10926	Pacific/Easter	Easter Island & Sala y Gomez
+CL	-2709-10926	Pacific/Easter	Easter Island
 CM	+0403+00942	Africa/Douala
-CN	+3114+12128	Asia/Shanghai	east China - Beijing, Guangdong, Shanghai, etc.
-CN	+4545+12641	Asia/Harbin	Heilongjiang (except Mohe), Jilin
-CN	+2934+10635	Asia/Chongqing	central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
-CN	+4348+08735	Asia/Urumqi	most of Tibet & Xinjiang
-CN	+3929+07559	Asia/Kashgar	west Tibet & Xinjiang
+CN	+3114+12128	Asia/Shanghai	Beijing Time
+CN	+4348+08735	Asia/Urumqi	Xinjiang Time
 CO	+0436-07405	America/Bogota
 CR	+0956-08405	America/Costa_Rica
 CU	+2308-08222	America/Havana
@@ -364,24 +349,26 @@ RE	-2052+05528	Indian/Reunion
 RO	+4426+02606	Europe/Bucharest
 RS	+4450+02030	Europe/Belgrade
 RU	+5443+02030	Europe/Kaliningrad	Moscow-01 - Kaliningrad
-RU	+5545+03735	Europe/Moscow	Moscow+00 - west Russia
-RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
-RU	+5312+05009	Europe/Samara	Moscow+00 - Samara, Udmurtia
+RU	+554521+0373704	Europe/Moscow	Moscow+00 - west Russia
 RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
+RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
+RU	+5312+05009	Europe/Samara	Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia
 RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
 RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
 RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
-RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
+RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo
 RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
 RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
+RU	+5203+11328	Asia/Chita	Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky
 RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
 RU	+623923+1353314	Asia/Khandyga	Moscow+06 - Tomponsky, Ust-Maysky
 RU	+4310+13156	Asia/Vladivostok	Moscow+07 - Amur River
 RU	+4658+14242	Asia/Sakhalin	Moscow+07 - Sakhalin Island
 RU	+643337+1431336	Asia/Ust-Nera	Moscow+07 - Oymyakonsky
-RU	+5934+15048	Asia/Magadan	Moscow+08 - Magadan
-RU	+5301+15839	Asia/Kamchatka	Moscow+08 - Kamchatka
-RU	+6445+17729	Asia/Anadyr	Moscow+08 - Bering Sea
+RU	+5934+15048	Asia/Magadan	Moscow+08 (Moscow+07 after 2014-10-26) - Magadan
+RU	+6728+15343	Asia/Srednekolymsk	Moscow+08 - E Sakha, N Kuril Is
+RU	+5301+15839	Asia/Kamchatka	Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka
+RU	+6445+17729	Asia/Anadyr	Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea
 RW	-0157+03004	Africa/Kigali
 SA	+2438+04643	Asia/Riyadh
 SB	-0932+16012	Pacific/Guadalcanal
@@ -448,13 +435,13 @@ US	+394421-1045903	America/Denver	Mountain Time
 US	+433649-1161209	America/Boise	Mountain Time - south Idaho & east Oregon
 US	+332654-1120424	America/Phoenix	Mountain Standard Time - Arizona (except Navajo)
 US	+340308-1181434	America/Los_Angeles	Pacific Time
+US	+550737-1313435	America/Metlakatla	Pacific Standard Time - Annette Island, Alaska
 US	+611305-1495401	America/Anchorage	Alaska Time
 US	+581807-1342511	America/Juneau	Alaska Time - Alaska panhandle
 US	+571035-1351807	America/Sitka	Alaska Time - southeast Alaska panhandle
 US	+593249-1394338	America/Yakutat	Alaska Time - Alaska panhandle neck
 US	+643004-1652423	America/Nome	Alaska Time - west Alaska
 US	+515248-1763929	America/Adak	Aleutian Islands
-US	+550737-1313435	America/Metlakatla	Metlakatla Time - Annette Island
 US	+211825-1575130	Pacific/Honolulu	Hawaii
 UY	-3453-05611	America/Montevideo
 UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
diff --git a/src/aix/classes/sun/awt/fontconfigs/aix.fontconfig.properties b/src/aix/classes/sun/awt/fontconfigs/aix.fontconfig.properties
index 29e7c7d9510f1724a2eb45bed44b720c831c2fce..f203f759894429775a24371c5be56a79c1cba7e3 100644
--- a/src/aix/classes/sun/awt/fontconfigs/aix.fontconfig.properties
+++ b/src/aix/classes/sun/awt/fontconfigs/aix.fontconfig.properties
@@ -24,9 +24,14 @@
 # questions.
 #
 
-# Minimal version for AIX using the standard Latin Type1 Fonts from the
-# package X11.fnt.iso_T1. These fonts are installed by default into
-# "/usr/lpp/X11/lib/X11/fonts/Type1" and sym-linked to "/usr/lib/X11/fonts/Type1"
+#
+# Portions Copyright (c) 2014 IBM Corporation
+#
+
+# This file references the standard Latin Type1 fonts from the AIX package
+# X11.fnt.iso_T1 and the Unicode TrueType fonts from X11.fnt.ucs.ttf. They
+# are located by default under "/usr/lpp/X11/lib/X11/fonts/{Type1,TrueType}"
+# and sym-linked to "/usr/lib/X11/fonts/".
 
 # Version
 
@@ -34,44 +39,381 @@ version=1
 
 # Component Font Mappings
 
-dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1
-dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1
-dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1
-dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1
+allfonts.iso10646-extB=-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2
+
+
+dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1
+dialog.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+dialog.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+dialog.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialog.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialog.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialog.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialog.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialog.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialog.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialog.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialog.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1
+dialog.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+dialog.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+dialog.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialog.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialog.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialog.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialog.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialog.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialog.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialog.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialog.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1
+dialog.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+dialog.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0
+dialog.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialog.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialog.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialog.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialog.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialog.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialog.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialog.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialog.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1
+dialog.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+dialog.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+dialog.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialog.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialog.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialog.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialog.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialog.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialog.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialog.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialog.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1
+dialoginput.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+dialoginput.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
+dialoginput.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialoginput.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialoginput.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialoginput.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialoginput.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialoginput.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialoginput.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialoginput.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialoginput.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1
+dialoginput.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+dialoginput.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
+dialoginput.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialoginput.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialoginput.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialoginput.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialoginput.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialoginput.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialoginput.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialoginput.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialoginput.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1
+dialoginput.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+dialoginput.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0
+dialoginput.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialoginput.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialoginput.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialoginput.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialoginput.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialoginput.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialoginput.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialoginput.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialoginput.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1
+dialoginput.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+dialoginput.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
+dialoginput.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+dialoginput.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+dialoginput.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+dialoginput.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+dialoginput.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+dialoginput.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+dialoginput.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+dialoginput.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+dialoginput.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1
+sansserif.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+sansserif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+sansserif.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+sansserif.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+sansserif.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+sansserif.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+sansserif.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+sansserif.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+sansserif.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+sansserif.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+sansserif.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1
+sansserif.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+sansserif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+sansserif.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+sansserif.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+sansserif.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+sansserif.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+sansserif.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+sansserif.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+sansserif.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+sansserif.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+sansserif.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1
+sansserif.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+sansserif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0
+sansserif.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+sansserif.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+sansserif.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+sansserif.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+sansserif.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+sansserif.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+sansserif.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+sansserif.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+sansserif.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1
+sansserif.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+sansserif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+sansserif.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+sansserif.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+sansserif.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+sansserif.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+sansserif.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+sansserif.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+sansserif.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+sansserif.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+sansserif.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
 
-dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1
-dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1
-dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1
-dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1
+serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1
+serif.plain.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+serif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+serif.plain.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+serif.plain.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+serif.plain.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+serif.plain.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+serif.plain.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+serif.plain.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+serif.plain.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+serif.plain.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+serif.plain.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
 
-sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1
-sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1
-sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1
-sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1
+serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1
+serif.bold.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+serif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+serif.bold.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+serif.bold.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+serif.bold.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+serif.bold.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+serif.bold.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+serif.bold.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+serif.bold.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+serif.bold.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+serif.bold.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
 
-serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1
-serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1
-serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1
-serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1
 
-monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1
-monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1
-monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1
-monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1
+serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1
+serif.italic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+serif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0
+serif.italic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+serif.italic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+serif.italic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+serif.italic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+serif.italic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+serif.italic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+serif.italic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+serif.italic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+serif.italic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1
+serif.bolditalic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
+serif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
+serif.bolditalic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+serif.bolditalic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+serif.bolditalic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+serif.bolditalic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+serif.bolditalic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+serif.bolditalic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+serif.bolditalic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+serif.bolditalic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+serif.bolditalic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1
+monospaced.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+monospaced.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
+monospaced.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+monospaced.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+monospaced.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+monospaced.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+monospaced.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+monospaced.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+monospaced.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+monospaced.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+monospaced.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1
+monospaced.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+monospaced.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
+monospaced.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+monospaced.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+monospaced.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+monospaced.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+monospaced.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+monospaced.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+monospaced.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+monospaced.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+monospaced.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1
+monospaced.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+monospaced.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0
+monospaced.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+monospaced.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+monospaced.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+monospaced.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+monospaced.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+monospaced.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+monospaced.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+monospaced.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+monospaced.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
+
+monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1
+monospaced.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
+monospaced.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
+monospaced.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
+monospaced.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
+monospaced.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
+monospaced.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
+monospaced.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
+monospaced.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
+monospaced.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
+monospaced.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
+monospaced.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
 
 # Search Sequences
 
 sequence.allfonts=latin-1
+sequence.allfonts.UTF-8=latin-1,japanese-iso10646
+# Uk_UA
+sequence.allfonts.x-IBM1124=latin-1,ukranian-ibm1124
+# Japanese
+sequence.allfonts.x-IBM943C=latin-1,japanese-x0201,japanese-x0208,japanese-udc
+sequence.allfonts.x-IBM29626C=latin-1,japanese-x0201,japanese-x0208,japanese-udc
+sequence.allfonts.UTF-8.ja=japanese-iso10646,latin-1,iso10646-extB
+# Chinese
+sequence.allfonts.x-EUC_CN=latin-1,chinese
+sequence.allfonts.GB18030=latin-1,chinese-iso10646,iso10646-extB
+sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-iso10646,iso10646-extB
+# Taiwanese
+sequence.allfonts.x-IBM964=latin-1,taiwanese-iso10646
+sequence.allfonts.Big5=latin-1,taiwanese-iso10646
+sequence.allfonts.UTF-8.zh.TW=latin-1,taiwanese-iso10646
+# Korean
+sequence.allfonts.x-IBM970=latin-1,korean
+sequence.allfonts.UTF-8.ko=latin-1,korean-iso10646
+# Thai
+sequence.allfonts.TIS-620=latin-1,thai
+sequence.allfonts.UTF-8.th=latin-1,thai
+# fallback
+sequence.fallback=thai,chinese-iso10646,taiwanese-iso10646,japanese-iso10646,korean-iso10646,iso10646-extB
+
+# Exclusion Ranges
+exclusion.japanese-iso10646=0000-00ff
+
+# Font File Names
+filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa
+filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa
+filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa
+filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa
+filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa
+filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa
+filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa
+filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa
+filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa
+filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa
+filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa
+filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa
+
+
+filename.-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2=/usr/lpp/X11/lib/X11/fonts/TrueType/MTSanXBA.ttf
+
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_t.ttf
+
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdt.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf
+filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_t.ttf
+
+filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+
+filename.-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/courth.ttf
+filename.-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/helvth.ttf
+filename.-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/timeth.ttf
+
+filename.-*-*-medium-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-bold-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-medium-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-bold-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-medium-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-*-*-bold-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-*-*-medium-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-*-*-bold-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+
+filename.-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
+filename.-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+filename.-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
+
+# AWT font path
+awtfontpath.japanese-x0201=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.japanese-x0208=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.japanese-udc=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.japanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.korean=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.korean-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.chinese=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.chinese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.taiwanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.thai=/usr/lpp/X11/lib/X11/fonts/TrueType
+awtfontpath.iso10646-extB=/usr/lpp/X11/lib/X11/fonts/TrueType
 
-filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa
-filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa
-filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa
-filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa
-filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa
-filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa
-filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa
-filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa
-filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa
-filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa
-filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa
-filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa
diff --git a/src/share/bin/java.c b/src/share/bin/java.c
index eb5c3319ab013a4e19cf5caea572cdf6bc816858..cc354ebaf40cdb6e935e649103fd252211250741 100644
--- a/src/share/bin/java.c
+++ b/src/share/bin/java.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1248,11 +1248,13 @@ NewPlatformString(JNIEnv *env, char *s)
         (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
         if (!(*env)->ExceptionOccurred(env)) {
             if (makePlatformStringMID == NULL) {
-                NULL_CHECK0(makePlatformStringMID = (*env)->GetStaticMethodID(env,
+                CHECK_JNI_RETURN_0(
+                    makePlatformStringMID = (*env)->GetStaticMethodID(env,
                         cls, "makePlatformString", "(Z[B)Ljava/lang/String;"));
             }
-            str = (*env)->CallStaticObjectMethod(env, cls,
-                    makePlatformStringMID, USE_STDERR, ary);
+            CHECK_JNI_RETURN_0(
+                str = (*env)->CallStaticObjectMethod(env, cls,
+                    makePlatformStringMID, USE_STDERR, ary));
             (*env)->DeleteLocalRef(env, ary);
             return str;
         }
@@ -1303,7 +1305,9 @@ LoadMainClass(JNIEnv *env, int mode, char *name)
                 "(ZILjava/lang/String;)Ljava/lang/Class;"));
 
     str = NewPlatformString(env, name);
-    result = (*env)->CallStaticObjectMethod(env, cls, mid, USE_STDERR, mode, str);
+    CHECK_JNI_RETURN_0(
+        result = (*env)->CallStaticObjectMethod(
+            env, cls, mid, USE_STDERR, mode, str));
 
     if (JLI_IsTraceLauncher()) {
         end   = CounterGet();
diff --git a/src/share/bin/java.h b/src/share/bin/java.h
index 83e97e60d9c50cd8396fc6f9990dc2a86b79dbaf..43450d8f51af87470ed02b1c65b4f85960833532 100644
--- a/src/share/bin/java.h
+++ b/src/share/bin/java.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -256,4 +256,47 @@ typedef struct {
 #define NULL_CHECK(NC_check_pointer) \
     NULL_CHECK_RETURN_VALUE(NC_check_pointer, )
 
+/*
+ * For JNI calls :
+ *  - check for thrown exceptions
+ *  - check for null return
+ *
+ *  JNI calls can return null and/or throw an exception.  Check for these.
+ *
+ *  : CHECK_JNI_RETURN_EXCEPTION()
+ *    return the specified RETURNVALUE if exception was generated
+ *  : CHECK_JNI_RETURN_0(JNISTATEMENT)        : check if JNISTATEMENT was successful, return 0 if not
+ *  : CHECK_JNI_RETURN_VOID(JNISTATEMENT)     : check if JNISTATEMENT was successful, return void if not
+ *  : CHECK_JNI_RETURN_VALUE(JNISTATEMENT,n)  : check if JNISTATEMENT was successful, return n if not
+ *
+ *  These macros need at least one parameter, the JNI statement [ JNISTATEMENT ].
+ *
+ *  E.G.: check the JNI statement, and specify a value to return if a failure was detected.
+ *
+ *      CHECK_JNI_RETURN_VALUE(str = (*env)->CallStaticObjectMethod(env, cls,
+ *                                               makePlatformStringMID, USE_STDERR, ary), -1);
+ */
+
+#define RETURNVOID return
+#define RETURN0 return 0
+#define RETURN(N) return (N)
+
+#define CHECK_JNI_RETURN_EXCEPTION(RETURNVALUE) \
+        if ((((*env)->ExceptionOccurred(env))!=NULL)) { \
+            RETURNVALUE; \
+        }
+
+#define CHECK_JNI_RETURN_0(JNISTATEMENT) \
+    CHECK_JNI_RETURN_EXCEPTION(RETURN0); \
+    NULL_CHECK0(JNISTATEMENT);
+
+#define CHECK_JNI_RETURN_VOID(JNISTATEMENT) \
+    CHECK_JNI_RETURN_EXCEPTION(RETURNVOID); \
+    NULL_CHECK(JNISTATEMENT);
+
+#define CHECK_JNI_RETURN_VALUE(JNISTATEMENT, NCRV_return_value) \
+    CHECK_JNI_RETURN_EXCEPTION(RETURN(NCRV_return_value)); \
+    NULL_CHECK_RETURN_VALUE(JNISTATEMENT, NCRV_return_value);
+
+
 #endif /* _JAVA_H_ */
diff --git a/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java b/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f676ee49934ecbdb60428badf33edd6d7c3c645
--- /dev/null
+++ b/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.attach;
+
+import java.io.IOException;
+
+/**
+ * Exception type to signal that an attach operation failed in the target VM.
+ *
+ * 

This exception can be thrown by the various operations of + * {@link com.sun.tools.attach.VirtualMachine} when the operation + * fails in the target VM. If there is a communication error, + * a regular IOException will be thrown. + * + * @since 1.9 + */ +@jdk.Exported +public class AttachOperationFailedException extends IOException { + + private static final long serialVersionUID = 2140308168167478043L; + + /** + * Constructs an AttachOperationFailedException with + * the specified detail message. + * + * @param s the detail message. + */ + public AttachOperationFailedException(String message) { + super(message); + } +} diff --git a/src/share/classes/com/sun/tools/attach/VirtualMachine.java b/src/share/classes/com/sun/tools/attach/VirtualMachine.java index 1bea751214769958d6cc6969a0e6f68695b2a821..d5e934a6e2d2acbd5524ed35fbee9ef748518c35 100644 --- a/src/share/classes/com/sun/tools/attach/VirtualMachine.java +++ b/src/share/classes/com/sun/tools/attach/VirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,16 +76,10 @@ import java.io.IOException; * // attach to target VM * VirtualMachine vm = VirtualMachine.attach("2177"); * - * // get system properties in target VM - * Properties props = vm.getSystemProperties(); - * - * // construct path to management agent - * String home = props.getProperty("java.home"); - * String agent = home + File.separator + "lib" + File.separator - * + "management-agent.jar"; - * - * // load agent into target VM - * vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000"); + * // start management agent + * Properties props = new Properties(); + * props.put("com.sun.management.jmxremote.port", "5000"); + * vm.startManagementAgent(props); * * // detach * vm.detach(); @@ -93,9 +87,9 @@ import java.io.IOException; *

* *

In this example we attach to a Java virtual machine that is identified by - * the process identifier 2177. The system properties from the target - * VM are then used to construct the path to a management agent which is then - * loaded into the target VM. Once loaded the client detaches from the target VM.

+ * the process identifier 2177. Then the JMX management agent is + * started in the target process using the supplied arguments. Finally, the + * client detaches from the target VM.

* *

A VirtualMachine is safe for use by multiple concurrent threads.

* @@ -564,8 +558,15 @@ public abstract class VirtualMachine { * * @return The system properties * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * * @throws IOException - * If an I/O error occurs + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. * * @see java.lang.System#getProperties * @see #loadAgentLibrary @@ -591,11 +592,80 @@ public abstract class VirtualMachine { * * @return The agent properties * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * * @throws IOException - * If an I/O error occurs + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. */ public abstract Properties getAgentProperties() throws IOException; + /** + * Starts the JMX management agent in the target virtual machine. + * + *

The configuration properties are the same as those specified on + * the command line when starting the JMX management agent. In the same + * way as on the command line, you need to specify at least the + * {@code com.sun.management.jmxremote.port} property. + * + *

See the online documentation for + * Monitoring and Management Using JMX Technology for further details. + * + * @param agentProperties + * A Properties object containing the configuration properties + * for the agent. + * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * + * @throws IOException + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. + * + * @throws IllegalArgumentException + * If keys or values in agentProperties are invalid. + * + * @throws NullPointerException + * If agentProperties is null. + * + * @since 1.8 + */ + public abstract void startManagementAgent(Properties agentProperties) throws IOException; + + /** + * Starts the local JMX management agent in the target virtual machine. + * + *

See the online documentation for + * Monitoring and Management Using JMX Technology for further details. + * + * @return The String representation of the local connector's service address. + * The value can be parsed by the + * {@link javax.management.remote.JMXServiceURL#JMXServiceURL(String)} + * constructor. + * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * + * @throws IOException + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. + * + * @since 1.8 + */ + public abstract String startLocalManagementAgent() throws IOException; + /** * Returns a hash-code value for this VirtualMachine. The hash * code is based upon the VirtualMachine's components, and satifies diff --git a/src/share/classes/java/awt/event/InputMethodEvent.java b/src/share/classes/java/awt/event/InputMethodEvent.java index cd7122d52ddb05d4838b0f8cbf36504c7ea21b09..d90e5ec5c68d58e09f5eb6cf5476d7e6ec997a2b 100644 --- a/src/share/classes/java/awt/event/InputMethodEvent.java +++ b/src/share/classes/java/awt/event/InputMethodEvent.java @@ -417,7 +417,8 @@ public class InputMethodEvent extends AWTEvent { private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); if (when == 0) { - when = getMostRecentEventTimeForSource(this.source); + // Can't use getMostRecentEventTimeForSource because source is always null during deserialization + when = EventQueue.getMostRecentEventTime(); } } diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java index d4c36bc865d1aee4d14bbed1aa479936142e217b..43c8c0e8ec73bab1159ea0e49b8cf4ab6cca0a8c 100644 --- a/src/share/classes/java/lang/Class.java +++ b/src/share/classes/java/lang/Class.java @@ -130,11 +130,15 @@ public final class Class implements java.io.Serializable, } /* - * Constructor. Only the Java Virtual Machine creates Class - * objects. + * Private constructor. Only the Java Virtual Machine creates Class objects. + * This constructor is not used and prevents the default constructor being + * generated. */ - private Class() {} - + private Class(ClassLoader loader) { + // Initialize final field for classLoader. The initialization value of non-null + // prevents future JIT optimizations from assuming this final field is null. + classLoader = loader; + } /** * Converts the object to a string. The string representation is the @@ -682,8 +686,10 @@ public final class Class implements java.io.Serializable, } // Package-private to allow ClassLoader access - native ClassLoader getClassLoader0(); + ClassLoader getClassLoader0() { return classLoader; } + // Initialized in JVM not by private constructor + private final ClassLoader classLoader; /** * Returns an array of {@code TypeVariable} objects that represent the diff --git a/src/share/classes/java/lang/invoke/BoundMethodHandle.java b/src/share/classes/java/lang/invoke/BoundMethodHandle.java index fda6be22d47ef03d2f633b6714423e8d4b2299aa..74f53e47906188490ee5fa0d38ed3d053d5c9da5 100644 --- a/src/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/src/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -26,11 +26,10 @@ package java.lang.invoke; import static jdk.internal.org.objectweb.asm.Opcodes.*; -import static java.lang.invoke.LambdaForm.basicTypes; -import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; -import java.lang.invoke.LambdaForm.Name; import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; @@ -51,89 +50,93 @@ import jdk.internal.org.objectweb.asm.Type; * * All bound arguments are encapsulated in dedicated species. */ -/* non-public */ abstract class BoundMethodHandle extends MethodHandle { +/*non-public*/ abstract class BoundMethodHandle extends MethodHandle { - /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) { + /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) { super(type, form); + assert(speciesData() == speciesData(form)); } // // BMH API and internals // - static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) { + static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) { // for some type signatures, there exist pre-defined concrete BMH classes try { switch (xtype) { - case 'L': - if (true) return bindSingle(type, form, x); // Use known fast path. - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x); - case 'I': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x)); - case 'J': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x); - case 'F': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x); - case 'D': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x); - default : throw new InternalError("unexpected xtype: " + xtype); + case L_TYPE: + return bindSingle(type, form, x); // Use known fast path. + case I_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x)); + case J_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x); + case F_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x); + case D_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x); + default : throw newInternalError("unexpected xtype: " + xtype); } } catch (Throwable t) { throw newInternalError(t); } } - static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { - return new Species_L(type, form, x); + /*non-public*/ + LambdaFormEditor editor() { + return form.editor(); } - MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) { - try { - switch (xtype) { - case 'L': return cloneExtendL(type, form, x); - case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x)); - case 'J': return cloneExtendJ(type, form, (long) x); - case 'F': return cloneExtendF(type, form, (float) x); - case 'D': return cloneExtendD(type, form, (double) x); - } - } catch (Throwable t) { - throw newInternalError(t); - } - throw new InternalError("unexpected type: " + xtype); + static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { + return Species_L.make(type, form, x); } - @Override - MethodHandle bindArgument(int pos, char basicType, Object value) { - MethodType type = type().dropParameterTypes(pos, pos+1); - LambdaForm form = internalForm().bind(1+pos, speciesData()); - return cloneExtend(type, form, basicType, value); + @Override // there is a default binder in the super class, for 'L' types only + /*non-public*/ + BoundMethodHandle bindArgumentL(int pos, Object value) { + return editor().bindArgumentL(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentI(int pos, int value) { + return editor().bindArgumentI(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentJ(int pos, long value) { + return editor().bindArgumentJ(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentF(int pos, float value) { + return editor().bindArgumentF(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentD(int pos, double value) { + return editor().bindArgumentD(this, pos, value); } @Override - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops)); - try { - return clone(srcType, form); - } catch (Throwable t) { - throw newInternalError(t); - } + BoundMethodHandle rebind() { + if (!tooComplex()) { + return this; + } + return makeReinvoker(this); } - @Override - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - try { - return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList()))); - } catch (Throwable t) { - throw newInternalError(t); - } + private boolean tooComplex() { + return (fieldCount() > FIELD_COUNT_THRESHOLD || + form.expressionCount() > FORM_EXPRESSION_THRESHOLD); } + private static final int FIELD_COUNT_THRESHOLD = 12; // largest convenient BMH field count + private static final int FORM_EXPRESSION_THRESHOLD = 24; // largest convenient BMH expression count - static final String EXTENSION_TYPES = "LIJFD"; - static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4; - static byte extensionIndex(char type) { - int i = EXTENSION_TYPES.indexOf(type); - if (i < 0) throw new InternalError(); - return (byte) i; + /** + * A reinvoker MH has this form: + * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }} + */ + static BoundMethodHandle makeReinvoker(MethodHandle target) { + LambdaForm form = DelegatingMethodHandle.makeReinvokerForm( + target, MethodTypeForm.LF_REBIND, + Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0)); + return Species_L.make(target.type(), form, target); } /** @@ -142,9 +145,22 @@ import jdk.internal.org.objectweb.asm.Type; */ /*non-public*/ abstract SpeciesData speciesData(); + /*non-public*/ static SpeciesData speciesData(LambdaForm form) { + Object c = form.names[0].constraint; + if (c instanceof SpeciesData) + return (SpeciesData) c; + // if there is no BMH constraint, then use the null constraint + return SpeciesData.EMPTY; + } + + /** + * Return the number of fields in this BMH. Equivalent to speciesData().fieldCount(). + */ + /*non-public*/ abstract int fieldCount(); + @Override - final Object internalProperties() { - return "/BMH="+internalValues(); + Object internalProperties() { + return "\n& BMH="+internalValues(); } @Override @@ -159,42 +175,28 @@ import jdk.internal.org.objectweb.asm.Type; /*non-public*/ final Object arg(int i) { try { switch (speciesData().fieldType(i)) { - case 'L': return argL(i); - case 'I': return argI(i); - case 'F': return argF(i); - case 'D': return argD(i); - case 'J': return argJ(i); + case L_TYPE: return speciesData().getters[i].invokeBasic(this); + case I_TYPE: return (int) speciesData().getters[i].invokeBasic(this); + case J_TYPE: return (long) speciesData().getters[i].invokeBasic(this); + case F_TYPE: return (float) speciesData().getters[i].invokeBasic(this); + case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this); } } catch (Throwable ex) { throw newInternalError(ex); } - throw new InternalError("unexpected type: " + speciesData().types+"."+i); + throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i); } - /*non-public*/ final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); } // // cloning API // - /*non-public*/ abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable; - - // The following is a grossly irregular hack: - @Override MethodHandle reinvokerTarget() { - try { - return (MethodHandle) argL(0); - } catch (Throwable ex) { - throw newInternalError(ex); - } - } + /*non-public*/ abstract BoundMethodHandle copyWith(MethodType mt, LambdaForm lf); + /*non-public*/ abstract BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg); // // concrete BMH classes required to close bootstrap loops @@ -203,150 +205,110 @@ import jdk.internal.org.objectweb.asm.Type; private // make it private to force users to access the enclosing class first static final class Species_L extends BoundMethodHandle { final Object argL0; - /*non-public*/ Species_L(MethodType mt, LambdaForm lf, Object argL0) { + private Species_L(MethodType mt, LambdaForm lf, Object argL0) { super(mt, lf); this.argL0 = argL0; } - // The following is a grossly irregular hack: - @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; } @Override /*non-public*/ SpeciesData speciesData() { return SPECIES_DATA; } - /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class); - @Override - /*non-public*/ final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable { - return new Species_L(mt, lf, argL0); - } - @Override - /*non-public*/ final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg); - } @Override - /*non-public*/ final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg); - } - @Override - /*non-public*/ final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg); - } - @Override - /*non-public*/ final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg); - } - @Override - /*non-public*/ final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg); - } - } - -/* - static final class Species_LL extends BoundMethodHandle { - final Object argL0; - final Object argL1; - public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) { - super(mt, lf); - this.argL0 = argL0; - this.argL1 = argL1; - } - @Override - public SpeciesData speciesData() { - return SPECIES_DATA; - } - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class); - @Override - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable { - return new Species_LL(mt, lf, argL0, argL1); - } - @Override - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - } - - static final class Species_JL extends BoundMethodHandle { - final long argJ0; - final Object argL1; - public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) { - super(mt, lf); - this.argJ0 = argJ0; - this.argL1 = argL1; + /*non-public*/ int fieldCount() { + return 1; } - @Override - public SpeciesData speciesData() { - return SPECIES_DATA; + /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class); + /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) { + return new Species_L(mt, lf, argL0); } - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class); - @Override public final long argJ0() { return argJ0; } - @Override public final Object argL1() { return argL1; } @Override - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable { - return new Species_JL(mt, lf, argJ0, argL1); + /*non-public*/ final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Species_L(mt, lf, argL0); } @Override - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } } -*/ // // BMH species meta-data // /** - * Meta-data wrapper for concrete BMH classes. + * Meta-data wrapper for concrete BMH types. + * Each BMH type corresponds to a given sequence of basic field types (LIJFD). + * The fields are immutable; their values are fully specified at object construction. + * Each BMH type supplies an array of getter functions which may be used in lambda forms. + * A BMH is constructed by cloning a shorter BMH and adding one or more new field values. + * The shortest possible BMH has zero fields; its class is SimpleMethodHandle. + * BMH species are not interrelated by subtyping, even though it would appear that + * a shorter BMH could serve as a supertype of a longer one which extends it. */ static class SpeciesData { - final String types; - final Class clazz; + private final String typeChars; + private final BasicType[] typeCodes; + private final Class clazz; // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH // Therefore, we need a non-final link in the chain. Use array elements. - final MethodHandle[] constructor; - final MethodHandle[] getters; - final SpeciesData[] extensions; + @Stable private final MethodHandle[] constructor; + @Stable private final MethodHandle[] getters; + @Stable private final NamedFunction[] nominalGetters; + @Stable private final SpeciesData[] extensions; /*non-public*/ int fieldCount() { - return types.length(); + return typeCodes.length; } - /*non-public*/ char fieldType(int i) { - return types.charAt(i); + /*non-public*/ BasicType fieldType(int i) { + return typeCodes[i]; + } + /*non-public*/ char fieldTypeChar(int i) { + return typeChars.charAt(i); + } + Object fieldSignature() { + return typeChars; + } + public Class fieldHolder() { + return clazz; } - public String toString() { - return "SpeciesData["+(isPlaceholder() ? "" : clazz.getSimpleName())+":"+types+"]"; + return "SpeciesData<"+fieldSignature()+">"; } /** @@ -354,45 +316,59 @@ import jdk.internal.org.objectweb.asm.Type; * represents a MH bound to a generic invoker, which in turn forwards to the corresponding * getter. */ - Name getterName(Name mhName, int i) { - MethodHandle mh = getters[i]; - assert(mh != null) : this+"."+i; - return new Name(mh, mhName); + NamedFunction getterFunction(int i) { + NamedFunction nf = nominalGetters[i]; + assert(nf.memberDeclaringClassOrNull() == fieldHolder()); + assert(nf.returnType() == fieldType(i)); + return nf; } - NamedFunction getterFunction(int i) { - return new NamedFunction(getters[i]); + NamedFunction[] getterFunctions() { + return nominalGetters; + } + + MethodHandle[] getterHandles() { return getters; } + + MethodHandle constructor() { + return constructor[0]; } static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class); private SpeciesData(String types, Class clazz) { - this.types = types; + this.typeChars = types; + this.typeCodes = basicTypes(types); this.clazz = clazz; if (!INIT_DONE) { - this.constructor = new MethodHandle[1]; + this.constructor = new MethodHandle[1]; // only one ctor this.getters = new MethodHandle[types.length()]; + this.nominalGetters = new NamedFunction[types.length()]; } else { this.constructor = Factory.makeCtors(clazz, types, null); this.getters = Factory.makeGetters(clazz, types, null); + this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters); } - this.extensions = new SpeciesData[EXTENSION_TYPES.length()]; + this.extensions = new SpeciesData[ARG_TYPE_LIMIT]; } private void initForBootstrap() { assert(!INIT_DONE); - if (constructor[0] == null) { + if (constructor() == null) { + String types = typeChars; Factory.makeCtors(clazz, types, this.constructor); Factory.makeGetters(clazz, types, this.getters); + Factory.makeNominalGetters(types, this.nominalGetters, this.getters); } } - private SpeciesData(String types) { + private SpeciesData(String typeChars) { // Placeholder only. - this.types = types; + this.typeChars = typeChars; + this.typeCodes = basicTypes(typeChars); this.clazz = null; this.constructor = null; this.getters = null; + this.nominalGetters = null; this.extensions = null; } private boolean isPlaceholder() { return clazz == null; } @@ -401,18 +377,15 @@ import jdk.internal.org.objectweb.asm.Type; static { CACHE.put("", EMPTY); } // make bootstrap predictable private static final boolean INIT_DONE; // set after finishes... - SpeciesData extendWithType(char type) { - int i = extensionIndex(type); - SpeciesData d = extensions[i]; - if (d != null) return d; - extensions[i] = d = get(types+type); - return d; + SpeciesData extendWith(byte type) { + return extendWith(BasicType.basicType(type)); } - SpeciesData extendWithIndex(byte index) { - SpeciesData d = extensions[index]; + SpeciesData extendWith(BasicType type) { + int ord = type.ordinal(); + SpeciesData d = extensions[ord]; if (d != null) return d; - extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index)); + extensions[ord] = d = get(typeChars+type.basicTypeChar()); return d; } @@ -456,8 +429,6 @@ import jdk.internal.org.objectweb.asm.Type; static { // pre-fill the BMH speciesdata cache with BMH's inner classes final Class rootCls = BoundMethodHandle.class; - SpeciesData d0 = BoundMethodHandle.SPECIES_DATA; // trigger class init - assert(d0 == null || d0 == lookupCache("")) : d0; try { for (Class c : rootCls.getDeclaredClasses()) { if (rootCls.isAssignableFrom(c)) { @@ -465,7 +436,7 @@ import jdk.internal.org.objectweb.asm.Type; SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh); assert(d != null) : cbmh.getName(); assert(d.clazz == cbmh); - assert(d == lookupCache(d.types)); + assert(d == lookupCache(d.typeChars)); } } } catch (Throwable e) { @@ -516,11 +487,10 @@ import jdk.internal.org.objectweb.asm.Type; static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG; static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG; static final String VOID_SIG = "()V"; + static final String INT_SIG = "()I"; static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;"; - static final Class[] TYPES = new Class[] { Object.class, int.class, long.class, float.class, double.class }; - static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" }; /** @@ -551,31 +521,35 @@ import jdk.internal.org.objectweb.asm.Type; * final Object argL0; * final Object argL1; * final int argI2; - * Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { + * private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { * super(mt, lf); * this.argL0 = argL0; * this.argL1 = argL1; * this.argI2 = argI2; * } * final SpeciesData speciesData() { return SPECIES_DATA; } + * final int fieldCount() { return 3; } * static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class); - * final BoundMethodHandle clone(MethodType mt, LambdaForm lf) { - * return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2); + * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { + * return new Species_LLI(mt, lf, argL0, argL1, argI2); * } - * final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) { + * return new Species_LLI(mt, lf, argL0, argL1, argI2); * } - * final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { + * return SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } - * final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { + * return SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } - * final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { + * return SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } - * final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { + * return SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * } + * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { + * return SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * } *

@@ -586,8 +560,9 @@ import jdk.internal.org.objectweb.asm.Type; static Class generateConcreteBMHClass(String types) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - final String className = SPECIES_PREFIX_PATH + types; - final String sourceFile = SPECIES_PREFIX_NAME + types; + String shortTypes = LambdaForm.shortenSignature(types); + final String className = SPECIES_PREFIX_PATH + shortTypes; + final String sourceFile = SPECIES_PREFIX_NAME + shortTypes; final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null); cw.visitSource(sourceFile, null); @@ -606,13 +581,13 @@ import jdk.internal.org.objectweb.asm.Type; MethodVisitor mv; // emit constructor - mv = cw.visitMethod(NOT_ACC_PUBLIC, "", makeSignature(types, true), null, null); + mv = cw.visitMethod(ACC_PRIVATE, "", makeSignature(types, true), null, null); mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 0); // this + mv.visitVarInsn(ALOAD, 1); // type + mv.visitVarInsn(ALOAD, 2); // form - mv.visitMethodInsn(INVOKESPECIAL, BMH, "", makeSignature("", true)); + mv.visitMethodInsn(INVOKESPECIAL, BMH, "", makeSignature("", true), false); for (int i = 0, j = 0; i < types.length(); ++i, ++j) { // i counts the arguments, j counts corresponding argument slots @@ -629,69 +604,91 @@ import jdk.internal.org.objectweb.asm.Type; mv.visitMaxs(0, 0); mv.visitEnd(); - // emit implementation of reinvokerTarget() - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null); + // emit implementation of speciesData() + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null); mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG); - mv.visitTypeInsn(CHECKCAST, MH); + mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // emit implementation of speciesData() - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null); + // emit implementation of fieldCount() + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null); mv.visitCode(); - mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); + int fc = types.length(); + if (fc <= (ICONST_5 - ICONST_0)) { + mv.visitInsn(ICONST_0 + fc); + } else { + mv.visitIntInsn(SIPUSH, fc); + } + mv.visitInsn(IRETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + // emit make() ...factory method wrapping constructor + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null); + mv.visitCode(); + // make instance + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); + // load mt, lf + mv.visitVarInsn(ALOAD, 0); // type + mv.visitVarInsn(ALOAD, 1); // form + // load factory method arguments + for (int i = 0, j = 0; i < types.length(); ++i, ++j) { + // i counts the arguments, j counts corresponding argument slots + char t = types.charAt(i); + mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3 + if (t == 'J' || t == 'D') { + ++j; // adjust argument register access + } + } + + // finally, invoke the constructor and return + mv.visitMethodInsn(INVOKESPECIAL, className, "", makeSignature(types, true), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // emit clone() - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE); + // emit copyWith() + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null); mv.visitCode(); - // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...) - // obtain constructor - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); - mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG); - mv.visitInsn(ICONST_0); - mv.visitInsn(AALOAD); + // make instance + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); // load mt, lf mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); // put fields on the stack emitPushFields(types, className, mv); // finally, invoke the constructor and return - mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types, false)); + mv.visitMethodInsn(INVOKESPECIAL, className, "", makeSignature(types, true), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // for each type, emit cloneExtendT() - for (Class c : TYPES) { - char t = Wrapper.basicTypeChar(c); - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE); + // for each type, emit copyWithExtendT() + for (BasicType type : BasicType.ARG_TYPES) { + int ord = type.ordinal(); + char btChar = type.basicTypeChar(); + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE); mv.visitCode(); - // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg) + // return SPECIES_DATA.extendWith(t).constructor().invokeBasic(mt, lf, argL0, ..., narg) // obtain constructor mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); - int iconstInsn = ICONST_0 + extensionIndex(t); + int iconstInsn = ICONST_0 + ord; assert(iconstInsn <= ICONST_5); mv.visitInsn(iconstInsn); - mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWithIndex", BMHSPECIES_DATA_EWI_SIG); - mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG); - mv.visitInsn(ICONST_0); - mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false); + mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "constructor", "()" + MH_SIG, false); // load mt, lf mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); // put fields on the stack emitPushFields(types, className, mv); // put narg on stack - mv.visitVarInsn(typeLoadOp(t), 3); + mv.visitVarInsn(typeLoadOp(btChar), 3); // finally, invoke the constructor and return - mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + t, false)); + mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -702,7 +699,7 @@ import jdk.internal.org.objectweb.asm.Type; mv.visitCode(); mv.visitLdcInsn(types); mv.visitLdcInsn(Type.getObjectType(className)); - mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG); + mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false); mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); @@ -730,7 +727,7 @@ import jdk.internal.org.objectweb.asm.Type; case 'J': return LLOAD; case 'F': return FLOAD; case 'D': return DLOAD; - default : throw new InternalError("unrecognized type " + t); + default : throw newInternalError("unrecognized type " + t); } } @@ -771,10 +768,19 @@ import jdk.internal.org.objectweb.asm.Type; static MethodHandle[] makeCtors(Class cbmh, String types, MethodHandle mhs[]) { if (mhs == null) mhs = new MethodHandle[1]; + if (types.equals("")) return mhs; // hack for empty BMH species mhs[0] = makeCbmhCtor(cbmh, types); return mhs; } + static NamedFunction[] makeNominalGetters(String types, NamedFunction[] nfs, MethodHandle[] getters) { + if (nfs == null) nfs = new NamedFunction[types.length()]; + for (int i = 0; i < nfs.length; ++i) { + nfs[i] = new NamedFunction(getters[i]); + } + return nfs; + } + // // Auxiliary methods. // @@ -808,52 +814,11 @@ import jdk.internal.org.objectweb.asm.Type; static MethodHandle makeCbmhCtor(Class cbmh, String types) { try { - return linkConstructor(LOOKUP.findConstructor(cbmh, MethodType.fromMethodDescriptorString(makeSignature(types, true), null))); + return LOOKUP.findStatic(cbmh, "make", MethodType.fromMethodDescriptorString(makeSignature(types, false), null)); } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) { throw newInternalError(e); } } - - /** - * Wrap a constructor call in a {@link LambdaForm}. - * - * If constructors ({@code } methods) are called in LFs, problems might arise if the LFs - * are turned into bytecode, because the call to the allocator is routed through an MH, and the - * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to - * {@code }. To avoid this, we add an indirection by invoking {@code } through - * {@link MethodHandle#linkToSpecial}. - * - * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void} - * result of the {@code } invocation. This entry is replaced. - */ - private static MethodHandle linkConstructor(MethodHandle cmh) { - final LambdaForm lf = cmh.form; - final int initNameIndex = lf.names.length - 1; - final Name initName = lf.names[initNameIndex]; - final MemberName ctorMN = initName.function.member; - final MethodType ctorMT = ctorMN.getInvocationType(); - - // obtain function member (call target) - // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!) - final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class); - MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic); - try { - linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class); - assert(linkerMN.isStatic()); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - // extend arguments array - Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1); - newArgs[newArgs.length - 1] = ctorMN; - // replace function - final NamedFunction nf = new NamedFunction(linkerMN); - final Name linkedCtor = new Name(nf, newArgs); - linkedCtor.initIndex(initNameIndex); - lf.names[initNameIndex] = linkedCtor; - return cmh; - } - } private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP; diff --git a/src/share/classes/java/lang/invoke/CallSite.java b/src/share/classes/java/lang/invoke/CallSite.java index 949364bcec4a17784486ad7cfa166dfab500e79b..10ac1c0716eba62fda2da11e3e5b5f55758ea505 100644 --- a/src/share/classes/java/lang/invoke/CallSite.java +++ b/src/share/classes/java/lang/invoke/CallSite.java @@ -102,7 +102,7 @@ public class CallSite { */ /*package-private*/ CallSite(MethodType type) { - target = type.invokers().uninitializedCallSite(); + target = makeUninitializedCallSite(type); } /** @@ -211,27 +211,40 @@ public class CallSite { public abstract MethodHandle dynamicInvoker(); /*non-public*/ MethodHandle makeDynamicInvoker() { - MethodHandle getTarget = GET_TARGET.bindReceiver(this); + MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this); MethodHandle invoker = MethodHandles.exactInvoker(this.type()); return MethodHandles.foldArguments(invoker, getTarget); } private static final MethodHandle GET_TARGET; + private static final MethodHandle THROW_UCS; static { try { GET_TARGET = IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + THROW_UCS = IMPL_LOOKUP. + findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class)); } catch (ReflectiveOperationException e) { throw newInternalError(e); } } /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */ - /*package-private*/ - static Empty uninitializedCallSite() { + private static Object uninitializedCallSite(Object... ignore) { throw new IllegalStateException("uninitialized call site"); } + private MethodHandle makeUninitializedCallSite(MethodType targetType) { + MethodType basicType = targetType.basicType(); + MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS); + if (invoker == null) { + invoker = THROW_UCS.asType(basicType); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker); + } + // unchecked view is OK since no values will be received or returned + return invoker.viewAsType(targetType, false); + } + // unsafe stuff: private static final long TARGET_OFFSET; static { @@ -319,7 +332,7 @@ public class CallSite { throw new ClassCastException("bootstrap method failed to produce a CallSite"); } if (!site.getTarget().type().equals(type)) - throw new WrongMethodTypeException("wrong type: "+site.getTarget()); + throw wrongTargetType(site.getTarget(), type); } catch (Throwable ex) { BootstrapMethodError bex; if (ex instanceof BootstrapMethodError) diff --git a/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java b/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java new file mode 100644 index 0000000000000000000000000000000000000000..63ba8fea5b2a3e7f3cc0dccdf6159c86df687bcd --- /dev/null +++ b/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.MethodHandleStatics.*; + +/** + * A method handle whose invocation behavior is determined by a target. + * The delegating MH itself can hold extra "intentions" beyond the simple behavior. + * @author jrose + */ +/*non-public*/ +abstract class DelegatingMethodHandle extends MethodHandle { + protected DelegatingMethodHandle(MethodHandle target) { + this(target.type(), target); + } + + protected DelegatingMethodHandle(MethodType type, MethodHandle target) { + super(type, chooseDelegatingForm(target)); + } + + /** Define this to extract the delegated target which supplies the invocation behavior. */ + abstract protected MethodHandle getTarget(); + + @Override + abstract MethodHandle asTypeUncached(MethodType newType); + + @Override + MemberName internalMemberName() { + return getTarget().internalMemberName(); + } + + @Override + boolean isInvokeSpecial() { + return getTarget().isInvokeSpecial(); + } + + @Override + Class internalCallerClass() { + return getTarget().internalCallerClass(); + } + + @Override + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + // FIXME: rethink 'copyWith' protocol; it is too low-level for use on all MHs + throw newIllegalArgumentException("do not use this"); + } + + @Override + String internalProperties() { + return "\n& Class="+getClass().getSimpleName()+ + "\n& Target="+getTarget().debugString(); + } + + @Override + BoundMethodHandle rebind() { + return getTarget().rebind(); + } + + private static LambdaForm chooseDelegatingForm(MethodHandle target) { + if (target instanceof SimpleMethodHandle) + return target.internalForm(); // no need for an indirection + return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget); + } + + /** Create a LF which simply reinvokes a target of the given basic type. */ + static LambdaForm makeReinvokerForm(MethodHandle target, + int whichCache, + Object constraint, + NamedFunction getTargetFn) { + MethodType mtype = target.type().basicType(); + boolean customized = (whichCache < 0 || + mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY); + LambdaForm form; + if (!customized) { + form = mtype.form().cachedLambdaForm(whichCache); + if (form != null) return form; + } + final int THIS_DMH = 0; + final int ARG_BASE = 1; + final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); + int nameCursor = ARG_LIMIT; + final int NEXT_MH = customized ? -1 : nameCursor++; + final int REINVOKE = nameCursor++; + LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); + assert(names.length == nameCursor); + names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint); + Object[] targetArgs; + if (customized) { + targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class); + names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself + } else { + names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]); + targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class); + targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH + names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs); + } + String debugString; + switch(whichCache) { + case MethodTypeForm.LF_REBIND: debugString = "BMH.reinvoke"; break; + case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate"; break; + default: debugString = "MH.reinvoke"; break; + } + form = new LambdaForm(debugString, ARG_LIMIT, names); + if (!customized) { + form = mtype.form().setCachedLambdaForm(whichCache, form); + } + return form; + } + + private static final NamedFunction NF_getTarget; + static { + try { + NF_getTarget = new NamedFunction(DelegatingMethodHandle.class + .getDeclaredMethod("getTarget")); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } +} diff --git a/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/share/classes/java/lang/invoke/DirectMethodHandle.java index 9c054519b4322d2f2ad25a003c1f4832858e3d1f..e9d2526cd8d336b9f082065973f4345ff7d57278 100644 --- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -31,6 +31,7 @@ import java.util.Arrays; import sun.invoke.util.VerifyAccess; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodTypeForm.*; import static java.lang.invoke.MethodHandleStatics.*; import java.lang.ref.WeakReference; @@ -58,6 +59,7 @@ class DirectMethodHandle extends MethodHandle { MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); if (m != null && m.isPublic()) { + assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong member = m; } } @@ -124,66 +126,31 @@ class DirectMethodHandle extends MethodHandle { return new Constructor(mtype, lform, ctor, init, instanceClass); } + @Override + BoundMethodHandle rebind() { + return BoundMethodHandle.makeReinvoker(this); + } + @Override MethodHandle copyWith(MethodType mt, LambdaForm lf) { + assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses return new DirectMethodHandle(mt, lf, member); } @Override String internalProperties() { - return "/DMH="+member.toString(); + return "\n& DMH.MN="+internalMemberName(); } //// Implementation methods. @Override - MethodHandle viewAsType(MethodType newType) { - return new DirectMethodHandle(newType, form, member); - } - @Override @ForceInline MemberName internalMemberName() { return member; } - @Override - MethodHandle bindArgument(int pos, char basicType, Object value) { - // If the member needs dispatching, do so. - if (pos == 0 && basicType == 'L') { - DirectMethodHandle concrete = maybeRebind(value); - if (concrete != null) - return concrete.bindReceiver(value); - } - return super.bindArgument(pos, basicType, value); - } - - @Override - MethodHandle bindReceiver(Object receiver) { - // If the member needs dispatching, do so. - DirectMethodHandle concrete = maybeRebind(receiver); - if (concrete != null) - return concrete.bindReceiver(receiver); - return super.bindReceiver(receiver); - } - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); - private DirectMethodHandle maybeRebind(Object receiver) { - if (receiver != null) { - switch (member.getReferenceKind()) { - case REF_invokeInterface: - case REF_invokeVirtual: - // Pre-dispatch the member. - Class concreteClass = receiver.getClass(); - MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial); - concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass); - if (concrete != null) - return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete); - break; - } - } - return null; - } - /** * Create a LF which can invoke the given method. * Cache and share this structure among all methods with @@ -264,9 +231,10 @@ class DirectMethodHandle extends MethodHandle { } else { names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]); } + assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]); Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class); assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args! - int result = LambdaForm.LAST_RESULT; + int result = LAST_RESULT; if (doesAlloc) { assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2); @@ -274,13 +242,23 @@ class DirectMethodHandle extends MethodHandle { result = NEW_OBJ; } names[LINKER_CALL] = new Name(linker, outArgs); - lambdaName += "_" + LambdaForm.basicTypeSignature(mtype); + lambdaName += "_" + shortenSignature(basicTypeSignature(mtype)); LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result); // This is a tricky bit of code. Don't send it through the LF interpreter. lform.compileToBytecode(); return lform; } + static Object findDirectMethodHandle(Name name) { + if (name.function == Lazy.NF_internalMemberName || + name.function == Lazy.NF_internalMemberNameEnsureInit || + name.function == Lazy.NF_constructorMethod) { + assert(name.arguments.length == 1); + return name.arguments[0]; + } + return null; + } + private static void maybeCompile(LambdaForm lform, MemberName m) { if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class)) // Help along bootstrapping... @@ -393,8 +371,8 @@ class DirectMethodHandle extends MethodHandle { return true; } @Override - MethodHandle viewAsType(MethodType newType) { - return new Special(newType, form, member); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Special(mt, lf, member); } } @@ -411,8 +389,8 @@ class DirectMethodHandle extends MethodHandle { assert(initMethod.isResolved()); } @Override - MethodHandle viewAsType(MethodType newType) { - return new Constructor(newType, form, member, initMethod, instanceClass); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Constructor(mt, lf, member, initMethod, instanceClass); } } @@ -441,8 +419,8 @@ class DirectMethodHandle extends MethodHandle { return fieldType.cast(obj); } @Override - MethodHandle viewAsType(MethodType newType) { - return new Accessor(newType, form, member, fieldOffset); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Accessor(mt, lf, member, fieldOffset); } } @@ -484,8 +462,8 @@ class DirectMethodHandle extends MethodHandle { return fieldType.cast(obj); } @Override - MethodHandle viewAsType(MethodType newType) { - return new StaticAccessor(newType, form, member, staticBase, staticOffset); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new StaticAccessor(mt, lf, member, staticBase, staticOffset); } } diff --git a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 2fc8618cbc5ca2181c47a737de2aaf3263161661..752c0976d9e417b13622c016e5476382915f5829 100644 --- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -193,10 +193,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; CallSite buildCallSite() throws LambdaConversionException { final Class innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0) { - final Constructor[] ctrs = AccessController.doPrivileged( - new PrivilegedAction() { + final Constructor[] ctrs = AccessController.doPrivileged( + new PrivilegedAction[]>() { @Override - public Constructor[] run() { + public Constructor[] run() { Constructor[] ctrs = innerClass.getDeclaredConstructors(); if (ctrs.length == 1) { // The lambda implementing inner class constructor is private, set @@ -338,7 +338,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; m.visitVarInsn(getLoadOpcode(argType), varIndex); varIndex += getParameterSize(argType); } - m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString()); + m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); m.visitInsn(ARETURN); m.visitMaxs(-1, -1); m.visitEnd(); @@ -354,7 +354,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, - METHOD_DESCRIPTOR_VOID); + METHOD_DESCRIPTOR_VOID, false); int parameterCount = invokedType.parameterCount(); for (int i = 0, lvIndex = 0; i < parameterCount; i++) { ctor.visitVarInsn(ALOAD, 0); @@ -402,7 +402,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR, - DESCR_CTOR_SERIALIZED_LAMBDA); + DESCR_CTOR_SERIALIZED_LAMBDA, false); mv.visitInsn(ARETURN); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored mv.visitMaxs(-1, -1); @@ -421,7 +421,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; mv.visitInsn(DUP); mv.visitLdcInsn("Non-serializable lambda"); mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR, - DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION); + DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); mv.visitInsn(ATHROW); mv.visitMaxs(-1, -1); mv.visitEnd(); @@ -434,7 +434,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; mv.visitInsn(DUP); mv.visitLdcInsn("Non-serializable lambda"); mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR, - DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION); + DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); mv.visitInsn(ATHROW); mv.visitMaxs(-1, -1); mv.visitEnd(); diff --git a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 55260ee5ad5fa5584a855193cd733972e86b9530..da78e44ac3dcad2b2b184646d9e4bf847ffd8ce2 100644 --- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -25,20 +25,20 @@ package java.lang.invoke; -import sun.invoke.util.VerifyAccess; -import java.lang.invoke.LambdaForm.Name; - -import sun.invoke.util.Wrapper; - import java.io.*; import java.util.*; +import java.lang.reflect.Modifier; import jdk.internal.org.objectweb.asm.*; -import java.lang.reflect.*; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; + +import sun.invoke.util.VerifyAccess; import sun.invoke.util.VerifyType; +import sun.invoke.util.Wrapper; import sun.reflect.misc.ReflectUtil; /** @@ -73,7 +73,11 @@ class InvokerBytecodeGenerator { private final LambdaForm lambdaForm; private final String invokerName; private final MethodType invokerType; - private final int[] localsMap; + + /** Info about local variables in compiled lambda form */ + private final int[] localsMap; // index + private final BasicType[] localTypes; // basic type + private final Class[] localClasses; // type /** ASM bytecode generation. */ private ClassWriter cw; @@ -82,6 +86,7 @@ class InvokerBytecodeGenerator { private static final MemberName.Factory MEMBERNAME_FACTORY = MemberName.getFactory(); private static final Class HOST_CLASS = LambdaForm.class; + /** Main constructor; other constructors delegate to this one. */ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, String className, String invokerName, MethodType invokerType) { if (invokerName.contains(".")) { @@ -97,18 +102,26 @@ class InvokerBytecodeGenerator { this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; - this.localsMap = new int[localsMapSize]; + this.localsMap = new int[localsMapSize+1]; + // last entry of localsMap is count of allocated local slots + this.localTypes = new BasicType[localsMapSize+1]; + this.localClasses = new Class[localsMapSize+1]; } + /** For generating LambdaForm interpreter entry points. */ private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) { this(null, invokerType.parameterCount(), className, invokerName, invokerType); // Create an array to map name indexes to locals indexes. + localTypes[localTypes.length - 1] = V_TYPE; for (int i = 0; i < localsMap.length; i++) { localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i); + if (i < invokerType.parameterCount()) + localTypes[i] = basicType(invokerType.parameterType(i)); } } + /** For generating customized code for a single LambdaForm. */ private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) { this(form, form.names.length, className, form.debugName, invokerType); @@ -116,7 +129,11 @@ class InvokerBytecodeGenerator { Name[] names = form.names; for (int i = 0, index = 0; i < localsMap.length; i++) { localsMap[i] = index; - index += Wrapper.forBasicType(names[i].type).stackSlots(); + if (i < names.length) { + BasicType type = names[i].type(); + index += type.basicTypeSlots(); + localTypes[i] = type; + } } } @@ -147,7 +164,6 @@ class InvokerBytecodeGenerator { static void maybeDump(final String className, final byte[] classFile) { if (DUMP_CLASS_FILES) { - System.out.println("dump: " + className); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { @@ -155,6 +171,7 @@ class InvokerBytecodeGenerator { String dumpName = className; //dumpName = dumpName.replace('/', '-'); File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class"); + System.out.println("dump: " + dumpFile); dumpFile.getParentFile().mkdirs(); FileOutputStream file = new FileOutputStream(dumpFile); file.write(classFile); @@ -203,7 +220,7 @@ class InvokerBytecodeGenerator { String constantPlaceholder(Object arg) { String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++; - if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + arg.toString() + ">>"; // debugging aid + if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + debugString(arg) + ">>"; // debugging aid if (cpPatches.containsKey(cpPlaceholder)) { throw new InternalError("observed CP placeholder twice: " + cpPlaceholder); } @@ -224,6 +241,17 @@ class InvokerBytecodeGenerator { return res; } + private static String debugString(Object arg) { + if (arg instanceof MethodHandle) { + MethodHandle mh = (MethodHandle) arg; + MemberName member = mh.internalMemberName(); + if (member != null) + return member.toString(); + return mh.debugString(); + } + return arg.toString(); + } + /** * Extract the number of constant pool entries from a given class file. * @@ -359,118 +387,212 @@ class InvokerBytecodeGenerator { /* * NOTE: These load/store methods use the localsMap to find the correct index! */ - private void emitLoadInsn(char type, int index) { - int opcode; + private void emitLoadInsn(BasicType type, int index) { + int opcode = loadInsnOpcode(type); + mv.visitVarInsn(opcode, localsMap[index]); + } + + private int loadInsnOpcode(BasicType type) throws InternalError { switch (type) { - case 'I': opcode = Opcodes.ILOAD; break; - case 'J': opcode = Opcodes.LLOAD; break; - case 'F': opcode = Opcodes.FLOAD; break; - case 'D': opcode = Opcodes.DLOAD; break; - case 'L': opcode = Opcodes.ALOAD; break; - default: - throw new InternalError("unknown type: " + type); + case I_TYPE: return Opcodes.ILOAD; + case J_TYPE: return Opcodes.LLOAD; + case F_TYPE: return Opcodes.FLOAD; + case D_TYPE: return Opcodes.DLOAD; + case L_TYPE: return Opcodes.ALOAD; + default: + throw new InternalError("unknown type: " + type); } - mv.visitVarInsn(opcode, localsMap[index]); } private void emitAloadInsn(int index) { - emitLoadInsn('L', index); + emitLoadInsn(L_TYPE, index); } - private void emitStoreInsn(char type, int index) { - int opcode; + private void emitStoreInsn(BasicType type, int index) { + int opcode = storeInsnOpcode(type); + mv.visitVarInsn(opcode, localsMap[index]); + } + + private int storeInsnOpcode(BasicType type) throws InternalError { switch (type) { - case 'I': opcode = Opcodes.ISTORE; break; - case 'J': opcode = Opcodes.LSTORE; break; - case 'F': opcode = Opcodes.FSTORE; break; - case 'D': opcode = Opcodes.DSTORE; break; - case 'L': opcode = Opcodes.ASTORE; break; - default: - throw new InternalError("unknown type: " + type); + case I_TYPE: return Opcodes.ISTORE; + case J_TYPE: return Opcodes.LSTORE; + case F_TYPE: return Opcodes.FSTORE; + case D_TYPE: return Opcodes.DSTORE; + case L_TYPE: return Opcodes.ASTORE; + default: + throw new InternalError("unknown type: " + type); } - mv.visitVarInsn(opcode, localsMap[index]); } private void emitAstoreInsn(int index) { - emitStoreInsn('L', index); + emitStoreInsn(L_TYPE, index); + } + + private byte arrayTypeCode(Wrapper elementType) { + switch (elementType) { + case BOOLEAN: return Opcodes.T_BOOLEAN; + case BYTE: return Opcodes.T_BYTE; + case CHAR: return Opcodes.T_CHAR; + case SHORT: return Opcodes.T_SHORT; + case INT: return Opcodes.T_INT; + case LONG: return Opcodes.T_LONG; + case FLOAT: return Opcodes.T_FLOAT; + case DOUBLE: return Opcodes.T_DOUBLE; + case OBJECT: return 0; // in place of Opcodes.T_OBJECT + default: throw new InternalError(); + } + } + + private int arrayInsnOpcode(byte tcode, int aaop) throws InternalError { + assert(aaop == Opcodes.AASTORE || aaop == Opcodes.AALOAD); + int xas; + switch (tcode) { + case Opcodes.T_BOOLEAN: xas = Opcodes.BASTORE; break; + case Opcodes.T_BYTE: xas = Opcodes.BASTORE; break; + case Opcodes.T_CHAR: xas = Opcodes.CASTORE; break; + case Opcodes.T_SHORT: xas = Opcodes.SASTORE; break; + case Opcodes.T_INT: xas = Opcodes.IASTORE; break; + case Opcodes.T_LONG: xas = Opcodes.LASTORE; break; + case Opcodes.T_FLOAT: xas = Opcodes.FASTORE; break; + case Opcodes.T_DOUBLE: xas = Opcodes.DASTORE; break; + case 0: xas = Opcodes.AASTORE; break; + default: throw new InternalError(); + } + return xas - Opcodes.AASTORE + aaop; + } + + + private void freeFrameLocal(int oldFrameLocal) { + int i = indexForFrameLocal(oldFrameLocal); + if (i < 0) return; + BasicType type = localTypes[i]; + int newFrameLocal = makeLocalTemp(type); + mv.visitVarInsn(loadInsnOpcode(type), oldFrameLocal); + mv.visitVarInsn(storeInsnOpcode(type), newFrameLocal); + assert(localsMap[i] == oldFrameLocal); + localsMap[i] = newFrameLocal; + assert(indexForFrameLocal(oldFrameLocal) < 0); + } + private int indexForFrameLocal(int frameLocal) { + for (int i = 0; i < localsMap.length; i++) { + if (localsMap[i] == frameLocal && localTypes[i] != V_TYPE) + return i; + } + return -1; + } + private int makeLocalTemp(BasicType type) { + int frameLocal = localsMap[localsMap.length - 1]; + localsMap[localsMap.length - 1] = frameLocal + type.basicTypeSlots(); + return frameLocal; } /** * Emit a boxing call. * - * @param type primitive type class to box. + * @param wrapper primitive type class to box. */ - private void emitBoxing(Class type) { - Wrapper wrapper = Wrapper.forPrimitiveType(type); + private void emitBoxing(Wrapper wrapper) { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = "valueOf"; String desc = "(" + wrapper.basicTypeChar() + ")L" + owner + ";"; - mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); } /** * Emit an unboxing call (plus preceding checkcast). * - * @param type wrapper type class to unbox. + * @param wrapper wrapper type class to unbox. */ - private void emitUnboxing(Class type) { - Wrapper wrapper = Wrapper.forWrapperType(type); + private void emitUnboxing(Wrapper wrapper) { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = wrapper.primitiveSimpleName() + "Value"; String desc = "()" + wrapper.basicTypeChar(); - mv.visitTypeInsn(Opcodes.CHECKCAST, owner); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc); + emitReferenceCast(wrapper.wrapperType(), null); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false); } /** - * Emit an implicit conversion. + * Emit an implicit conversion for an argument which must be of the given pclass. + * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface. * * @param ptype type of value present on stack * @param pclass type of value required on stack + * @param arg compile-time representation of value on stack (Node, constant) or null if none */ - private void emitImplicitConversion(char ptype, Class pclass) { + private void emitImplicitConversion(BasicType ptype, Class pclass, Object arg) { + assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller + if (pclass == ptype.basicTypeClass() && ptype != L_TYPE) + return; // nothing to do switch (ptype) { - case 'L': - if (VerifyType.isNullConversion(Object.class, pclass)) + case L_TYPE: + if (VerifyType.isNullConversion(Object.class, pclass, false)) { + if (PROFILE_LEVEL > 0) + emitReferenceCast(Object.class, arg); + return; + } + emitReferenceCast(pclass, arg); return; - if (isStaticallyNameable(pclass)) { - mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass)); - } else { - mv.visitLdcInsn(constantPlaceholder(pclass)); - mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); - mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG); - if (pclass.isArray()) - mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); + case I_TYPE: + if (!VerifyType.isNullConversion(int.class, pclass, false)) + emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); + return; + } + throw newInternalError("bad implicit conversion: tc="+ptype+": "+pclass); + } + + /** Update localClasses type map. Return true if the information is already present. */ + private boolean assertStaticType(Class cls, Name n) { + int local = n.index(); + Class aclass = localClasses[local]; + if (aclass != null && (aclass == cls || cls.isAssignableFrom(aclass))) { + return true; // type info is already present + } else if (aclass == null || aclass.isAssignableFrom(cls)) { + localClasses[local] = cls; // type info can be improved + } + return false; + } + + private void emitReferenceCast(Class cls, Object arg) { + Name writeBack = null; // local to write back result + if (arg instanceof Name) { + Name n = (Name) arg; + if (assertStaticType(cls, n)) + return; // this cast was already performed + if (lambdaForm.useCount(n) > 1) { + // This guy gets used more than once. + writeBack = n; } - return; - case 'I': - if (!VerifyType.isNullConversion(int.class, pclass)) - emitPrimCast(ptype, Wrapper.basicTypeChar(pclass)); - return; - case 'J': - assert(pclass == long.class); - return; - case 'F': - assert(pclass == float.class); - return; - case 'D': - assert(pclass == double.class); - return; } - throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass); + if (isStaticallyNameable(cls)) { + String sig = getInternalName(cls); + mv.visitTypeInsn(Opcodes.CHECKCAST, sig); + } else { + mv.visitLdcInsn(constantPlaceholder(cls)); + mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); + mv.visitInsn(Opcodes.SWAP); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); + if (Object[].class.isAssignableFrom(cls)) + mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); + else if (PROFILE_LEVEL > 0) + mv.visitTypeInsn(Opcodes.CHECKCAST, OBJ); + } + if (writeBack != null) { + mv.visitInsn(Opcodes.DUP); + emitAstoreInsn(writeBack.index()); + } } /** * Emits an actual return instruction conforming to the given return type. */ - private void emitReturnInsn(Class type) { + private void emitReturnInsn(BasicType type) { int opcode; - switch (Wrapper.basicTypeChar(type)) { - case 'I': opcode = Opcodes.IRETURN; break; - case 'J': opcode = Opcodes.LRETURN; break; - case 'F': opcode = Opcodes.FRETURN; break; - case 'D': opcode = Opcodes.DRETURN; break; - case 'L': opcode = Opcodes.ARETURN; break; - case 'V': opcode = Opcodes.RETURN; break; + switch (type) { + case I_TYPE: opcode = Opcodes.IRETURN; break; + case J_TYPE: opcode = Opcodes.LRETURN; break; + case F_TYPE: opcode = Opcodes.FRETURN; break; + case D_TYPE: opcode = Opcodes.DRETURN; break; + case L_TYPE: opcode = Opcodes.ARETURN; break; + case V_TYPE: opcode = Opcodes.RETURN; break; default: throw new InternalError("unknown return type: " + type); } @@ -478,7 +600,11 @@ class InvokerBytecodeGenerator { } private static String getInternalName(Class c) { - assert(VerifyAccess.isTypeVisible(c, Object.class)); + if (c == Object.class) return OBJ; + else if (c == Object[].class) return OBJARY; + else if (c == Class.class) return CLS; + else if (c == MethodHandle.class) return MH; + assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName(); return c.getName().replace('.', '/'); } @@ -507,39 +633,62 @@ class InvokerBytecodeGenerator { // iterate over the form's names, generating bytecode instructions for each // start iterating at the first name following the arguments + Name onStack = null; for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) { Name name = lambdaForm.names[i]; - MemberName member = name.function.member(); - if (isSelectAlternative(i)) { - emitSelectAlternative(name, lambdaForm.names[i + 1]); - i++; // skip MH.invokeBasic of the selectAlternative result - } else if (isGuardWithCatch(i)) { - emitGuardWithCatch(i); - i = i+2; // Jump to the end of GWC idiom - } else if (isStaticallyInvocable(member)) { + emitStoreResult(onStack); + onStack = name; // unless otherwise modified below + MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); + switch (intr) { + case SELECT_ALTERNATIVE: + assert isSelectAlternative(i); + onStack = emitSelectAlternative(name, lambdaForm.names[i+1]); + i++; // skip MH.invokeBasic of the selectAlternative result + continue; + case GUARD_WITH_CATCH: + assert isGuardWithCatch(i); + onStack = emitGuardWithCatch(i); + i = i+2; // Jump to the end of GWC idiom + continue; + case NEW_ARRAY: + Class rtype = name.function.methodType().returnType(); + if (isStaticallyNameable(rtype)) { + emitNewArray(name); + continue; + } + break; + case ARRAY_LOAD: + emitArrayLoad(name); + continue; + case ARRAY_STORE: + emitArrayStore(name); + continue; + case IDENTITY: + assert(name.arguments.length == 1); + emitPushArguments(name); + continue; + case ZERO: + assert(name.arguments.length == 0); + emitConst(name.type.basicTypeWrapper().zero()); + continue; + case NONE: + // no intrinsic associated + break; + default: + throw newInternalError("Unknown intrinsic: "+intr); + } + + MemberName member = name.function.member(); + if (isStaticallyInvocable(member)) { emitStaticInvoke(member, name); } else { emitInvoke(name); } - - // Update cached form name's info in case an intrinsic spanning multiple names was encountered. - name = lambdaForm.names[i]; - member = name.function.member(); - - // store the result from evaluating to the target name in a local if required - // (if this is the last value, i.e., the one that is going to be returned, - // avoid store/load/return and just return) - if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) { - // return value - do nothing - } else if (name.type != 'V') { - // non-void: actually assign - emitStoreInsn(name.type, name.index()); - } } // return statement - emitReturn(); + emitReturn(onStack); classFileEpilogue(); bogusMethod(lambdaForm); @@ -549,33 +698,47 @@ class InvokerBytecodeGenerator { return classFile; } + void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } + void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + + void emitArrayOp(Name name, int arrayOpcode) { + assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE; + Class elementType = name.function.methodType().parameterType(0).getComponentType(); + assert elementType != null; + emitPushArguments(name); + if (elementType.isPrimitive()) { + Wrapper w = Wrapper.forPrimitiveType(elementType); + arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode); + } + mv.visitInsn(arrayOpcode); + } + /** * Emit an invoke for the given name. */ void emitInvoke(Name name) { + assert(!isLinkerMethodInvoke(name)); // should use the static path for these if (true) { // push receiver MethodHandle target = name.function.resolvedHandle; assert(target != null) : name.exprString(); mv.visitLdcInsn(constantPlaceholder(target)); - mv.visitTypeInsn(Opcodes.CHECKCAST, MH); + emitReferenceCast(MethodHandle.class, target); } else { // load receiver emitAloadInsn(0); - mv.visitTypeInsn(Opcodes.CHECKCAST, MH); + emitReferenceCast(MethodHandle.class, null); mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG); mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG); // TODO more to come } // push arguments - for (int i = 0; i < name.arguments.length; i++) { - emitPushArgument(name, i); - } + emitPushArguments(name); // invocation MethodType type = name.function.methodType(); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString()); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false); } static private Class[] STATICALLY_INVOCABLE_PACKAGES = { @@ -586,6 +749,10 @@ class InvokerBytecodeGenerator { //MethodHandle.class already covered }; + static boolean isStaticallyInvocable(Name name) { + return isStaticallyInvocable(name.function.member()); + } + static boolean isStaticallyInvocable(MemberName member) { if (member == null) return false; if (member.isConstructor()) return false; @@ -612,6 +779,8 @@ class InvokerBytecodeGenerator { } static boolean isStaticallyNameable(Class cls) { + if (cls == Object.class) + return true; while (cls.isArray()) cls = cls.getComponentType(); if (cls.isPrimitive()) @@ -632,12 +801,17 @@ class InvokerBytecodeGenerator { return false; } + void emitStaticInvoke(Name name) { + emitStaticInvoke(name.function.member(), name); + } + /** * Emit an invoke for the given name, using the MemberName directly. */ void emitStaticInvoke(MemberName member, Name name) { assert(member.equals(name.function.member())); - String cname = getInternalName(member.getDeclaringClass()); + Class defc = member.getDeclaringClass(); + String cname = getInternalName(defc); String mname = member.getName(); String mtype; byte refKind = member.getReferenceKind(); @@ -654,9 +828,7 @@ class InvokerBytecodeGenerator { } // push arguments - for (int i = 0; i < name.arguments.length; i++) { - emitPushArgument(name, i); - } + emitPushArguments(name); // invocation if (member.isMethod()) { @@ -667,6 +839,52 @@ class InvokerBytecodeGenerator { mtype = MethodType.toFieldDescriptorString(member.getFieldType()); mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype); } + // Issue a type assertion for the result, so we can avoid casts later. + if (name.type == L_TYPE) { + Class rtype = member.getInvocationType().returnType(); + assert(!rtype.isPrimitive()); + if (rtype != Object.class && !rtype.isInterface()) { + assertStaticType(rtype, name); + } + } + } + + void emitNewArray(Name name) throws InternalError { + Class rtype = name.function.methodType().returnType(); + if (name.arguments.length == 0) { + // The array will be a constant. + Object emptyArray; + try { + emptyArray = name.function.resolvedHandle.invoke(); + } catch (Throwable ex) { + throw newInternalError(ex); + } + assert(java.lang.reflect.Array.getLength(emptyArray) == 0); + assert(emptyArray.getClass() == rtype); // exact typing + mv.visitLdcInsn(constantPlaceholder(emptyArray)); + emitReferenceCast(rtype, emptyArray); + return; + } + Class arrayElementType = rtype.getComponentType(); + assert(arrayElementType != null); + emitIconstInsn(name.arguments.length); + int xas = Opcodes.AASTORE; + if (!arrayElementType.isPrimitive()) { + mv.visitTypeInsn(Opcodes.ANEWARRAY, getInternalName(arrayElementType)); + } else { + byte tc = arrayTypeCode(Wrapper.forPrimitiveType(arrayElementType)); + xas = arrayInsnOpcode(tc, xas); + mv.visitIntInsn(Opcodes.NEWARRAY, tc); + } + // store arguments + for (int i = 0; i < name.arguments.length; i++) { + mv.visitInsn(Opcodes.DUP); + emitIconstInsn(i); + emitPushArgument(name, i); + mv.visitInsn(xas); + } + // the array is left on the stack + assertStaticType(rtype, name); } int refKindOpcode(byte refKind) { switch (refKind) { @@ -708,6 +926,21 @@ class InvokerBytecodeGenerator { !member.isPublic() && !member.isStatic(); } + /** + * Check if MemberName is a call to MethodHandle.linkToStatic, etc. + */ + private boolean isLinkerMethodInvoke(Name name) { + if (name.function == null) + return false; + if (name.arguments.length < 1) + return false; // must have MH argument + MemberName member = name.function.member(); + return member != null && + member.getDeclaringClass() == MethodHandle.class && + !member.isPublic() && member.isStatic() && + member.getName().startsWith("linkTo"); + } + /** * Check if i-th name is a call to MethodHandleImpl.selectAlternative. */ @@ -756,7 +989,9 @@ class InvokerBytecodeGenerator { * t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I} * }
*/ - private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + assert isStaticallyInvocable(invokeBasicName); + Name receiver = (Name) invokeBasicName.arguments[0]; Label L_fallback = new Label(); @@ -764,15 +999,15 @@ class InvokerBytecodeGenerator { // load test result emitPushArgument(selectAlternativeName, 0); - mv.visitInsn(Opcodes.ICONST_1); // if_icmpne L_fallback - mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback); + mv.visitJumpInsn(Opcodes.IFEQ, L_fallback); // invoke selectAlternativeName.arguments[1] + Class[] preForkClasses = localClasses.clone(); emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot - emitInvoke(invokeBasicName); + emitStaticInvoke(invokeBasicName); // goto L_done mv.visitJumpInsn(Opcodes.GOTO, L_done); @@ -781,12 +1016,17 @@ class InvokerBytecodeGenerator { mv.visitLabel(L_fallback); // invoke selectAlternativeName.arguments[2] + System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot - emitInvoke(invokeBasicName); + emitStaticInvoke(invokeBasicName); // L_done: mv.visitLabel(L_done); + // for now do not bother to merge typestate; just reset to the dominator state + System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); + + return invokeBasicName; // return what's on stack } /** @@ -809,7 +1049,7 @@ class InvokerBytecodeGenerator { * return a3.invokeBasic(ex, a6, a7); * }} */ - private void emitGuardWithCatch(int pos) { + private Name emitGuardWithCatch(int pos) { Name args = lambdaForm.names[pos]; Name invoker = lambdaForm.names[pos+1]; Name result = lambdaForm.names[pos+2]; @@ -860,6 +1100,12 @@ class InvokerBytecodeGenerator { mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(L_done); + + return result; + } + + private void emitPushArguments(Name args) { + emitPushArguments(args, 0); } private void emitPushArguments(Name args, int start) { @@ -870,75 +1116,69 @@ class InvokerBytecodeGenerator { private void emitPushArgument(Name name, int paramIndex) { Object arg = name.arguments[paramIndex]; - char ptype = name.function.parameterType(paramIndex); - MethodType mtype = name.function.methodType(); + Class ptype = name.function.methodType().parameterType(paramIndex); + emitPushArgument(ptype, arg); + } + + private void emitPushArgument(Class ptype, Object arg) { + BasicType bptype = basicType(ptype); if (arg instanceof Name) { Name n = (Name) arg; emitLoadInsn(n.type, n.index()); - emitImplicitConversion(n.type, mtype.parameterType(paramIndex)); - } else if ((arg == null || arg instanceof String) && ptype == 'L') { + emitImplicitConversion(n.type, ptype, n); + } else if ((arg == null || arg instanceof String) && bptype == L_TYPE) { emitConst(arg); } else { - if (Wrapper.isWrapperType(arg.getClass()) && ptype != 'L') { + if (Wrapper.isWrapperType(arg.getClass()) && bptype != L_TYPE) { emitConst(arg); } else { mv.visitLdcInsn(constantPlaceholder(arg)); - emitImplicitConversion('L', mtype.parameterType(paramIndex)); + emitImplicitConversion(L_TYPE, ptype, arg); } } } + /** + * Store the name to its local, if necessary. + */ + private void emitStoreResult(Name name) { + if (name != null && name.type != V_TYPE) { + // non-void: actually assign + emitStoreInsn(name.type, name.index()); + } + } + /** * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type. */ - private void emitReturn() { + private void emitReturn(Name onStack) { // return statement - if (lambdaForm.result == -1) { + Class rclass = invokerType.returnType(); + BasicType rtype = lambdaForm.returnType(); + assert(rtype == basicType(rclass)); // must agree + if (rtype == V_TYPE) { // void mv.visitInsn(Opcodes.RETURN); + // it doesn't matter what rclass is; the JVM will discard any value } else { LambdaForm.Name rn = lambdaForm.names[lambdaForm.result]; - char rtype = Wrapper.basicTypeChar(invokerType.returnType()); // put return value on the stack if it is not already there - if (lambdaForm.result != lambdaForm.names.length - 1) { - emitLoadInsn(rn.type, lambdaForm.result); + if (rn != onStack) { + emitLoadInsn(rtype, lambdaForm.result); } - // potentially generate cast - // rtype is the return type of the invoker - generated code must conform to this - // rn.type is the type of the result Name in the LF - if (rtype != rn.type) { - // need cast - if (rtype == 'L') { - // possibly cast the primitive to the correct type for boxing - char boxedType = Wrapper.forWrapperType(invokerType.returnType()).basicTypeChar(); - if (boxedType != rn.type) { - emitPrimCast(rn.type, boxedType); - } - // cast primitive to reference ("boxing") - emitBoxing(invokerType.returnType()); - } else { - // to-primitive cast - if (rn.type != 'L') { - // prim-to-prim cast - emitPrimCast(rn.type, rtype); - } else { - // ref-to-prim cast ("unboxing") - throw new InternalError("no ref-to-prim (unboxing) casts supported right now"); - } - } - } + emitImplicitConversion(rtype, rclass, rn); // generate actual return statement - emitReturnInsn(invokerType.returnType()); + emitReturnInsn(rtype); } } /** * Emit a type conversion bytecode casting from "from" to "to". */ - private void emitPrimCast(char from, char to) { + private void emitPrimCast(Wrapper from, Wrapper to) { // Here's how. // - indicates forbidden // <-> indicates implicit @@ -955,17 +1195,15 @@ class InvokerBytecodeGenerator { // no cast required, should be dead code anyway return; } - Wrapper wfrom = Wrapper.forBasicType(from); - Wrapper wto = Wrapper.forBasicType(to); - if (wfrom.isSubwordOrInt()) { + if (from.isSubwordOrInt()) { // cast from {byte,short,char,int} to anything emitI2X(to); } else { // cast from {long,float,double} to anything - if (wto.isSubwordOrInt()) { + if (to.isSubwordOrInt()) { // cast to {byte,short,char,int} emitX2I(from); - if (wto.bitWidth() < 32) { + if (to.bitWidth() < 32) { // targets other than int require another conversion emitI2X(to); } @@ -973,20 +1211,26 @@ class InvokerBytecodeGenerator { // cast to {long,float,double} - this is verbose boolean error = false; switch (from) { - case 'J': - if (to == 'F') { mv.visitInsn(Opcodes.L2F); } - else if (to == 'D') { mv.visitInsn(Opcodes.L2D); } - else error = true; + case LONG: + switch (to) { + case FLOAT: mv.visitInsn(Opcodes.L2F); break; + case DOUBLE: mv.visitInsn(Opcodes.L2D); break; + default: error = true; break; + } break; - case 'F': - if (to == 'J') { mv.visitInsn(Opcodes.F2L); } - else if (to == 'D') { mv.visitInsn(Opcodes.F2D); } - else error = true; + case FLOAT: + switch (to) { + case LONG : mv.visitInsn(Opcodes.F2L); break; + case DOUBLE: mv.visitInsn(Opcodes.F2D); break; + default: error = true; break; + } break; - case 'D': - if (to == 'J') { mv.visitInsn(Opcodes.D2L); } - else if (to == 'F') { mv.visitInsn(Opcodes.D2F); } - else error = true; + case DOUBLE: + switch (to) { + case LONG : mv.visitInsn(Opcodes.D2L); break; + case FLOAT: mv.visitInsn(Opcodes.D2F); break; + default: error = true; break; + } break; default: error = true; @@ -999,16 +1243,16 @@ class InvokerBytecodeGenerator { } } - private void emitI2X(char type) { + private void emitI2X(Wrapper type) { switch (type) { - case 'B': mv.visitInsn(Opcodes.I2B); break; - case 'S': mv.visitInsn(Opcodes.I2S); break; - case 'C': mv.visitInsn(Opcodes.I2C); break; - case 'I': /* naught */ break; - case 'J': mv.visitInsn(Opcodes.I2L); break; - case 'F': mv.visitInsn(Opcodes.I2F); break; - case 'D': mv.visitInsn(Opcodes.I2D); break; - case 'Z': + case BYTE: mv.visitInsn(Opcodes.I2B); break; + case SHORT: mv.visitInsn(Opcodes.I2S); break; + case CHAR: mv.visitInsn(Opcodes.I2C); break; + case INT: /* naught */ break; + case LONG: mv.visitInsn(Opcodes.I2L); break; + case FLOAT: mv.visitInsn(Opcodes.I2F); break; + case DOUBLE: mv.visitInsn(Opcodes.I2D); break; + case BOOLEAN: // For compatibility with ValueConversions and explicitCastArguments: mv.visitInsn(Opcodes.ICONST_1); mv.visitInsn(Opcodes.IAND); @@ -1017,39 +1261,24 @@ class InvokerBytecodeGenerator { } } - private void emitX2I(char type) { + private void emitX2I(Wrapper type) { switch (type) { - case 'J': mv.visitInsn(Opcodes.L2I); break; - case 'F': mv.visitInsn(Opcodes.F2I); break; - case 'D': mv.visitInsn(Opcodes.D2I); break; - default: throw new InternalError("unknown type: " + type); + case LONG: mv.visitInsn(Opcodes.L2I); break; + case FLOAT: mv.visitInsn(Opcodes.F2I); break; + case DOUBLE: mv.visitInsn(Opcodes.D2I); break; + default: throw new InternalError("unknown type: " + type); } } - private static String basicTypeCharSignature(String prefix, MethodType type) { - StringBuilder buf = new StringBuilder(prefix); - for (Class ptype : type.parameterList()) - buf.append(Wrapper.forBasicType(ptype).basicTypeChar()); - buf.append('_').append(Wrapper.forBasicType(type.returnType()).basicTypeChar()); - return buf.toString(); - } - /** * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments. */ static MemberName generateLambdaFormInterpreterEntryPoint(String sig) { - assert(LambdaForm.isValidSignature(sig)); - //System.out.println("generateExactInvoker "+sig); - // compute method type - // first parameter and return type - char tret = LambdaForm.signatureReturn(sig); - MethodType type = MethodType.methodType(LambdaForm.typeClass(tret), MethodHandle.class); - // other parameter types - int arity = LambdaForm.signatureArity(sig); - for (int i = 1; i < arity; i++) { - type = type.appendParameterTypes(LambdaForm.typeClass(sig.charAt(i))); - } - InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", "interpret_"+tret, type); + assert(isValidSignature(sig)); + String name = "interpret_"+signatureReturn(sig).basicTypeChar(); + MethodType type = signatureType(sig); // sig includes leading argument + type = type.changeParameterType(0, MethodHandle.class); + InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", name, type); return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } @@ -1071,10 +1300,10 @@ class InvokerBytecodeGenerator { Class ptype = invokerType.parameterType(i); mv.visitInsn(Opcodes.DUP); emitIconstInsn(i); - emitLoadInsn(Wrapper.basicTypeChar(ptype), i); + emitLoadInsn(basicType(ptype), i); // box if primitive type if (ptype.isPrimitive()) { - emitBoxing(ptype); + emitBoxing(Wrapper.forPrimitiveType(ptype)); } mv.visitInsn(Opcodes.AASTORE); } @@ -1082,16 +1311,16 @@ class InvokerBytecodeGenerator { emitAloadInsn(0); mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", "Ljava/lang/invoke/LambdaForm;"); mv.visitInsn(Opcodes.SWAP); // swap form and array; avoid local variable - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;", false); // maybe unbox Class rtype = invokerType.returnType(); if (rtype.isPrimitive() && rtype != void.class) { - emitUnboxing(Wrapper.asWrapperType(rtype)); + emitUnboxing(Wrapper.forPrimitiveType(rtype)); } // return statement - emitReturnInsn(rtype); + emitReturnInsn(basicType(rtype)); classFileEpilogue(); bogusMethod(invokerType); @@ -1105,14 +1334,12 @@ class InvokerBytecodeGenerator { * Generate bytecode for a NamedFunction invoker. */ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { - MethodType invokerType = LambdaForm.NamedFunction.INVOKER_METHOD_TYPE; - String invokerName = basicTypeCharSignature("invoke_", typeForm.erasedType()); + MethodType invokerType = NamedFunction.INVOKER_METHOD_TYPE; + String invokerName = "invoke_" + shortenSignature(basicTypeSignature(typeForm.erasedType())); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType); return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm)); } - static int nfi = 0; - private byte[] generateNamedFunctionInvokerImpl(MethodTypeForm typeForm) { MethodType dstType = typeForm.erasedType(); classFilePrologue(); @@ -1138,14 +1365,14 @@ class InvokerBytecodeGenerator { Class sptype = dstType.basicType().wrap().parameterType(i); Wrapper dstWrapper = Wrapper.forBasicType(dptype); Wrapper srcWrapper = dstWrapper.isSubwordOrInt() ? Wrapper.INT : dstWrapper; // narrow subword from int - emitUnboxing(srcWrapper.wrapperType()); - emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar()); + emitUnboxing(srcWrapper); + emitPrimCast(srcWrapper, dstWrapper); } } // Invoke String targetDesc = dstType.basicType().toMethodDescriptorString(); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", targetDesc); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", targetDesc, false); // Box primitive types Class rtype = dstType.returnType(); @@ -1153,15 +1380,15 @@ class InvokerBytecodeGenerator { Wrapper srcWrapper = Wrapper.forBasicType(rtype); Wrapper dstWrapper = srcWrapper.isSubwordOrInt() ? Wrapper.INT : srcWrapper; // widen subword to int // boolean casts not allowed - emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar()); - emitBoxing(dstWrapper.primitiveType()); + emitPrimCast(srcWrapper, dstWrapper); + emitBoxing(dstWrapper); } // If the return type is void we return a null reference. if (rtype == void.class) { mv.visitInsn(Opcodes.ACONST_NULL); } - emitReturnInsn(Object.class); // NOTE: NamedFunction invokers always return a reference value. + emitReturnInsn(L_TYPE); // NOTE: NamedFunction invokers always return a reference value. classFileEpilogue(); bogusMethod(dstType); diff --git a/src/share/classes/java/lang/invoke/Invokers.java b/src/share/classes/java/lang/invoke/Invokers.java index b9c18b548bd5ec5962e764d69825a52962911d4b..14aef1bd7b46284b2209727dca4c511dcbd82fb0 100644 --- a/src/share/classes/java/lang/invoke/Invokers.java +++ b/src/share/classes/java/lang/invoke/Invokers.java @@ -25,8 +25,9 @@ package java.lang.invoke; +import java.lang.reflect.Array; import java.util.Arrays; -import sun.invoke.empty.Empty; + import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @@ -40,52 +41,63 @@ class Invokers { // exact type (sans leading taget MH) for the outgoing call private final MethodType targetType; - // FIXME: Get rid of the invokers that are not useful. - - // exact invoker for the outgoing call - private /*lazy*/ MethodHandle exactInvoker; - private /*lazy*/ MethodHandle basicInvoker; // invokeBasic (unchecked exact) - - // erased (partially untyped but with primitives) invoker for the outgoing call - // FIXME: get rid of - private /*lazy*/ MethodHandle erasedInvoker; - // FIXME: get rid of - /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric - - // general invoker for the outgoing call - private /*lazy*/ MethodHandle generalInvoker; - - // general invoker for the outgoing call, uses varargs - private /*lazy*/ MethodHandle varargsInvoker; - - // general invoker for the outgoing call; accepts a trailing Object[] - private final /*lazy*/ MethodHandle[] spreadInvokers; - - // invoker for an unbound callsite - private /*lazy*/ MethodHandle uninitializedCallSite; + // Cached adapter information: + private final @Stable MethodHandle[] invokers = new MethodHandle[INV_LIMIT]; + // Indexes into invokers: + static final int + INV_EXACT = 0, // MethodHandles.exactInvoker + INV_GENERIC = 1, // MethodHandles.invoker (generic invocation) + INV_BASIC = 2, // MethodHandles.basicInvoker + INV_LIMIT = 3; /** Compute and cache information common to all collecting adapters * that implement members of the erasure-family of the given erased type. */ /*non-public*/ Invokers(MethodType targetType) { this.targetType = targetType; - this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1]; } /*non-public*/ MethodHandle exactInvoker() { - MethodHandle invoker = exactInvoker; + MethodHandle invoker = cachedInvoker(INV_EXACT); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(true); - exactInvoker = invoker; - return invoker; + return setCachedInvoker(INV_EXACT, invoker); } - /*non-public*/ MethodHandle generalInvoker() { - MethodHandle invoker = generalInvoker; + /*non-public*/ MethodHandle genericInvoker() { + MethodHandle invoker = cachedInvoker(INV_GENERIC); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(false); - generalInvoker = invoker; - return invoker; + return setCachedInvoker(INV_GENERIC, invoker); + } + + /*non-public*/ MethodHandle basicInvoker() { + MethodHandle invoker = cachedInvoker(INV_BASIC); + if (invoker != null) return invoker; + MethodType basicType = targetType.basicType(); + if (basicType != targetType) { + // double cache; not used significantly + return setCachedInvoker(INV_BASIC, basicType.invokers().basicInvoker()); + } + invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_BASIC_INV); + if (invoker == null) { + MemberName method = invokeBasicMethod(basicType); + invoker = DirectMethodHandle.make(method); + assert(checkInvoker(invoker)); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_BASIC_INV, invoker); + } + return setCachedInvoker(INV_BASIC, invoker); + } + + private MethodHandle cachedInvoker(int idx) { + return invokers[idx]; + } + + private synchronized MethodHandle setCachedInvoker(int idx, final MethodHandle invoker) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = invokers[idx]; + if (prev != null) return prev; + return invokers[idx] = invoker; } private MethodHandle makeExactOrGeneralInvoker(boolean isExact) { @@ -95,7 +107,7 @@ class Invokers { LambdaForm lform = invokeHandleForm(mtype, false, which); MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); String whichName = (isExact ? "invokeExact" : "invoke"); - invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype)); + invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype), false); assert(checkInvoker(invoker)); maybeCompileToBytecode(invoker); return invoker; @@ -110,21 +122,6 @@ class Invokers { } } - /*non-public*/ MethodHandle basicInvoker() { - MethodHandle invoker = basicInvoker; - if (invoker != null) return invoker; - MethodType basicType = targetType.basicType(); - if (basicType != targetType) { - // double cache; not used significantly - return basicInvoker = basicType.invokers().basicInvoker(); - } - MemberName method = invokeBasicMethod(basicType); - invoker = DirectMethodHandle.make(method); - assert(checkInvoker(invoker)); - basicInvoker = invoker; - return invoker; - } - // This next one is called from LambdaForm.NamedFunction.. /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) { assert(basicType == basicType.basicType()); @@ -145,87 +142,42 @@ class Invokers { return true; } - // FIXME: get rid of - /*non-public*/ MethodHandle erasedInvoker() { - MethodHandle xinvoker = exactInvoker(); - MethodHandle invoker = erasedInvoker; - if (invoker != null) return invoker; - MethodType erasedType = targetType.erase(); - invoker = xinvoker.asType(erasedType.invokerType()); - erasedInvoker = invoker; - return invoker; - } - + /** + * Find or create an invoker which passes unchanged a given number of arguments + * and spreads the rest from a trailing array argument. + * The invoker target type is the post-spread type {@code (TYPEOF(uarg*), TYPEOF(sarg*))=>RT}. + * All the {@code sarg}s must have a common type {@code C}. (If there are none, {@code Object} is assumed.} + * @param leadingArgCount the number of unchanged (non-spread) arguments + * @return {@code invoker.invokeExact(mh, uarg*, C[]{sarg*}) := (RT)mh.invoke(uarg*, sarg*)} + */ /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { - MethodHandle vaInvoker = spreadInvokers[leadingArgCount]; - if (vaInvoker != null) return vaInvoker; int spreadArgCount = targetType.parameterCount() - leadingArgCount; - MethodType spreadInvokerType = targetType - .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class); - if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { - // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a) - // where ginvoker.invoke(mh, a*) => mh.invoke(a*). - MethodHandle genInvoker = generalInvoker(); - vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount); - } else { - // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]). - // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) - // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) - MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType); - MethodHandle makeSpreader; - try { - makeSpreader = IMPL_LOOKUP - .findVirtual(MethodHandle.class, "asSpreader", - MethodType.methodType(MethodHandle.class, Class.class, int.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount); - vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); + MethodType postSpreadType = targetType; + Class argArrayType = impliedRestargType(postSpreadType, leadingArgCount); + if (postSpreadType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { + return genericInvoker().asSpreader(argArrayType, spreadArgCount); } - assert(vaInvoker.type().equals(spreadInvokerType.invokerType())); - maybeCompileToBytecode(vaInvoker); - spreadInvokers[leadingArgCount] = vaInvoker; - return vaInvoker; + // Cannot build a generic invoker here of type ginvoker.invoke(mh, a*[254]). + // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) + // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) + MethodType preSpreadType = postSpreadType + .replaceParameterTypes(leadingArgCount, postSpreadType.parameterCount(), argArrayType); + MethodHandle arrayInvoker = MethodHandles.invoker(preSpreadType); + MethodHandle makeSpreader = MethodHandles.insertArguments(Lazy.MH_asSpreader, 1, argArrayType, spreadArgCount); + return MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); } - /*non-public*/ MethodHandle varargsInvoker() { - MethodHandle vaInvoker = varargsInvoker; - if (vaInvoker != null) return vaInvoker; - vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType()); - varargsInvoker = vaInvoker; - return vaInvoker; - } - - private static MethodHandle THROW_UCS = null; - - /*non-public*/ MethodHandle uninitializedCallSite() { - MethodHandle invoker = uninitializedCallSite; - if (invoker != null) return invoker; - if (targetType.parameterCount() > 0) { - MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); - Invokers invokers0 = type0.invokers(); - invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), - 0, targetType.parameterList()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; + private static Class impliedRestargType(MethodType restargType, int fromPos) { + if (restargType.isGeneric()) return Object[].class; // can be nothing else + int maxPos = restargType.parameterCount(); + if (fromPos >= maxPos) return Object[].class; // reasonable default + Class argType = restargType.parameterType(fromPos); + for (int i = fromPos+1; i < maxPos; i++) { + if (argType != restargType.parameterType(i)) + throw newIllegalArgumentException("need homogeneous rest arguments", restargType); } - invoker = THROW_UCS; - if (invoker == null) { - try { - THROW_UCS = invoker = IMPL_LOOKUP - .findStatic(CallSite.class, "uninitializedCallSite", - MethodType.methodType(Empty.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - } - invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType())); - invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; + if (argType == Object.class) return Object[].class; + return Array.newInstance(argType, 0).getClass(); } public String toString() { @@ -308,7 +260,9 @@ class Invokers { : Arrays.asList(mtype, customized, which, nameCursor, names.length); if (MTYPE_ARG >= INARG_LIMIT) { assert(names[MTYPE_ARG] == null); - NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0); + BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L(); + names[THIS_MH] = names[THIS_MH].withConstraint(speciesData); + NamedFunction getter = speciesData.getterFunction(0); names[MTYPE_ARG] = new Name(getter, names[THIS_MH]); // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM) } @@ -360,9 +314,6 @@ class Invokers { Object checkGenericType(Object mhObj, Object expectedObj) { MethodHandle mh = (MethodHandle) mhObj; MethodType expected = (MethodType) expectedObj; - if (mh.type() == expected) return mh; - MethodHandle atc = mh.asTypeCache; - if (atc != null && atc.type() == expected) return atc; return mh.asType(expected); /* Maybe add more paths here. Possible optimizations: * for (R)MH.invoke(a*), @@ -436,27 +387,40 @@ class Invokers { } // Local constant functions: - private static final NamedFunction NF_checkExactType; - private static final NamedFunction NF_checkGenericType; - private static final NamedFunction NF_asType; - private static final NamedFunction NF_getCallSiteTarget; + private static final NamedFunction + NF_checkExactType, + NF_checkGenericType, + NF_getCallSiteTarget; static { try { - NF_checkExactType = new NamedFunction(Invokers.class - .getDeclaredMethod("checkExactType", Object.class, Object.class)); - NF_checkGenericType = new NamedFunction(Invokers.class - .getDeclaredMethod("checkGenericType", Object.class, Object.class)); - NF_asType = new NamedFunction(MethodHandle.class - .getDeclaredMethod("asType", MethodType.class)); - NF_getCallSiteTarget = new NamedFunction(Invokers.class - .getDeclaredMethod("getCallSiteTarget", Object.class)); - NF_checkExactType.resolve(); - NF_checkGenericType.resolve(); - NF_getCallSiteTarget.resolve(); - // bound + NamedFunction nfs[] = { + NF_checkExactType = new NamedFunction(Invokers.class + .getDeclaredMethod("checkExactType", Object.class, Object.class)), + NF_checkGenericType = new NamedFunction(Invokers.class + .getDeclaredMethod("checkGenericType", Object.class, Object.class)), + NF_getCallSiteTarget = new NamedFunction(Invokers.class + .getDeclaredMethod("getCallSiteTarget", Object.class)) + }; + for (NamedFunction nf : nfs) { + // Each nf must be statically invocable or we get tied up in our bootstraps. + assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf; + nf.resolve(); + } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } } + private static class Lazy { + private static final MethodHandle MH_asSpreader; + + static { + try { + MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader", + MethodType.methodType(MethodHandle.class, Class.class, int.class)); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } + } } diff --git a/src/share/classes/java/lang/invoke/LambdaForm.java b/src/share/classes/java/lang/invoke/LambdaForm.java index a8291e273c0fcb23aa1653219d28a46680320dd6..b83040647c5c105f9ba2ac8bc17667d9d38b0709 100644 --- a/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/share/classes/java/lang/invoke/LambdaForm.java @@ -27,17 +27,16 @@ package java.lang.invoke; import java.lang.annotation.*; import java.lang.reflect.Method; -import java.util.Map; import java.util.List; import java.util.Arrays; -import java.util.ArrayList; import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; + import sun.invoke.util.Wrapper; +import java.lang.reflect.Field; + +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; -import java.lang.reflect.Field; -import java.util.Objects; /** * The symbolic, non-executable form of a method handle's invocation semantics. @@ -125,19 +124,136 @@ class LambdaForm { MemberName vmentry; // low-level behavior, or null if not yet prepared private boolean isCompiled; - // Caches for common structural transforms: - LambdaForm[] bindCache; + Object transformCache; // managed by LambdaFormEditor public static final int VOID_RESULT = -1, LAST_RESULT = -2; + enum BasicType { + L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types + I_TYPE('I', int.class, Wrapper.INT), + J_TYPE('J', long.class, Wrapper.LONG), + F_TYPE('F', float.class, Wrapper.FLOAT), + D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types + V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts + + static final BasicType[] ALL_TYPES = BasicType.values(); + static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1); + + static final int ARG_TYPE_LIMIT = ARG_TYPES.length; + static final int TYPE_LIMIT = ALL_TYPES.length; + + private final char btChar; + private final Class btClass; + private final Wrapper btWrapper; + + private BasicType(char btChar, Class btClass, Wrapper wrapper) { + this.btChar = btChar; + this.btClass = btClass; + this.btWrapper = wrapper; + } + + char basicTypeChar() { + return btChar; + } + Class basicTypeClass() { + return btClass; + } + Wrapper basicTypeWrapper() { + return btWrapper; + } + int basicTypeSlots() { + return btWrapper.stackSlots(); + } + + static BasicType basicType(byte type) { + return ALL_TYPES[type]; + } + static BasicType basicType(char type) { + switch (type) { + case 'L': return L_TYPE; + case 'I': return I_TYPE; + case 'J': return J_TYPE; + case 'F': return F_TYPE; + case 'D': return D_TYPE; + case 'V': return V_TYPE; + // all subword types are represented as ints + case 'Z': + case 'B': + case 'S': + case 'C': + return I_TYPE; + default: + throw newInternalError("Unknown type char: '"+type+"'"); + } + } + static BasicType basicType(Wrapper type) { + char c = type.basicTypeChar(); + return basicType(c); + } + static BasicType basicType(Class type) { + if (!type.isPrimitive()) return L_TYPE; + return basicType(Wrapper.forPrimitiveType(type)); + } + + static char basicTypeChar(Class type) { + return basicType(type).btChar; + } + static BasicType[] basicTypes(List> types) { + BasicType[] btypes = new BasicType[types.size()]; + for (int i = 0; i < btypes.length; i++) { + btypes[i] = basicType(types.get(i)); + } + return btypes; + } + static BasicType[] basicTypes(String types) { + BasicType[] btypes = new BasicType[types.length()]; + for (int i = 0; i < btypes.length; i++) { + btypes[i] = basicType(types.charAt(i)); + } + return btypes; + } + static byte[] basicTypesOrd(BasicType[] btypes) { + byte[] ords = new byte[btypes.length]; + for (int i = 0; i < btypes.length; i++) { + ords[i] = (byte)btypes[i].ordinal(); + } + return ords; + } + static boolean isBasicTypeChar(char c) { + return "LIJFDV".indexOf(c) >= 0; + } + static boolean isArgBasicTypeChar(char c) { + return "LIJFD".indexOf(c) >= 0; + } + + static { assert(checkBasicType()); } + private static boolean checkBasicType() { + for (int i = 0; i < ARG_TYPE_LIMIT; i++) { + assert ARG_TYPES[i].ordinal() == i; + assert ARG_TYPES[i] == ALL_TYPES[i]; + } + for (int i = 0; i < TYPE_LIMIT; i++) { + assert ALL_TYPES[i].ordinal() == i; + } + assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE; + assert !Arrays.asList(ARG_TYPES).contains(V_TYPE); + return true; + } + } + LambdaForm(String debugName, int arity, Name[] names, int result) { assert(namesOK(arity, names)); this.arity = arity; this.result = fixResult(result, names); this.names = names.clone(); - this.debugName = debugName; - normalize(); + this.debugName = fixDebugName(debugName); + int maxOutArity = normalize(); + if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) { + // Cannot use LF interpreter on very high arity expressions. + assert(maxOutArity <= MethodType.MAX_JVM_ARITY); + compileToBytecode(); + } } LambdaForm(String debugName, @@ -168,12 +284,12 @@ class LambdaForm { // Called only from getPreparedForm. assert(isValidSignature(sig)); this.arity = signatureArity(sig); - this.result = (signatureReturn(sig) == 'V' ? -1 : arity); + this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity); this.names = buildEmptyNames(arity, sig); this.debugName = "LF.zero"; assert(nameRefsAreLegal()); assert(isEmpty()); - assert(sig.equals(basicTypeSignature())); + assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature(); } private static Name[] buildEmptyNames(int arity, String basicTypeSignature) { @@ -181,24 +297,55 @@ class LambdaForm { int resultPos = arity + 1; // skip '_' if (arity < 0 || basicTypeSignature.length() != resultPos+1) throw new IllegalArgumentException("bad arity for "+basicTypeSignature); - int numRes = (basicTypeSignature.charAt(resultPos) == 'V' ? 0 : 1); + int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1); Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity)); for (int i = 0; i < numRes; i++) { - names[arity + i] = constantZero(arity + i, basicTypeSignature.charAt(resultPos + i)); + Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i)))); + names[arity + i] = zero.newIndex(arity + i); } return names; } private static int fixResult(int result, Name[] names) { - if (result >= 0) { - if (names[result].type == 'V') - return -1; - } else if (result == LAST_RESULT) { - return names.length - 1; - } + if (result == LAST_RESULT) + result = names.length - 1; // might still be void + if (result >= 0 && names[result].type == V_TYPE) + result = VOID_RESULT; return result; } + private static String fixDebugName(String debugName) { + if (DEBUG_NAME_COUNTERS != null) { + int under = debugName.indexOf('_'); + int length = debugName.length(); + if (under < 0) under = length; + String debugNameStem = debugName.substring(0, under); + Integer ctr; + synchronized (DEBUG_NAME_COUNTERS) { + ctr = DEBUG_NAME_COUNTERS.get(debugNameStem); + if (ctr == null) ctr = 0; + DEBUG_NAME_COUNTERS.put(debugNameStem, ctr+1); + } + StringBuilder buf = new StringBuilder(debugNameStem); + buf.append('_'); + int leadingZero = buf.length(); + buf.append((int) ctr); + for (int i = buf.length() - leadingZero; i < 3; i++) + buf.insert(leadingZero, '0'); + if (under < length) { + ++under; // skip "_" + while (under < length && Character.isDigit(debugName.charAt(under))) { + ++under; + } + if (under < length && debugName.charAt(under) == '_') ++under; + if (under < length) + buf.append('_').append(debugName, under, length); + } + return buf.toString(); + } + return debugName; + } + private static boolean namesOK(int arity, Name[] names) { for (int i = 0; i < names.length; i++) { Name n = names[i]; @@ -211,9 +358,12 @@ class LambdaForm { return true; } - /** Renumber and/or replace params so that they are interned and canonically numbered. */ - private void normalize() { + /** Renumber and/or replace params so that they are interned and canonically numbered. + * @return maximum argument list length among the names (since we have to pass over them anyway) + */ + private int normalize() { Name[] oldNames = null; + int maxOutArity = 0; int changesStart = 0; for (int i = 0; i < names.length; i++) { Name n = names[i]; @@ -224,6 +374,8 @@ class LambdaForm { } names[i] = n.cloneWithIndex(i); } + if (n.arguments != null && maxOutArity < n.arguments.length) + maxOutArity = n.arguments.length; } if (oldNames != null) { int startFixing = arity; @@ -250,6 +402,7 @@ class LambdaForm { } assert(nameRefsAreLegal()); } + return maxOutArity; } /** @@ -261,7 +414,7 @@ class LambdaForm { * This allows Name references to be freely reused to construct * fresh lambdas, without confusion. */ - private boolean nameRefsAreLegal() { + boolean nameRefsAreLegal() { assert(arity >= 0 && arity <= names.length); assert(result >= -1 && result < names.length); // Do all names possess an index consistent with their local definition order? @@ -294,16 +447,28 @@ class LambdaForm { // } /** Report the return type. */ - char returnType() { - if (result < 0) return 'V'; + BasicType returnType() { + if (result < 0) return V_TYPE; Name n = names[result]; return n.type; } /** Report the N-th argument type. */ - char parameterType(int n) { + BasicType parameterType(int n) { + return parameter(n).type; + } + + /** Report the N-th argument name. */ + Name parameter(int n) { assert(n < arity); - return names[n].type; + Name param = names[n]; + assert(param.isParam()); + return param; + } + + /** Report the N-th argument type constraint. */ + Object parameterConstraint(int n) { + return parameter(n).constraint; } /** Report the arity. */ @@ -311,6 +476,11 @@ class LambdaForm { return arity; } + /** Report the number of expressions (non-parameter names). */ + int expressionCount() { + return names.length - arity; + } + /** Return the method type corresponding to my basic type signature. */ MethodType methodType() { return signatureType(basicTypeSignature()); @@ -319,15 +489,15 @@ class LambdaForm { final String basicTypeSignature() { StringBuilder buf = new StringBuilder(arity() + 3); for (int i = 0, a = arity(); i < a; i++) - buf.append(parameterType(i)); - return buf.append('_').append(returnType()).toString(); + buf.append(parameterType(i).basicTypeChar()); + return buf.append('_').append(returnType().basicTypeChar()).toString(); } static int signatureArity(String sig) { assert(isValidSignature(sig)); return sig.indexOf('_'); } - static char signatureReturn(String sig) { - return sig.charAt(signatureArity(sig)+1); + static BasicType signatureReturn(String sig) { + return basicType(sig.charAt(signatureArity(sig) + 1)); } static boolean isValidSignature(String sig) { int arity = sig.indexOf('_'); @@ -339,27 +509,15 @@ class LambdaForm { char c = sig.charAt(i); if (c == 'V') return (i == siglen - 1 && arity == siglen - 2); - if (ALL_TYPES.indexOf(c) < 0) return false; // must be [LIJFD] + if (!isArgBasicTypeChar(c)) return false; // must be [LIJFD] } return true; // [LIJFD]*_[LIJFDV] } - static Class typeClass(char t) { - switch (t) { - case 'I': return int.class; - case 'J': return long.class; - case 'F': return float.class; - case 'D': return double.class; - case 'L': return Object.class; - case 'V': return void.class; - default: assert false; - } - return null; - } static MethodType signatureType(String sig) { Class[] ptypes = new Class[signatureArity(sig)]; for (int i = 0; i < ptypes.length; i++) - ptypes[i] = typeClass(sig.charAt(i)); - Class rtype = typeClass(signatureReturn(sig)); + ptypes[i] = basicType(sig.charAt(i)).btClass; + Class rtype = signatureReturn(sig).btClass; return MethodType.methodType(rtype, ptypes); } @@ -457,21 +615,12 @@ class LambdaForm { isCompiled = true; return vmentry; } catch (Error | Exception ex) { - throw newInternalError("compileToBytecode", ex); + throw newInternalError(this.toString(), ex); } } - private static final ConcurrentHashMap PREPARED_FORMS; - static { - int capacity = 512; // expect many distinct signatures over time - float loadFactor = 0.75f; // normal default - int writers = 1; - PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers); - } - - private static Map computeInitialPreparedForms() { + private static void computeInitialPreparedForms() { // Find all predefined invokers and associate them with canonical empty lambda forms. - HashMap forms = new HashMap<>(); for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) { if (!m.isStatic() || !m.isPackage()) continue; MethodType mt = m.getMethodType(); @@ -482,13 +631,9 @@ class LambdaForm { assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_')))); LambdaForm form = new LambdaForm(sig); form.vmentry = m; - form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form); - // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only - forms.put(sig, form); + form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form); } } - //System.out.println("computeInitialPreparedForms => "+forms); - return forms; } // Set this false to disable use of the interpret_L methods defined in this file. @@ -522,13 +667,11 @@ class LambdaForm { } private static LambdaForm getPreparedForm(String sig) { MethodType mtype = signatureType(sig); - //LambdaForm prep = PREPARED_FORMS.get(sig); LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET); if (prep != null) return prep; assert(isValidSignature(sig)); prep = new LambdaForm(sig); prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig); - //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep); return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep); } @@ -543,21 +686,21 @@ class LambdaForm { assert(mt.parameterCount() == arity-1); for (int i = 0; i < av.length; i++) { Class pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1)); - assert(valueMatches(sig.charAt(i), pt, av[i])); + assert(valueMatches(basicType(sig.charAt(i)), pt, av[i])); } return true; } - private static boolean valueMatches(char tc, Class type, Object x) { + private static boolean valueMatches(BasicType tc, Class type, Object x) { // The following line is needed because (...)void method handles can use non-void invokers - if (type == void.class) tc = 'V'; // can drop any kind of value + if (type == void.class) tc = V_TYPE; // can drop any kind of value assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type); switch (tc) { - case 'I': assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break; - case 'J': assert x instanceof Long : "instanceof Long: " + x; break; - case 'F': assert x instanceof Float : "instanceof Float: " + x; break; - case 'D': assert x instanceof Double : "instanceof Double: " + x; break; - case 'L': assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break; - case 'V': break; // allow anything here; will be dropped + case I_TYPE: assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break; + case J_TYPE: assert x instanceof Long : "instanceof Long: " + x; break; + case F_TYPE: assert x instanceof Float : "instanceof Float: " + x; break; + case D_TYPE: assert x instanceof Double : "instanceof Double: " + x; break; + case L_TYPE: assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break; + case V_TYPE: break; // allow anything here; will be dropped default: assert(false); } return true; @@ -584,10 +727,7 @@ class LambdaForm { /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */ private static final int COMPILE_THRESHOLD; static { - if (MethodHandleStatics.COMPILE_THRESHOLD != null) - COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD; - else - COMPILE_THRESHOLD = 30; // default value + COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD); } private int invocationCounter = 0; @@ -603,7 +743,9 @@ class LambdaForm { for (int i = argumentValues.length; i < values.length; i++) { values[i] = interpretName(names[i], values); } - return (result < 0) ? null : values[result]; + Object rv = (result < 0) ? null : values[result]; + assert(resultCheck(argumentValues, rv)); + return rv; } @Hidden @@ -660,28 +802,6 @@ class LambdaForm { return rval; } - //** This transform is applied (statically) to every name.function. */ - /* - private static MethodHandle eraseSubwordTypes(MethodHandle mh) { - MethodType mt = mh.type(); - if (mt.hasPrimitives()) { - mt = mt.changeReturnType(eraseSubwordType(mt.returnType())); - for (int i = 0; i < mt.parameterCount(); i++) { - mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i))); - } - mh = MethodHandles.explicitCastArguments(mh, mt); - } - return mh; - } - private static Class eraseSubwordType(Class type) { - if (!type.isPrimitive()) return type; - if (type == int.class) return type; - Wrapper w = Wrapper.forPrimitiveType(type); - if (w.isSubwordOrInt()) return int.class; - return type; - } - */ - static void traceInterpreter(String event, Object obj, Object... args) { if (TRACE_INTERPRETER) { System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : "")); @@ -694,8 +814,16 @@ class LambdaForm { assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length"; // also check that the leading (receiver) argument is somehow bound to this LF: assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0]; - assert(((MethodHandle)argumentValues[0]).internalForm() == this); + MethodHandle mh = (MethodHandle) argumentValues[0]; + assert(mh.internalForm() == this); // note: argument #0 could also be an interface wrapper, in the future + argumentTypesMatch(basicTypeSignature(), argumentValues); + return true; + } + private boolean resultCheck(Object[] argumentValues, Object result) { + MethodHandle mh = (MethodHandle) argumentValues[0]; + MethodType mt = mh.type(); + assert(valueMatches(returnType(), mt.returnType(), result)); return true; } @@ -714,7 +842,7 @@ class LambdaForm { if (i == arity) buf.append(")=>{"); Name n = names[i]; if (i >= arity) buf.append("\n "); - buf.append(n); + buf.append(n.paramString()); if (i < arity) { if (i+1 < arity) buf.append(","); continue; @@ -722,6 +850,7 @@ class LambdaForm { buf.append("=").append(n.exprString()); buf.append(";"); } + if (arity == names.length) buf.append(")=>{"); buf.append(result < 0 ? "void" : names[result]).append("}"); if (TRACE_INTERPRETER) { // Extra verbosity: @@ -731,135 +860,19 @@ class LambdaForm { return buf.toString(); } - /** - * Apply immediate binding for a Name in this form indicated by its position relative to the form. - * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not - * accepted as valid. - */ - LambdaForm bindImmediate(int pos, char basicType, Object value) { - // must be an argument, and the types must match - assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value); - - int arity2 = arity - 1; - Name[] names2 = new Name[names.length - 1]; - for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2 - Name n = names[r]; - if (n.isParam()) { - if (n.index == pos) { - // do not copy over the argument that is to be replaced with a literal, - // but adjust the write index - --w; - } else { - names2[w] = new Name(w, n.type); - } - } else { - Object[] arguments2 = new Object[n.arguments.length]; - for (int i = 0; i < n.arguments.length; ++i) { - Object arg = n.arguments[i]; - if (arg instanceof Name) { - int ni = ((Name) arg).index; - if (ni == pos) { - arguments2[i] = value; - } else if (ni < pos) { - // replacement position not yet passed - arguments2[i] = names2[ni]; - } else { - // replacement position passed - arguments2[i] = names2[ni - 1]; - } - } else { - arguments2[i] = arg; - } - } - names2[w] = new Name(n.function, arguments2); - names2[w].initIndex(w); - } - } - - int result2 = result == -1 ? -1 : result - 1; - return new LambdaForm(debugName, arity2, names2, result2); + @Override + public boolean equals(Object obj) { + return obj instanceof LambdaForm && equals((LambdaForm)obj); } - - LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) { - Name name = names[namePos]; - BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type); - return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData); - } - LambdaForm bind(Name name, Name binding, - BoundMethodHandle.SpeciesData oldData, - BoundMethodHandle.SpeciesData newData) { - int pos = name.index; - assert(name.isParam()); - assert(!binding.isParam()); - assert(name.type == binding.type); - assert(0 <= pos && pos < arity && names[pos] == name); - assert(binding.function.memberDeclaringClassOrNull() == newData.clazz); - assert(oldData.getters.length == newData.getters.length-1); - if (bindCache != null) { - LambdaForm form = bindCache[pos]; - if (form != null) { - assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>"; - return form; - } - } else { - bindCache = new LambdaForm[arity]; - } - assert(nameRefsAreLegal()); - int arity2 = arity-1; - Name[] names2 = names.clone(); - names2[pos] = binding; // we might move this in a moment - - // The newly created LF will run with a different BMH. - // Switch over any pre-existing BMH field references to the new BMH class. - int firstOldRef = -1; - for (int i = 0; i < names2.length; i++) { - Name n = names[i]; - if (n.function != null && - n.function.memberDeclaringClassOrNull() == oldData.clazz) { - MethodHandle oldGetter = n.function.resolvedHandle; - MethodHandle newGetter = null; - for (int j = 0; j < oldData.getters.length; j++) { - if (oldGetter == oldData.getters[j]) - newGetter = newData.getters[j]; - } - if (newGetter != null) { - if (firstOldRef < 0) firstOldRef = i; - Name n2 = new Name(newGetter, n.arguments); - names2[i] = n2; - } - } - } - - // Walk over the new list of names once, in forward order. - // Replace references to 'name' with 'binding'. - // Replace data structure references to the old BMH species with the new. - // This might cause a ripple effect, but it will settle in one pass. - assert(firstOldRef < 0 || firstOldRef > pos); - for (int i = pos+1; i < names2.length; i++) { - if (i <= arity2) continue; - names2[i] = names2[i].replaceNames(names, names2, pos, i); - } - - // (a0, a1, name=a2, a3, a4) => (a0, a1, a3, a4, binding) - int insPos = pos; - for (; insPos+1 < names2.length; insPos++) { - Name n = names2[insPos+1]; - if (n.isSiblingBindingBefore(binding)) { - names2[insPos] = n; - } else { - break; - } - } - names2[insPos] = binding; - - // Since we moved some stuff, maybe update the result reference: - int result2 = result; - if (result2 == pos) - result2 = insPos; - else if (result2 > pos && result2 <= insPos) - result2 -= 1; - - return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2); + public boolean equals(LambdaForm that) { + if (this.result != that.result) return false; + return Arrays.equals(this.names, that.names); + } + public int hashCode() { + return result + 31 * Arrays.hashCode(names); + } + LambdaFormEditor editor() { + return LambdaFormEditor.lambdaFormEditor(this); } boolean contains(Name name) { @@ -874,17 +887,17 @@ class LambdaForm { return false; } - LambdaForm addArguments(int pos, char... types) { - assert(pos <= arity); + LambdaForm addArguments(int pos, BasicType... types) { + // names array has MH in slot 0; skip it. + int argpos = pos + 1; + assert(argpos <= arity); int length = names.length; int inTypes = types.length; Name[] names2 = Arrays.copyOf(names, length + inTypes); int arity2 = arity + inTypes; int result2 = result; - if (result2 >= arity) + if (result2 >= argpos) result2 += inTypes; - // names array has MH in slot 0; skip it. - int argpos = pos + 1; // Note: The LF constructor will rename names2[argpos...]. // Make space for new arguments (shift temporaries). System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos); @@ -895,13 +908,10 @@ class LambdaForm { } LambdaForm addArguments(int pos, List> types) { - char[] basicTypes = new char[types.size()]; - for (int i = 0; i < basicTypes.length; i++) - basicTypes[i] = basicType(types.get(i)); - return addArguments(pos, basicTypes); + return addArguments(pos, basicTypes(types)); } - LambdaForm permuteArguments(int skip, int[] reorder, char[] types) { + LambdaForm permuteArguments(int skip, int[] reorder, BasicType[] types) { // Note: When inArg = reorder[outArg], outArg is fed by a copy of inArg. // The types are the types of the new (incoming) arguments. int length = names.length; @@ -960,7 +970,7 @@ class LambdaForm { return new LambdaForm(debugName, arity2, names2, result2); } - static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) { + static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) { int inTypes = types.length; int outArgs = reorder.length; for (int i = 0; i < outArgs; i++) { @@ -980,8 +990,9 @@ class LambdaForm { } NamedFunction(MemberName member, MethodHandle resolvedHandle) { this.member = member; - //resolvedHandle = eraseSubwordTypes(resolvedHandle); this.resolvedHandle = resolvedHandle; + // The following assert is almost always correct, but will fail for corner cases, such as PrivateInvokeTest. + //assert(!isInvokeBasic()); } NamedFunction(MethodType basicInvokerType) { assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType; @@ -992,6 +1003,13 @@ class LambdaForm { // necessary to pass BigArityTest this.member = Invokers.invokeBasicMethod(basicInvokerType); } + assert(isInvokeBasic()); + } + + private boolean isInvokeBasic() { + return member != null && + member.isMethodHandleInvoke() && + "invokeBasic".equals(member.getName()); } // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc. @@ -1044,10 +1062,10 @@ class LambdaForm { String sig = m.getName().substring("invoke_".length()); int arity = LambdaForm.signatureArity(sig); MethodType srcType = MethodType.genericMethodType(arity); - if (LambdaForm.signatureReturn(sig) == 'V') + if (LambdaForm.signatureReturn(sig) == V_TYPE) srcType = srcType.changeReturnType(void.class); MethodTypeForm typeForm = srcType.form(); - typeForm.namedFunctionInvoker = DirectMethodHandle.make(m); + typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m)); } } } @@ -1057,85 +1075,104 @@ class LambdaForm { /** void return type invokers. */ @Hidden static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 0); + assert(arityCheck(0, void.class, mh, a)); mh.invokeBasic(); return null; } @Hidden static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 1); + assert(arityCheck(1, void.class, mh, a)); mh.invokeBasic(a[0]); return null; } @Hidden static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 2); + assert(arityCheck(2, void.class, mh, a)); mh.invokeBasic(a[0], a[1]); return null; } @Hidden static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 3); + assert(arityCheck(3, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2]); return null; } @Hidden static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 4); + assert(arityCheck(4, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2], a[3]); return null; } @Hidden static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 5); + assert(arityCheck(5, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); return null; } /** Object return type invokers. */ @Hidden static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 0); + assert(arityCheck(0, mh, a)); return mh.invokeBasic(); } @Hidden static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 1); + assert(arityCheck(1, mh, a)); return mh.invokeBasic(a[0]); } @Hidden static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 2); + assert(arityCheck(2, mh, a)); return mh.invokeBasic(a[0], a[1]); } @Hidden static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 3); + assert(arityCheck(3, mh, a)); return mh.invokeBasic(a[0], a[1], a[2]); } @Hidden static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 4); + assert(arityCheck(4, mh, a)); return mh.invokeBasic(a[0], a[1], a[2], a[3]); } @Hidden static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 5); + assert(arityCheck(5, mh, a)); return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); } + private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) { + return arityCheck(arity, Object.class, mh, a); + } + private static boolean arityCheck(int arity, Class rtype, MethodHandle mh, Object[] a) { + assert(a.length == arity) + : Arrays.asList(a.length, arity); + assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype)) + : Arrays.asList(mh, rtype, arity); + MemberName member = mh.internalMemberName(); + if (member != null && member.getName().equals("invokeBasic") && member.isMethodHandleInvoke()) { + assert(arity > 0); + assert(a[0] instanceof MethodHandle); + MethodHandle mh2 = (MethodHandle) a[0]; + assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype)) + : Arrays.asList(member, mh2, rtype, arity); + } + return true; + } static final MethodType INVOKER_METHOD_TYPE = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); private static MethodHandle computeInvoker(MethodTypeForm typeForm) { - MethodHandle mh = typeForm.namedFunctionInvoker; + typeForm = typeForm.basicType().form(); // normalize to basic type + MethodHandle mh = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh != null) return mh; MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm); // this could take a while mh = DirectMethodHandle.make(invoker); - MethodHandle mh2 = typeForm.namedFunctionInvoker; + MethodHandle mh2 = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh2 != null) return mh2; // benign race if (!mh.type().equals(INVOKER_METHOD_TYPE)) - throw new InternalError(mh.debugString()); - return typeForm.namedFunctionInvoker = mh; + throw newInternalError(mh.debugString()); + return typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, mh); } @Hidden @@ -1193,11 +1230,6 @@ class LambdaForm { return true; } - String basicTypeSignature() { - //return LambdaForm.basicTypeSignature(resolvedHandle.type()); - return LambdaForm.basicTypeSignature(methodType()); - } - MethodType methodType() { if (resolvedHandle != null) return resolvedHandle.type(); @@ -1224,18 +1256,15 @@ class LambdaForm { return (member == null) ? null : member.getDeclaringClass(); } - char returnType() { + BasicType returnType() { return basicType(methodType().returnType()); } - char parameterType(int n) { + BasicType parameterType(int n) { return basicType(methodType().parameterType(n)); } int arity() { - //int siglen = member.getMethodType().parameterCount(); - //if (!member.isStatic()) siglen += 1; - //return siglen; return methodType().parameterCount(); } @@ -1243,74 +1272,109 @@ class LambdaForm { if (member == null) return String.valueOf(resolvedHandle); return member.getDeclaringClass().getSimpleName()+"."+member.getName(); } - } - void resolve() { - for (Name n : names) n.resolve(); - } + public boolean isIdentity() { + return this.equals(identity(returnType())); + } - public static char basicType(Class type) { - char c = Wrapper.basicTypeChar(type); - if ("ZBSC".indexOf(c) >= 0) c = 'I'; - assert("LIJFDV".indexOf(c) >= 0); - return c; - } - public static char[] basicTypes(List> types) { - char[] btypes = new char[types.size()]; - for (int i = 0; i < btypes.length; i++) { - btypes[i] = basicType(types.get(i)); + public boolean isConstantZero() { + return this.equals(constantZero(returnType())); + } + + public MethodHandleImpl.Intrinsic intrinsicName() { + return resolvedHandle == null ? MethodHandleImpl.Intrinsic.NONE + : resolvedHandle.intrinsicName(); } - return btypes; } + public static String basicTypeSignature(MethodType type) { char[] sig = new char[type.parameterCount() + 2]; int sigp = 0; for (Class pt : type.parameterList()) { - sig[sigp++] = basicType(pt); + sig[sigp++] = basicTypeChar(pt); } sig[sigp++] = '_'; - sig[sigp++] = basicType(type.returnType()); + sig[sigp++] = basicTypeChar(type.returnType()); assert(sigp == sig.length); return String.valueOf(sig); } + public static String shortenSignature(String signature) { + // Hack to make signatures more readable when they show up in method names. + final int NO_CHAR = -1, MIN_RUN = 3; + int c0, c1 = NO_CHAR, c1reps = 0; + StringBuilder buf = null; + int len = signature.length(); + if (len < MIN_RUN) return signature; + for (int i = 0; i <= len; i++) { + // shift in the next char: + c0 = c1; c1 = (i == len ? NO_CHAR : signature.charAt(i)); + if (c1 == c0) { ++c1reps; continue; } + // shift in the next count: + int c0reps = c1reps; c1reps = 1; + // end of a character run + if (c0reps < MIN_RUN) { + if (buf != null) { + while (--c0reps >= 0) + buf.append((char)c0); + } + continue; + } + // found three or more in a row + if (buf == null) + buf = new StringBuilder().append(signature, 0, i - c0reps); + buf.append((char)c0).append(c0reps); + } + return (buf == null) ? signature : buf.toString(); + } static final class Name { - final char type; + final BasicType type; private short index; final NamedFunction function; + final Object constraint; // additional type information, if not null @Stable final Object[] arguments; - private Name(int index, char type, NamedFunction function, Object[] arguments) { + private Name(int index, BasicType type, NamedFunction function, Object[] arguments) { this.index = (short)index; this.type = type; this.function = function; this.arguments = arguments; + this.constraint = null; assert(this.index == index); } + private Name(Name that, Object constraint) { + this.index = that.index; + this.type = that.type; + this.function = that.function; + this.arguments = that.arguments; + this.constraint = constraint; + assert(constraint == null || isParam()); // only params have constraints + assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class); + } Name(MethodHandle function, Object... arguments) { this(new NamedFunction(function), arguments); } Name(MethodType functionType, Object... arguments) { this(new NamedFunction(functionType), arguments); - assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == 'L'); + assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == L_TYPE); } Name(MemberName function, Object... arguments) { this(new NamedFunction(function), arguments); } Name(NamedFunction function, Object... arguments) { - this(-1, function.returnType(), function, arguments = arguments.clone()); + this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class)); assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString(); for (int i = 0; i < arguments.length; i++) assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString(); } - Name(int index, char type) { + /** Create a raw parameter of the given type, with an expected index. */ + Name(int index, BasicType type) { this(index, type, null, null); } - Name(char type) { - this(-1, type); - } + /** Create a raw parameter of the given type. */ + Name(BasicType type) { this(-1, type); } - char type() { return type; } + BasicType type() { return type; } int index() { return index; } boolean initIndex(int i) { if (index != i) { @@ -1319,7 +1383,9 @@ class LambdaForm { } return true; } - + char typeChar() { + return type.btChar; + } void resolve() { if (function != null) @@ -1332,7 +1398,11 @@ class LambdaForm { } Name cloneWithIndex(int i) { Object[] newArguments = (arguments == null) ? null : arguments.clone(); - return new Name(i, type, function, newArguments); + return new Name(i, type, function, newArguments).withConstraint(constraint); + } + Name withConstraint(Object constraint) { + if (constraint == this.constraint) return this; + return new Name(this, constraint); } Name replaceName(Name oldName, Name newName) { // FIXME: use replaceNames uniformly if (oldName == newName) return this; @@ -1352,7 +1422,11 @@ class LambdaForm { if (!replaced) return this; return new Name(function, arguments); } + /** In the arguments of this Name, replace oldNames[i] pairwise by newNames[i]. + * Limit such replacements to {@code start<=i= end) return this; @SuppressWarnings("LocalVariableHidesMemberVariable") Object[] arguments = this.arguments; boolean replaced = false; @@ -1397,18 +1471,26 @@ class LambdaForm { return function == null; } boolean isConstantZero() { - return !isParam() && arguments.length == 0 && function.equals(constantZero(0, type).function); + return !isParam() && arguments.length == 0 && function.isConstantZero(); } public String toString() { - return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+type; + return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+typeChar(); } public String debugString() { - String s = toString(); + String s = paramString(); return (function == null) ? s : s + "=" + exprString(); } + public String paramString() { + String s = toString(); + Object c = constraint; + if (c == null) + return s; + if (c instanceof Class) c = ((Class)c).getSimpleName(); + return s + "/" + c; + } public String exprString() { - if (function == null) return "null"; + if (function == null) return toString(); StringBuilder buf = new StringBuilder(function.toString()); buf.append("("); String cma = ""; @@ -1423,48 +1505,20 @@ class LambdaForm { return buf.toString(); } - private static boolean typesMatch(char parameterType, Object object) { + static boolean typesMatch(BasicType parameterType, Object object) { if (object instanceof Name) { return ((Name)object).type == parameterType; } switch (parameterType) { - case 'I': return object instanceof Integer; - case 'J': return object instanceof Long; - case 'F': return object instanceof Float; - case 'D': return object instanceof Double; + case I_TYPE: return object instanceof Integer; + case J_TYPE: return object instanceof Long; + case F_TYPE: return object instanceof Float; + case D_TYPE: return object instanceof Double; } - assert(parameterType == 'L'); + assert(parameterType == L_TYPE); return true; } - /** - * Does this Name precede the given binding node in some canonical order? - * This predicate is used to order data bindings (via insertion sort) - * with some stability. - */ - boolean isSiblingBindingBefore(Name binding) { - assert(!binding.isParam()); - if (isParam()) return true; - if (function.equals(binding.function) && - arguments.length == binding.arguments.length) { - boolean sawInt = false; - for (int i = 0; i < arguments.length; i++) { - Object a1 = arguments[i]; - Object a2 = binding.arguments[i]; - if (!a1.equals(a2)) { - if (a1 instanceof Integer && a2 instanceof Integer) { - if (sawInt) continue; - sawInt = true; - if ((int)a1 < (int)a2) continue; // still might be true - } - return false; - } - } - return sawInt; - } - return false; - } - /** Return the index of the last occurrence of n in the argument array. * Return -1 if the name is not used. */ @@ -1510,7 +1564,7 @@ class LambdaForm { @Override public int hashCode() { if (isParam()) - return index | (type << 8); + return index | (type.ordinal() << 8); return function.hashCode() ^ Arrays.hashCode(arguments); } } @@ -1545,14 +1599,17 @@ class LambdaForm { } static Name argument(int which, char type) { - int tn = ALL_TYPES.indexOf(type); - if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT) + return argument(which, basicType(type)); + } + static Name argument(int which, BasicType type) { + if (which >= INTERNED_ARGUMENT_LIMIT) return new Name(which, type); - return INTERNED_ARGUMENTS[tn][which]; + return INTERNED_ARGUMENTS[type.ordinal()][which]; } static Name internArgument(Name n) { assert(n.isParam()) : "not param: " + n; assert(n.index < INTERNED_ARGUMENT_LIMIT); + if (n.constraint != null) return n; return argument(n.index, n.type); } static Name[] arguments(int extra, String types) { @@ -1590,57 +1647,119 @@ class LambdaForm { names[i] = argument(i, basicType(types.parameterType(i))); return names; } - static final String ALL_TYPES = "LIJFD"; // omit V, not an argument type static final int INTERNED_ARGUMENT_LIMIT = 10; private static final Name[][] INTERNED_ARGUMENTS - = new Name[ALL_TYPES.length()][INTERNED_ARGUMENT_LIMIT]; + = new Name[ARG_TYPE_LIMIT][INTERNED_ARGUMENT_LIMIT]; static { - for (int tn = 0; tn < ALL_TYPES.length(); tn++) { - for (int i = 0; i < INTERNED_ARGUMENTS[tn].length; i++) { - char type = ALL_TYPES.charAt(tn); - INTERNED_ARGUMENTS[tn][i] = new Name(i, type); + for (BasicType type : BasicType.ARG_TYPES) { + int ord = type.ordinal(); + for (int i = 0; i < INTERNED_ARGUMENTS[ord].length; i++) { + INTERNED_ARGUMENTS[ord][i] = new Name(i, type); } } } private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); - static Name constantZero(int which, char type) { - return CONSTANT_ZERO[ALL_TYPES.indexOf(type)].newIndex(which); - } - private static final Name[] CONSTANT_ZERO - = new Name[ALL_TYPES.length()]; - static { - for (int tn = 0; tn < ALL_TYPES.length(); tn++) { - char bt = ALL_TYPES.charAt(tn); - Wrapper wrap = Wrapper.forBasicType(bt); - MemberName zmem = new MemberName(LambdaForm.class, "zero"+bt, MethodType.methodType(wrap.primitiveType()), REF_invokeStatic); + static LambdaForm identityForm(BasicType type) { + return LF_identityForm[type.ordinal()]; + } + static LambdaForm zeroForm(BasicType type) { + return LF_zeroForm[type.ordinal()]; + } + static NamedFunction identity(BasicType type) { + return NF_identity[type.ordinal()]; + } + static NamedFunction constantZero(BasicType type) { + return NF_zero[type.ordinal()]; + } + private static final LambdaForm[] LF_identityForm = new LambdaForm[TYPE_LIMIT]; + private static final LambdaForm[] LF_zeroForm = new LambdaForm[TYPE_LIMIT]; + private static final NamedFunction[] NF_identity = new NamedFunction[TYPE_LIMIT]; + private static final NamedFunction[] NF_zero = new NamedFunction[TYPE_LIMIT]; + private static void createIdentityForms() { + for (BasicType type : BasicType.ALL_TYPES) { + int ord = type.ordinal(); + char btChar = type.basicTypeChar(); + boolean isVoid = (type == V_TYPE); + Class btClass = type.btClass; + MethodType zeType = MethodType.methodType(btClass); + MethodType idType = isVoid ? zeType : zeType.appendParameterTypes(btClass); + + // Look up some symbolic names. It might not be necessary to have these, + // but if we need to emit direct references to bytecodes, it helps. + // Zero is built from a call to an identity function with a constant zero input. + MemberName idMem = new MemberName(LambdaForm.class, "identity_"+btChar, idType, REF_invokeStatic); + MemberName zeMem = new MemberName(LambdaForm.class, "zero_"+btChar, zeType, REF_invokeStatic); try { - zmem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zmem, null, NoSuchMethodException.class); + zeMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zeMem, null, NoSuchMethodException.class); + idMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, idMem, null, NoSuchMethodException.class); } catch (IllegalAccessException|NoSuchMethodException ex) { throw newInternalError(ex); } - NamedFunction zcon = new NamedFunction(zmem); - Name n = new Name(zcon).newIndex(0); - assert(n.type == ALL_TYPES.charAt(tn)); - CONSTANT_ZERO[tn] = n; - assert(n.isConstantZero()); + + NamedFunction idFun = new NamedFunction(idMem); + LambdaForm idForm; + if (isVoid) { + Name[] idNames = new Name[] { argument(0, L_TYPE) }; + idForm = new LambdaForm(idMem.getName(), 1, idNames, VOID_RESULT); + } else { + Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) }; + idForm = new LambdaForm(idMem.getName(), 2, idNames, 1); + } + LF_identityForm[ord] = idForm; + NF_identity[ord] = idFun; + + NamedFunction zeFun = new NamedFunction(zeMem); + LambdaForm zeForm; + if (isVoid) { + zeForm = idForm; + } else { + Object zeValue = Wrapper.forBasicType(btChar).zero(); + Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) }; + zeForm = new LambdaForm(zeMem.getName(), 1, zeNames, 1); + } + LF_zeroForm[ord] = zeForm; + NF_zero[ord] = zeFun; + + assert(idFun.isIdentity()); + assert(zeFun.isConstantZero()); + assert(new Name(zeFun).isConstantZero()); } - } - // Avoid appealing to ValueConversions at bootstrap time: - private static int zeroI() { return 0; } - private static long zeroJ() { return 0; } - private static float zeroF() { return 0; } - private static double zeroD() { return 0; } - private static Object zeroL() { return null; } + // Do this in a separate pass, so that SimpleMethodHandle.make can see the tables. + for (BasicType type : BasicType.ALL_TYPES) { + int ord = type.ordinal(); + NamedFunction idFun = NF_identity[ord]; + LambdaForm idForm = LF_identityForm[ord]; + MemberName idMem = idFun.member; + idFun.resolvedHandle = SimpleMethodHandle.make(idMem.getInvocationType(), idForm); - // Put this last, so that previous static inits can run before. - static { - if (USE_PREDEFINED_INTERPRET_METHODS) - PREPARED_FORMS.putAll(computeInitialPreparedForms()); + NamedFunction zeFun = NF_zero[ord]; + LambdaForm zeForm = LF_zeroForm[ord]; + MemberName zeMem = zeFun.member; + zeFun.resolvedHandle = SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm); + + assert(idFun.isIdentity()); + assert(zeFun.isConstantZero()); + assert(new Name(zeFun).isConstantZero()); + } } + // Avoid appealing to ValueConversions at bootstrap time: + private static int identity_I(int x) { return x; } + private static long identity_J(long x) { return x; } + private static float identity_F(float x) { return x; } + private static double identity_D(double x) { return x; } + private static Object identity_L(Object x) { return x; } + private static void identity_V() { return; } // same as zeroV, but that's OK + private static int zero_I() { return 0; } + private static long zero_J() { return 0; } + private static float zero_F() { return 0; } + private static double zero_D() { return 0; } + private static Object zero_L() { return null; } + private static void zero_V() { return; } + /** * Internal marker for byte-compiled LambdaForms. */ @@ -1659,38 +1778,21 @@ class LambdaForm { @interface Hidden { } + private static final HashMap DEBUG_NAME_COUNTERS; + static { + if (debugEnabled()) + DEBUG_NAME_COUNTERS = new HashMap<>(); + else + DEBUG_NAME_COUNTERS = null; + } -/* - // Smoke-test for the invokers used in this file. - static void testMethodHandleLinkers() throws Throwable { - MemberName.Factory lookup = MemberName.getFactory(); - MemberName asList_MN = new MemberName(Arrays.class, "asList", - MethodType.methodType(List.class, Object[].class), - REF_invokeStatic); - //MethodHandleNatives.resolve(asList_MN, null); - asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class); - System.out.println("about to call "+asList_MN); - Object[] abc = { "a", "bc" }; - List lst = (List) MethodHandle.linkToStatic(abc, asList_MN); - System.out.println("lst="+lst); - MemberName toString_MN = new MemberName(Object.class.getMethod("toString")); - String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN); - toString_MN = new MemberName(Object.class.getMethod("toString"), true); - String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN); - System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString())); - MemberName toArray_MN = new MemberName(List.class.getMethod("toArray")); - Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN); - System.out.println("toArray="+Arrays.toString(arr)); - } - static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } } - // Requires these definitions in MethodHandle: - static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable; - static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable; - static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable; - static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable; - */ - - static { NamedFunction.initializeInvokers(); } + // Put this last, so that previous static inits can run before. + static { + createIdentityForms(); + if (USE_PREDEFINED_INTERPRET_METHODS) + computeInitialPreparedForms(); + NamedFunction.initializeInvokers(); + } // The following hack is necessary in order to suppress TRACE_INTERPRETER // during execution of the static initializes of this class. diff --git a/src/share/classes/java/lang/invoke/LambdaFormBuffer.java b/src/share/classes/java/lang/invoke/LambdaFormBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..872a2a5992162829a13d3556b12aa2778c844357 --- /dev/null +++ b/src/share/classes/java/lang/invoke/LambdaFormBuffer.java @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.ArrayList; +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; + +/** Working storage for an LF that is being transformed. + * Similarly to a StringBuffer, the editing can take place in multiple steps. + */ +final class LambdaFormBuffer { + private int arity, length; + private Name[] names; + private Name[] originalNames; // snapshot of pre-transaction names + private byte flags; + private int firstChange; + private Name resultName; + private String debugName; + private ArrayList dups; + + private static final int F_TRANS = 0x10, F_OWNED = 0x03; + + LambdaFormBuffer(LambdaForm lf) { + this(lf.arity, lf.names, lf.result); + debugName = lf.debugName; + assert(lf.nameRefsAreLegal()); + } + + private LambdaFormBuffer(int arity, Name[] names, int result) { + this.arity = arity; + setNames(names); + if (result == LAST_RESULT) result = length - 1; + if (result >= 0 && names[result].type != V_TYPE) + resultName = names[result]; + } + + private LambdaForm lambdaForm() { + assert(!inTrans()); // need endEdit call to tidy things up + return new LambdaForm(debugName, arity, nameArray(), resultIndex()); + } + + Name name(int i) { + assert(i < length); + return names[i]; + } + + Name[] nameArray() { + return Arrays.copyOf(names, length); + } + + int resultIndex() { + if (resultName == null) return VOID_RESULT; + int index = indexOf(resultName, names); + assert(index >= 0); + return index; + } + + void setNames(Name[] names2) { + names = originalNames = names2; // keep a record of where everything was to start with + length = names2.length; + flags = 0; + } + + private boolean verifyArity() { + for (int i = 0; i < arity && i < firstChange; i++) { + assert(names[i].isParam()) : "#" + i + "=" + names[i]; + } + for (int i = arity; i < length; i++) { + assert(!names[i].isParam()) : "#" + i + "=" + names[i]; + } + for (int i = length; i < names.length; i++) { + assert(names[i] == null) : "#" + i + "=" + names[i]; + } + // check resultName also + if (resultName != null) { + int resultIndex = indexOf(resultName, names); + assert(resultIndex >= 0) : "not found: " + resultName.exprString() + Arrays.asList(names); + assert(names[resultIndex] == resultName); + } + return true; + } + + private boolean verifyFirstChange() { + assert(inTrans()); + for (int i = 0; i < length; i++) { + if (names[i] != originalNames[i]) { + assert(firstChange == i) : Arrays.asList(firstChange, i, originalNames[i].exprString(), Arrays.asList(names)); + return true; + } + } + assert(firstChange == length) : Arrays.asList(firstChange, Arrays.asList(names)); + return true; + } + + private static int indexOf(NamedFunction fn, NamedFunction[] fns) { + for (int i = 0; i < fns.length; i++) { + if (fns[i] == fn) return i; + } + return -1; + } + + private static int indexOf(Name n, Name[] ns) { + for (int i = 0; i < ns.length; i++) { + if (ns[i] == n) return i; + } + return -1; + } + + boolean inTrans() { + return (flags & F_TRANS) != 0; + } + + int ownedCount() { + return flags & F_OWNED; + } + + void growNames(int insertPos, int growLength) { + int oldLength = length; + int newLength = oldLength + growLength; + int oc = ownedCount(); + if (oc == 0 || newLength > names.length) { + names = Arrays.copyOf(names, (names.length + growLength) * 5 / 4); + if (oc == 0) { + flags++; + oc++; + assert(ownedCount() == oc); + } + } + if (originalNames != null && originalNames.length < names.length) { + originalNames = Arrays.copyOf(originalNames, names.length); + if (oc == 1) { + flags++; + oc++; + assert(ownedCount() == oc); + } + } + if (growLength == 0) return; + int insertEnd = insertPos + growLength; + int tailLength = oldLength - insertPos; + System.arraycopy(names, insertPos, names, insertEnd, tailLength); + Arrays.fill(names, insertPos, insertEnd, null); + if (originalNames != null) { + System.arraycopy(originalNames, insertPos, originalNames, insertEnd, tailLength); + Arrays.fill(originalNames, insertPos, insertEnd, null); + } + length = newLength; + if (firstChange >= insertPos) { + firstChange += growLength; + } + } + + int lastIndexOf(Name n) { + int result = -1; + for (int i = 0; i < length; i++) { + if (names[i] == n) result = i; + } + return result; + } + + /** We have just overwritten the name at pos1 with the name at pos2. + * This means that there are two copies of the name, which we will have to fix later. + */ + private void noteDuplicate(int pos1, int pos2) { + Name n = names[pos1]; + assert(n == names[pos2]); + assert(originalNames[pos1] != null); // something was replaced at pos1 + assert(originalNames[pos2] == null || originalNames[pos2] == n); + if (dups == null) { + dups = new ArrayList<>(); + } + dups.add(n); + } + + /** Replace duplicate names by nulls, and remove all nulls. */ + private void clearDuplicatesAndNulls() { + if (dups != null) { + // Remove duplicates. + assert(ownedCount() >= 1); + for (Name dup : dups) { + for (int i = firstChange; i < length; i++) { + if (names[i] == dup && originalNames[i] != dup) { + names[i] = null; + assert(Arrays.asList(names).contains(dup)); + break; // kill only one dup + } + } + } + dups.clear(); + } + // Now that we are done with originalNames, remove "killed" names. + int oldLength = length; + for (int i = firstChange; i < length; i++) { + if (names[i] == null) { + System.arraycopy(names, i + 1, names, i, (--length - i)); + --i; // restart loop at this position + } + } + if (length < oldLength) { + Arrays.fill(names, length, oldLength, null); + } + assert(!Arrays.asList(names).subList(0, length).contains(null)); + } + + /** Create a private, writable copy of names. + * Preserve the original copy, for reference. + */ + void startEdit() { + assert(verifyArity()); + int oc = ownedCount(); + assert(!inTrans()); // no nested transactions + flags |= F_TRANS; + Name[] oldNames = names; + Name[] ownBuffer = (oc == 2 ? originalNames : null); + assert(ownBuffer != oldNames); + if (ownBuffer != null && ownBuffer.length >= length) { + names = copyNamesInto(ownBuffer); + } else { + // make a new buffer to hold the names + final int SLOP = 2; + names = Arrays.copyOf(oldNames, Math.max(length + SLOP, oldNames.length)); + if (oc < 2) ++flags; + assert(ownedCount() == oc + 1); + } + originalNames = oldNames; + assert(originalNames != names); + firstChange = length; + assert(inTrans()); + } + + private void changeName(int i, Name name) { + assert(inTrans()); + assert(i < length); + Name oldName = names[i]; + assert(oldName == originalNames[i]); // no multiple changes + assert(verifyFirstChange()); + if (ownedCount() == 0) + growNames(0, 0); + names[i] = name; + if (firstChange > i) { + firstChange = i; + } + if (resultName != null && resultName == oldName) { + resultName = name; + } + } + + /** Change the result name. Null means a void result. */ + void setResult(Name name) { + assert(name == null || lastIndexOf(name) >= 0); + resultName = name; + } + + /** Finish a transaction. */ + LambdaForm endEdit() { + assert(verifyFirstChange()); + // Assuming names have been changed pairwise from originalNames[i] to names[i], + // update arguments to ensure referential integrity. + for (int i = Math.max(firstChange, arity); i < length; i++) { + Name name = names[i]; + if (name == null) continue; // space for removed duplicate + Name newName = name.replaceNames(originalNames, names, firstChange, i); + if (newName != name) { + names[i] = newName; + if (resultName == name) { + resultName = newName; + } + } + } + assert(inTrans()); + flags &= ~F_TRANS; + clearDuplicatesAndNulls(); + originalNames = null; + // If any parameters have been changed, then reorder them as needed. + // This is a "sheep-and-goats" stable sort, pushing all non-parameters + // to the right of all parameters. + if (firstChange < arity) { + Name[] exprs = new Name[arity - firstChange]; + int argp = firstChange, exprp = 0; + for (int i = firstChange; i < arity; i++) { + Name name = names[i]; + if (name.isParam()) { + names[argp++] = name; + } else { + exprs[exprp++] = name; + } + } + assert(exprp == (arity - argp)); + // copy the exprs just after the last remaining param + System.arraycopy(exprs, 0, names, argp, exprp); + // adjust arity + arity -= exprp; + } + assert(verifyArity()); + return lambdaForm(); + } + + private Name[] copyNamesInto(Name[] buffer) { + System.arraycopy(names, 0, buffer, 0, length); + Arrays.fill(buffer, length, buffer.length, null); + return buffer; + } + + /** Replace any Name whose function is in oldFns with a copy + * whose function is in the corresponding position in newFns. + * Only do this if the arguments are exactly equal to the given. + */ + LambdaFormBuffer replaceFunctions(NamedFunction[] oldFns, NamedFunction[] newFns, + Object... forArguments) { + assert(inTrans()); + if (oldFns.length == 0) return this; + for (int i = arity; i < length; i++) { + Name n = names[i]; + int nfi = indexOf(n.function, oldFns); + if (nfi >= 0 && Arrays.equals(n.arguments, forArguments)) { + changeName(i, new Name(newFns[nfi], n.arguments)); + } + } + return this; + } + + private void replaceName(int pos, Name binding) { + assert(inTrans()); + assert(verifyArity()); + assert(pos < arity); + Name param = names[pos]; + assert(param.isParam()); + assert(param.type == binding.type); + changeName(pos, binding); + } + + /** Replace a parameter by a fresh parameter. */ + LambdaFormBuffer renameParameter(int pos, Name newParam) { + assert(newParam.isParam()); + replaceName(pos, newParam); + return this; + } + + /** Replace a parameter by a fresh expression. */ + LambdaFormBuffer replaceParameterByNewExpression(int pos, Name binding) { + assert(!binding.isParam()); + assert(lastIndexOf(binding) < 0); // else use replaceParameterByCopy + replaceName(pos, binding); + return this; + } + + /** Replace a parameter by another parameter or expression already in the form. */ + LambdaFormBuffer replaceParameterByCopy(int pos, int valuePos) { + assert(pos != valuePos); + replaceName(pos, names[valuePos]); + noteDuplicate(pos, valuePos); // temporarily, will occur twice in the names array + return this; + } + + private void insertName(int pos, Name expr, boolean isParameter) { + assert(inTrans()); + assert(verifyArity()); + assert(isParameter ? pos <= arity : pos >= arity); + growNames(pos, 1); + if (isParameter) arity += 1; + changeName(pos, expr); + } + + /** Insert a fresh expression. */ + LambdaFormBuffer insertExpression(int pos, Name expr) { + assert(!expr.isParam()); + insertName(pos, expr, false); + return this; + } + + /** Insert a fresh parameter. */ + LambdaFormBuffer insertParameter(int pos, Name param) { + assert(param.isParam()); + insertName(pos, param, true); + return this; + } +} diff --git a/src/share/classes/java/lang/invoke/LambdaFormEditor.java b/src/share/classes/java/lang/invoke/LambdaFormEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..1c29d73b4ccb894e59f240840b20be810d591a19 --- /dev/null +++ b/src/share/classes/java/lang/invoke/LambdaFormEditor.java @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; +import static java.lang.invoke.MethodHandleImpl.Intrinsic; +import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; + +import sun.invoke.util.Wrapper; + +/** Transforms on LFs. + * A lambda-form editor can derive new LFs from its base LF. + * The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes. + * To support this caching, a LF has an optional pointer to its editor. + */ +class LambdaFormEditor { + final LambdaForm lambdaForm; + + private LambdaFormEditor(LambdaForm lambdaForm) { + this.lambdaForm = lambdaForm; + } + + // Factory method. + static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) { + // TO DO: Consider placing intern logic here, to cut down on duplication. + // lambdaForm = findPreexistingEquivalent(lambdaForm) + return new LambdaFormEditor(lambdaForm); + } + + /** A description of a cached transform, possibly associated with the result of the transform. + * The logical content is a sequence of byte values, starting with a Kind.ordinal value. + * The sequence is unterminated, ending with an indefinite number of zero bytes. + * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long. + */ + private static final class Transform { + final long packedBytes; + final byte[] fullBytes; + final LambdaForm result; // result of transform, or null, if there is none available + + private enum Kind { + NO_KIND, // necessary because ordinal must be greater than zero + BIND_ARG, ADD_ARG, DUP_ARG, + SPREAD_ARGS, + FILTER_ARG, FILTER_RETURN, FILTER_RETURN_TO_ZERO, + COLLECT_ARGS, COLLECT_ARGS_TO_VOID, COLLECT_ARGS_TO_ARRAY, + FOLD_ARGS, FOLD_ARGS_TO_VOID, + PERMUTE_ARGS + //maybe add more for guard with test, catch exception, pointwise type conversions + } + + private static final boolean STRESS_TEST = false; // turn on to disable most packing + private static final int + PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4), + PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1, + PACKED_BYTE_MAX_LENGTH = (STRESS_TEST ? 3 : 64 / PACKED_BYTE_SIZE); + + private static long packedBytes(byte[] bytes) { + if (bytes.length > PACKED_BYTE_MAX_LENGTH) return 0; + long pb = 0; + int bitset = 0; + for (int i = 0; i < bytes.length; i++) { + int b = bytes[i] & 0xFF; + bitset |= b; + pb |= (long)b << (i * PACKED_BYTE_SIZE); + } + if (!inRange(bitset)) + return 0; + return pb; + } + private static long packedBytes(int b0, int b1) { + assert(inRange(b0 | b1)); + return ( (b0 << 0*PACKED_BYTE_SIZE) + | (b1 << 1*PACKED_BYTE_SIZE)); + } + private static long packedBytes(int b0, int b1, int b2) { + assert(inRange(b0 | b1 | b2)); + return ( (b0 << 0*PACKED_BYTE_SIZE) + | (b1 << 1*PACKED_BYTE_SIZE) + | (b2 << 2*PACKED_BYTE_SIZE)); + } + private static long packedBytes(int b0, int b1, int b2, int b3) { + assert(inRange(b0 | b1 | b2 | b3)); + return ( (b0 << 0*PACKED_BYTE_SIZE) + | (b1 << 1*PACKED_BYTE_SIZE) + | (b2 << 2*PACKED_BYTE_SIZE) + | (b3 << 3*PACKED_BYTE_SIZE)); + } + private static boolean inRange(int bitset) { + assert((bitset & 0xFF) == bitset); // incoming values must fit in *unsigned* byte + return ((bitset & ~PACKED_BYTE_MASK) == 0); + } + private static byte[] fullBytes(int... byteValues) { + byte[] bytes = new byte[byteValues.length]; + int i = 0; + for (int bv : byteValues) { + bytes[i++] = bval(bv); + } + assert(packedBytes(bytes) == 0); + return bytes; + } + + private byte byteAt(int i) { + long pb = packedBytes; + if (pb == 0) { + if (i >= fullBytes.length) return 0; + return fullBytes[i]; + } + assert(fullBytes == null); + if (i > PACKED_BYTE_MAX_LENGTH) return 0; + int pos = (i * PACKED_BYTE_SIZE); + return (byte)((pb >>> pos) & PACKED_BYTE_MASK); + } + + Kind kind() { return Kind.values()[byteAt(0)]; } + + private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) { + this.packedBytes = packedBytes; + this.fullBytes = fullBytes; + this.result = result; + } + private Transform(long packedBytes) { + this(packedBytes, null, null); + assert(packedBytes != 0); + } + private Transform(byte[] fullBytes) { + this(0, fullBytes, null); + } + + private static byte bval(int b) { + assert((b & 0xFF) == b); // incoming value must fit in *unsigned* byte + return (byte)b; + } + private static byte bval(Kind k) { + return bval(k.ordinal()); + } + static Transform of(Kind k, int b1) { + byte b0 = bval(k); + if (inRange(b0 | b1)) + return new Transform(packedBytes(b0, b1)); + else + return new Transform(fullBytes(b0, b1)); + } + static Transform of(Kind k, int b1, int b2) { + byte b0 = (byte) k.ordinal(); + if (inRange(b0 | b1 | b2)) + return new Transform(packedBytes(b0, b1, b2)); + else + return new Transform(fullBytes(b0, b1, b2)); + } + static Transform of(Kind k, int b1, int b2, int b3) { + byte b0 = (byte) k.ordinal(); + if (inRange(b0 | b1 | b2 | b3)) + return new Transform(packedBytes(b0, b1, b2, b3)); + else + return new Transform(fullBytes(b0, b1, b2, b3)); + } + private static final byte[] NO_BYTES = {}; + static Transform of(Kind k, int... b123) { + return ofBothArrays(k, b123, NO_BYTES); + } + static Transform of(Kind k, int b1, byte[] b234) { + return ofBothArrays(k, new int[]{ b1 }, b234); + } + static Transform of(Kind k, int b1, int b2, byte[] b345) { + return ofBothArrays(k, new int[]{ b1, b2 }, b345); + } + private static Transform ofBothArrays(Kind k, int[] b123, byte[] b456) { + byte[] fullBytes = new byte[1 + b123.length + b456.length]; + int i = 0; + fullBytes[i++] = bval(k); + for (int bv : b123) { + fullBytes[i++] = bval(bv); + } + for (byte bv : b456) { + fullBytes[i++] = bv; + } + long packedBytes = packedBytes(fullBytes); + if (packedBytes != 0) + return new Transform(packedBytes); + else + return new Transform(fullBytes); + } + + Transform withResult(LambdaForm result) { + return new Transform(this.packedBytes, this.fullBytes, result); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Transform && equals((Transform)obj); + } + public boolean equals(Transform that) { + return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes); + } + @Override + public int hashCode() { + if (packedBytes != 0) { + assert(fullBytes == null); + return Long.hashCode(packedBytes); + } + return Arrays.hashCode(fullBytes); + } + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + long bits = packedBytes; + if (bits != 0) { + buf.append("("); + while (bits != 0) { + buf.append(bits & PACKED_BYTE_MASK); + bits >>>= PACKED_BYTE_SIZE; + if (bits != 0) buf.append(","); + } + buf.append(")"); + } + if (fullBytes != null) { + buf.append("unpacked"); + buf.append(Arrays.toString(fullBytes)); + } + if (result != null) { + buf.append(" result="); + buf.append(result); + } + return buf.toString(); + } + } + + /** Find a previously cached transform equivalent to the given one, and return its result. */ + private LambdaForm getInCache(Transform key) { + assert(key.result == null); + // The transformCache is one of null, Transform, Transform[], or ConcurrentHashMap. + Object c = lambdaForm.transformCache; + Transform k = null; + if (c instanceof ConcurrentHashMap) { + @SuppressWarnings("unchecked") + ConcurrentHashMap m = (ConcurrentHashMap) c; + k = m.get(key); + } else if (c == null) { + return null; + } else if (c instanceof Transform) { + // one-element cache avoids overhead of an array + Transform t = (Transform)c; + if (t.equals(key)) k = t; + } else { + Transform[] ta = (Transform[])c; + for (int i = 0; i < ta.length; i++) { + Transform t = ta[i]; + if (t == null) break; + if (t.equals(key)) { k = t; break; } + } + } + assert(k == null || key.equals(k)); + return k == null ? null : k.result; + } + + /** Arbitrary but reasonable limits on Transform[] size for cache. */ + private static final int MIN_CACHE_ARRAY_SIZE = 4, MAX_CACHE_ARRAY_SIZE = 16; + + /** Cache a transform with its result, and return that result. + * But if an equivalent transform has already been cached, return its result instead. + */ + private LambdaForm putInCache(Transform key, LambdaForm form) { + key = key.withResult(form); + for (int pass = 0; ; pass++) { + Object c = lambdaForm.transformCache; + if (c instanceof ConcurrentHashMap) { + @SuppressWarnings("unchecked") + ConcurrentHashMap m = (ConcurrentHashMap) c; + Transform k = m.putIfAbsent(key, key); + return k != null ? k.result : form; + } + assert(pass == 0); + synchronized (lambdaForm) { + c = lambdaForm.transformCache; + if (c instanceof ConcurrentHashMap) + continue; + if (c == null) { + lambdaForm.transformCache = key; + return form; + } + Transform[] ta; + if (c instanceof Transform) { + Transform k = (Transform)c; + if (k.equals(key)) { + return k.result; + } + // expand one-element cache to small array + ta = new Transform[MIN_CACHE_ARRAY_SIZE]; + ta[0] = k; + lambdaForm.transformCache = c = ta; + } else { + // it is already expanded + ta = (Transform[])c; + } + int len = ta.length; + int i; + for (i = 0; i < len; i++) { + Transform k = ta[i]; + if (k == null) { + break; + } + if (k.equals(key)) { + return k.result; + } + } + if (i < len) { + // just fall through to cache update + } else if (len < MAX_CACHE_ARRAY_SIZE) { + len = Math.min(len * 2, MAX_CACHE_ARRAY_SIZE); + ta = Arrays.copyOf(ta, len); + lambdaForm.transformCache = ta; + } else { + ConcurrentHashMap m = new ConcurrentHashMap<>(MAX_CACHE_ARRAY_SIZE * 2); + for (Transform k : ta) { + m.put(k, k); + } + lambdaForm.transformCache = m; + // The second iteration will update for this query, concurrently. + continue; + } + ta[i] = key; + return form; + } + } + } + + private LambdaFormBuffer buffer() { + return new LambdaFormBuffer(lambdaForm); + } + + /// Editing methods for method handles. These need to have fast paths. + + private BoundMethodHandle.SpeciesData oldSpeciesData() { + return BoundMethodHandle.speciesData(lambdaForm); + } + private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) { + return oldSpeciesData().extendWith(type); + } + + BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = L_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendL(type2, form2, value); + } + BoundMethodHandle bindArgumentI(BoundMethodHandle mh, int pos, int value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = I_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendI(type2, form2, value); + } + + BoundMethodHandle bindArgumentJ(BoundMethodHandle mh, int pos, long value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = J_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendJ(type2, form2, value); + } + + BoundMethodHandle bindArgumentF(BoundMethodHandle mh, int pos, float value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = F_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendF(type2, form2, value); + } + + BoundMethodHandle bindArgumentD(BoundMethodHandle mh, int pos, double value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = D_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendD(type2, form2, value); + } + + private MethodType bindArgumentType(BoundMethodHandle mh, int pos, BasicType bt) { + assert(mh.form == lambdaForm); + assert(mh.form.names[1+pos].type == bt); + assert(BasicType.basicType(mh.type().parameterType(pos)) == bt); + return mh.type().dropParameterTypes(pos, pos+1); + } + + /// Editing methods for lambda forms. + // Each editing method can (potentially) cache the edited LF so that it can be reused later. + + LambdaForm bindArgumentForm(int pos) { + Transform key = Transform.of(Transform.Kind.BIND_ARG, pos); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos))); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos)); + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + Name newBaseAddress; + NamedFunction getter = newData.getterFunction(oldData.fieldCount()); + + if (pos != 0) { + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress)); + } else { + // cannot bind the MH arg itself, unless oldData is empty + assert(oldData == BoundMethodHandle.SpeciesData.EMPTY); + newBaseAddress = new Name(L_TYPE).withConstraint(newData); + buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress)); + buf.insertParameter(0, newBaseAddress); + } + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm addArgumentForm(int pos, BasicType type) { + Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal()); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity+1); + assert(form.parameterType(pos) == type); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + buf.insertParameter(pos, new Name(type)); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm dupArgumentForm(int srcPos, int dstPos) { + Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity-1); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + assert(lambdaForm.parameter(srcPos).constraint == null); + assert(lambdaForm.parameter(dstPos).constraint == null); + buf.replaceParameterByCopy(dstPos, srcPos); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm spreadArgumentsForm(int pos, Class arrayType, int arrayLength) { + Class elementType = arrayType.getComponentType(); + Class erasedArrayType = arrayType; + if (!elementType.isPrimitive()) + erasedArrayType = Object[].class; + BasicType bt = basicType(elementType); + int elementTypeKey = bt.ordinal(); + if (bt.basicTypeClass() != elementType) { + if (elementType.isPrimitive()) { + elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); + } + } + Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - arrayLength + 1); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + assert(pos <= MethodType.MAX_JVM_ARITY); + assert(pos + arrayLength <= lambdaForm.arity); + assert(pos > 0); // cannot spread the MH arg itself + + Name spreadParam = new Name(L_TYPE); + Name checkSpread = new Name(MethodHandleImpl.Lazy.NF_checkSpreadArgument, spreadParam, arrayLength); + + // insert the new expressions + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos++, checkSpread); + // adjust the arguments + MethodHandle aload = MethodHandles.arrayElementGetter(erasedArrayType); + for (int i = 0; i < arrayLength; i++) { + Name loadArgument = new Name(aload, spreadParam, i); + buf.insertExpression(exprPos + i, loadArgument); + buf.replaceParameterByCopy(pos + i, exprPos + i); + } + buf.insertParameter(pos, spreadParam); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm collectArgumentsForm(int pos, MethodType collectorType) { + int collectorArity = collectorType.parameterCount(); + boolean dropResult = (collectorType.returnType() == void.class); + if (collectorArity == 1 && !dropResult) { + return filterArgumentForm(pos, basicType(collectorType.parameterType(0))); + } + BasicType[] newTypes = BasicType.basicTypes(collectorType.parameterList()); + Transform.Kind kind = (dropResult + ? Transform.Kind.COLLECT_ARGS_TO_VOID + : Transform.Kind.COLLECT_ARGS); + if (dropResult && collectorArity == 0) pos = 1; // pure side effect + Transform key = Transform.of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes)); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity); + return form; + } + form = makeArgumentCombinationForm(pos, collectorType, false, dropResult); + return putInCache(key, form); + } + + LambdaForm collectArgumentArrayForm(int pos, MethodHandle arrayCollector) { + MethodType collectorType = arrayCollector.type(); + int collectorArity = collectorType.parameterCount(); + assert(arrayCollector.intrinsicName() == Intrinsic.NEW_ARRAY); + Class arrayType = collectorType.returnType(); + Class elementType = arrayType.getComponentType(); + BasicType argType = basicType(elementType); + int argTypeKey = argType.ordinal(); + if (argType.basicTypeClass() != elementType) { + // return null if it requires more metadata (like String[].class) + if (!elementType.isPrimitive()) + return null; + argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); + } + assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType))); + Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY; + Transform key = Transform.of(kind, pos, collectorArity, argTypeKey); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - 1 + collectorArity); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + assert(pos + 1 <= lambdaForm.arity); + assert(pos > 0); // cannot filter the MH arg itself + + Name[] newParams = new Name[collectorArity]; + for (int i = 0; i < collectorArity; i++) { + newParams[i] = new Name(pos + i, argType); + } + Name callCombiner = new Name(arrayCollector, (Object[]) /*...*/ newParams); + + // insert the new expression + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos, callCombiner); + + // insert new arguments + int argPos = pos + 1; // skip result parameter + for (Name newParam : newParams) { + buf.insertParameter(argPos++, newParam); + } + assert(buf.lastIndexOf(callCombiner) == exprPos+newParams.length); + buf.replaceParameterByCopy(pos, exprPos+newParams.length); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm filterArgumentForm(int pos, BasicType newType) { + Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal()); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity); + assert(form.parameterType(pos) == newType); + return form; + } + + BasicType oldType = lambdaForm.parameterType(pos); + MethodType filterType = MethodType.methodType(oldType.basicTypeClass(), + newType.basicTypeClass()); + form = makeArgumentCombinationForm(pos, filterType, false, false); + return putInCache(key, form); + } + + private LambdaForm makeArgumentCombinationForm(int pos, + MethodType combinerType, + boolean keepArguments, boolean dropResult) { + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + int combinerArity = combinerType.parameterCount(); + int resultArity = (dropResult ? 0 : 1); + + assert(pos <= MethodType.MAX_JVM_ARITY); + assert(pos + resultArity + (keepArguments ? combinerArity : 0) <= lambdaForm.arity); + assert(pos > 0); // cannot filter the MH arg itself + assert(combinerType == combinerType.basicType()); + assert(combinerType.returnType() != void.class || dropResult); + + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE); + + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + Name newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + + Name getCombiner = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress); + Object[] combinerArgs = new Object[1 + combinerArity]; + combinerArgs[0] = getCombiner; + Name[] newParams; + if (keepArguments) { + newParams = new Name[0]; + System.arraycopy(lambdaForm.names, pos + resultArity, + combinerArgs, 1, combinerArity); + } else { + newParams = new Name[combinerArity]; + BasicType[] newTypes = basicTypes(combinerType.parameterList()); + for (int i = 0; i < newTypes.length; i++) { + newParams[i] = new Name(pos + i, newTypes[i]); + } + System.arraycopy(newParams, 0, + combinerArgs, 1, combinerArity); + } + Name callCombiner = new Name(combinerType, combinerArgs); + + // insert the two new expressions + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos+0, getCombiner); + buf.insertExpression(exprPos+1, callCombiner); + + // insert new arguments, if needed + int argPos = pos + resultArity; // skip result parameter + for (Name newParam : newParams) { + buf.insertParameter(argPos++, newParam); + } + assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length); + if (!dropResult) { + buf.replaceParameterByCopy(pos, exprPos+1+newParams.length); + } + + return buf.endEdit(); + } + + LambdaForm filterReturnForm(BasicType newType, boolean constantZero) { + Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN); + Transform key = Transform.of(kind, newType.ordinal()); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity); + assert(form.returnType() == newType); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + int insPos = lambdaForm.names.length; + Name callFilter; + if (constantZero) { + // Synthesize a constant zero value for the given type. + if (newType == V_TYPE) + callFilter = null; + else + callFilter = new Name(constantZero(newType)); + } else { + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE); + + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + Name newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + + Name getFilter = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress); + buf.insertExpression(insPos++, getFilter); + BasicType oldType = lambdaForm.returnType(); + if (oldType == V_TYPE) { + MethodType filterType = MethodType.methodType(newType.basicTypeClass()); + callFilter = new Name(filterType, getFilter); + } else { + MethodType filterType = MethodType.methodType(newType.basicTypeClass(), oldType.basicTypeClass()); + callFilter = new Name(filterType, getFilter, lambdaForm.names[lambdaForm.result]); + } + } + + if (callFilter != null) + buf.insertExpression(insPos++, callFilter); + buf.setResult(callFilter); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) { + int combinerArity = combinerType.parameterCount(); + Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS); + Transform key = Transform.of(kind, foldPos, combinerArity); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0)); + return form; + } + form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult); + return putInCache(key, form); + } + + LambdaForm permuteArgumentsForm(int skip, int[] reorder) { + assert(skip == 1); // skip only the leading MH argument, names[0] + int length = lambdaForm.names.length; + int outArgs = reorder.length; + int inTypes = 0; + boolean nullPerm = true; + for (int i = 0; i < reorder.length; i++) { + int inArg = reorder[i]; + if (inArg != i) nullPerm = false; + inTypes = Math.max(inTypes, inArg+1); + } + assert(skip + reorder.length == lambdaForm.arity); + if (nullPerm) return lambdaForm; // do not bother to cache + Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == skip+inTypes) : form; + return form; + } + + BasicType[] types = new BasicType[inTypes]; + for (int i = 0; i < outArgs; i++) { + int inArg = reorder[i]; + types[inArg] = lambdaForm.names[skip + i].type; + } + assert (skip + outArgs == lambdaForm.arity); + assert (permutedTypesMatch(reorder, types, lambdaForm.names, skip)); + int pos = 0; + while (pos < outArgs && reorder[pos] == pos) { + pos += 1; + } + Name[] names2 = new Name[length - outArgs + inTypes]; + System.arraycopy(lambdaForm.names, 0, names2, 0, skip + pos); + int bodyLength = length - lambdaForm.arity; + System.arraycopy(lambdaForm.names, skip + outArgs, names2, skip + inTypes, bodyLength); + int arity2 = names2.length - bodyLength; + int result2 = lambdaForm.result; + if (result2 >= 0) { + if (result2 < skip + outArgs) { + result2 = reorder[result2 - skip]; + } else { + result2 = result2 - outArgs + inTypes; + } + } + for (int j = pos; j < outArgs; j++) { + Name n = lambdaForm.names[skip + j]; + int i = reorder[j]; + Name n2 = names2[skip + i]; + if (n2 == null) { + names2[skip + i] = n2 = new Name(types[i]); + } else { + assert (n2.type == types[i]); + } + for (int k = arity2; k < names2.length; k++) { + names2[k] = names2[k].replaceName(n, n2); + } + } + for (int i = skip + pos; i < arity2; i++) { + if (names2[i] == null) { + names2[i] = argument(i, types[i - skip]); + } + } + for (int j = lambdaForm.arity; j < lambdaForm.names.length; j++) { + int i = j - lambdaForm.arity + arity2; + Name n = lambdaForm.names[j]; + Name n2 = names2[i]; + if (n != n2) { + for (int k = i + 1; k < names2.length; k++) { + names2[k] = names2[k].replaceName(n, n2); + } + } + } + + form = new LambdaForm(lambdaForm.debugName, arity2, names2, result2); + return putInCache(key, form); + } + + static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) { + for (int i = 0; i < reorder.length; i++) { + assert (names[skip + i].isParam()); + assert (names[skip + i].type == types[reorder[i]]); + } + return true; + } +} diff --git a/src/share/classes/java/lang/invoke/MemberName.java b/src/share/classes/java/lang/invoke/MemberName.java index 9cc901eea7abbec4d180cf2f4e23baf476ec4461..cd169f3721f03575184579f6f9634edfdc6008cb 100644 --- a/src/share/classes/java/lang/invoke/MemberName.java +++ b/src/share/classes/java/lang/invoke/MemberName.java @@ -327,10 +327,6 @@ import java.util.Objects; assert(getReferenceKind() == oldKind); assert(MethodHandleNatives.refKindIsValid(refKind)); flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT); -// if (isConstructor() && refKind != REF_newInvokeSpecial) -// flags += (IS_METHOD - IS_CONSTRUCTOR); -// else if (refKind == REF_newInvokeSpecial && isMethod()) -// flags += (IS_CONSTRUCTOR - IS_METHOD); return this; } @@ -344,9 +340,11 @@ import java.util.Objects; return !testFlags(mask, 0); } - /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */ + /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). + * Also returns true for the non-public MH.invokeBasic. + */ public boolean isMethodHandleInvoke() { - final int bits = MH_INVOKE_MODS; + final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; final int negs = Modifier.STATIC; if (testFlags(bits | negs, bits) && clazz == MethodHandle.class) { @@ -355,7 +353,14 @@ import java.util.Objects; return false; } public static boolean isMethodHandleInvokeName(String name) { - return name.equals("invoke") || name.equals("invokeExact"); + switch (name) { + case "invoke": + case "invokeExact": + case "invokeBasic": // internal sig-poly method + return true; + default: + return false; + } } private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC; @@ -720,16 +725,8 @@ import java.util.Objects; init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); initResolved(false); } - /** Create a field or type name from the given components: Declaring class, name, type. - * The declaring class may be supplied as null if this is to be a bare name and type. - * The modifier flags default to zero. - * The resulting name will in an unresolved state. - */ - public MemberName(Class defClass, String name, Class type, Void unused) { - this(defClass, name, type, REF_NONE); - initResolved(false); - } - /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. + /** Create a method or constructor name from the given components: + * Declaring class, name, type, reference kind. * It will be a constructor if and only if the name is {@code "<init>"}. * The declaring class may be supplied as null if this is to be a bare name and type. * The last argument is optional, a boolean which requests REF_invokeSpecial. diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java index ce115df85ed175758c72a59206fd5fdad8d955ff..f0169e73dfc8ecfa7eb3fac4db7b31b1c9869208 100644 --- a/src/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/share/classes/java/lang/invoke/MethodHandle.java @@ -27,12 +27,8 @@ package java.lang.invoke; import java.util.*; -import sun.invoke.util.*; -import sun.misc.Unsafe; import static java.lang.invoke.MethodHandleStatics.*; -import java.util.logging.Level; -import java.util.logging.Logger; /** * A method handle is a typed, directly executable reference to an underlying method, @@ -625,15 +621,8 @@ public abstract class MethodHandle { * @see MethodHandles#spreadInvoker */ public Object invokeWithArguments(Object... arguments) throws Throwable { - int argc = arguments == null ? 0 : arguments.length; - @SuppressWarnings("LocalVariableHidesMemberVariable") - MethodType type = type(); - if (type.parameterCount() != argc || isVarargsCollector()) { - // simulate invoke - return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); - } - MethodHandle invoker = type.invokers().varargsInvoker(); - return invoker.invokeExact(this, arguments); + MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length); + return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments); } /** @@ -731,7 +720,7 @@ public abstract class MethodHandle { *
  • If the return type T0 is void and T1 a primitive, * a zero value is introduced. * - * (Note: Both T0 and T1 may be regarded as static types, + * (Note: Both T0 and T1 may be regarded as static types, * because neither corresponds specifically to the dynamic type of any * actual argument or return value.) *

    @@ -763,18 +752,26 @@ public abstract class MethodHandle { return this; } // Return 'this.asTypeCache' if the conversion is already memoized. + MethodHandle atc = asTypeCached(newType); + if (atc != null) { + return atc; + } + return asTypeUncached(newType); + } + + private MethodHandle asTypeCached(MethodType newType) { MethodHandle atc = asTypeCache; if (atc != null && newType == atc.type) { return atc; } - return asTypeUncached(newType); + return null; } /** Override this to change asType behavior. */ /*non-public*/ MethodHandle asTypeUncached(MethodType newType) { if (!type.isConvertibleTo(newType)) throw new WrongMethodTypeException("cannot convert "+this+" to "+newType); - return asTypeCache = convertArguments(newType); + return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, true); } /** @@ -867,34 +864,48 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray * @see #asCollector */ public MethodHandle asSpreader(Class arrayType, int arrayLength) { - asSpreaderChecks(arrayType, arrayLength); - int spreadArgPos = type.parameterCount() - arrayLength; - return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength); + MethodType postSpreadType = asSpreaderChecks(arrayType, arrayLength); + int arity = type().parameterCount(); + int spreadArgPos = arity - arrayLength; + if (USE_LAMBDA_FORM_EDITOR) { + MethodHandle afterSpread = this.asType(postSpreadType); + BoundMethodHandle mh = afterSpread.rebind(); + LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength); + MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType); + return mh.copyWith(preSpreadType, lform); + } else { + return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength); + } } - private void asSpreaderChecks(Class arrayType, int arrayLength) { + /** + * See if {@code asSpreader} can be validly called with the given arguments. + * Return the type of the method handle call after spreading but before conversions. + */ + private MethodType asSpreaderChecks(Class arrayType, int arrayLength) { spreadArrayChecks(arrayType, arrayLength); int nargs = type().parameterCount(); if (nargs < arrayLength || arrayLength < 0) throw newIllegalArgumentException("bad spread array length"); - if (arrayType != Object[].class && arrayLength != 0) { - boolean sawProblem = false; - Class arrayElement = arrayType.getComponentType(); - for (int i = nargs - arrayLength; i < nargs; i++) { - if (!MethodType.canConvert(arrayElement, type().parameterType(i))) { - sawProblem = true; + Class arrayElement = arrayType.getComponentType(); + MethodType mtype = type(); + boolean match = true, fail = false; + for (int i = nargs - arrayLength; i < nargs; i++) { + Class ptype = mtype.parameterType(i); + if (ptype != arrayElement) { + match = false; + if (!MethodType.canConvert(arrayElement, ptype)) { + fail = true; break; } } - if (sawProblem) { - ArrayList> ptypes = new ArrayList<>(type().parameterList()); - for (int i = nargs - arrayLength; i < nargs; i++) { - ptypes.set(i, arrayElement); - } - // elicit an error: - this.asType(MethodType.methodType(type().returnType(), ptypes)); - } } + if (match) return mtype; + MethodType needType = mtype.asSpreaderType(arrayType, arrayLength); + if (!fail) return needType; + // elicit an error: + this.asType(needType); + throw newInternalError("should not return", null); } private void spreadArrayChecks(Class arrayType, int arrayLength) { @@ -984,16 +995,31 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); */ public MethodHandle asCollector(Class arrayType, int arrayLength) { asCollectorChecks(arrayType, arrayLength); - int collectArgPos = type().parameterCount()-1; - MethodHandle target = this; - if (arrayType != type().parameterType(collectArgPos)) - target = convertArguments(type().changeParameterType(collectArgPos, arrayType)); - MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength); - return MethodHandles.collectArguments(target, collectArgPos, collector); + int collectArgPos = type().parameterCount() - 1; + if (USE_LAMBDA_FORM_EDITOR) { + BoundMethodHandle mh = rebind(); + MethodType resultType = type().asCollectorType(arrayType, arrayLength); + MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); + LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray); + if (lform != null) { + return mh.copyWith(resultType, lform); + } + lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType()); + return mh.copyWithExtendL(resultType, lform, newArray); + } else { + MethodHandle target = this; + if (arrayType != type().parameterType(collectArgPos)) + target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), true); + MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength); + return MethodHandles.collectArguments(target, collectArgPos, collector); + } } - // private API: return true if last param exactly matches arrayType - private boolean asCollectorChecks(Class arrayType, int arrayLength) { + /** + * See if {@code asCollector} can be validly called with the given arguments. + * Return false if the last parameter is not an exact match to arrayType. + */ + /*non-public*/ boolean asCollectorChecks(Class arrayType, int arrayLength) { spreadArrayChecks(arrayType, arrayLength); int nargs = type().parameterCount(); if (nargs != 0) { @@ -1155,7 +1181,7 @@ assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); * @see #asFixedArity */ public MethodHandle asVarargsCollector(Class arrayType) { - Class arrayElement = arrayType.getComponentType(); + arrayType.getClass(); // explicit NPE boolean lastMatch = asCollectorChecks(arrayType, 0); if (isVarargsCollector() && lastMatch) return this; @@ -1257,14 +1283,8 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); * @see MethodHandles#insertArguments */ public MethodHandle bindTo(Object x) { - Class ptype; - @SuppressWarnings("LocalVariableHidesMemberVariable") - MethodType type = type(); - if (type.parameterCount() == 0 || - (ptype = type.parameterType(0)).isPrimitive()) - throw newIllegalArgumentException("no leading reference parameter", x); - x = ptype.cast(x); // throw CCE if needed - return bindReceiver(x); + x = type.leadingReferenceParameter().cast(x); // throw CCE if needed + return bindArgumentL(0, x); } /** @@ -1284,14 +1304,17 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); */ @Override public String toString() { - if (DEBUG_METHOD_HANDLE_NAMES) return debugString(); + if (DEBUG_METHOD_HANDLE_NAMES) return "MethodHandle"+debugString(); return standardString(); } String standardString() { return "MethodHandle"+type; } + /** Return a string with a several lines describing the method handle structure. + * This string would be suitable for display in an IDE debugger. + */ String debugString() { - return standardString()+"/LF="+internalForm()+internalProperties(); + return type+" : "+internalForm()+internalProperties(); } //// Implementation methods. @@ -1300,22 +1323,42 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); // Other transforms to do: convert, explicitCast, permute, drop, filter, fold, GWT, catch + BoundMethodHandle bindArgumentL(int pos, Object value) { + return rebind().bindArgumentL(pos, value); + } + /*non-public*/ MethodHandle setVarargs(MemberName member) throws IllegalAccessException { if (!member.isVarargs()) return this; - int argc = type().parameterCount(); - if (argc != 0) { - Class arrayType = type().parameterType(argc-1); - if (arrayType.isArray()) { - return MethodHandleImpl.makeVarargsCollector(this, arrayType); - } + Class arrayType = type().lastParameterType(); + if (arrayType.isArray()) { + return MethodHandleImpl.makeVarargsCollector(this, arrayType); } throw member.makeAccessException("cannot make variable arity", null); } + /*non-public*/ - MethodHandle viewAsType(MethodType newType) { + MethodHandle viewAsType(MethodType newType, boolean strict) { // No actual conversions, just a new view of the same method. - return MethodHandleImpl.makePairwiseConvert(this, newType, 0); + // Note that this operation must not produce a DirectMethodHandle, + // because retyped DMHs, like any transformed MHs, + // cannot be cracked into MethodHandleInfo. + assert viewAsTypeChecks(newType, strict); + BoundMethodHandle mh = rebind(); + assert(!((MethodHandle)mh instanceof DirectMethodHandle)); + return mh.copyWith(newType, mh.form); + } + + /*non-public*/ + boolean viewAsTypeChecks(MethodType newType, boolean strict) { + if (strict) { + assert(type().isViewableAs(newType, true)) + : Arrays.asList(this, newType); + } else { + assert(type().basicType().isViewableAs(newType.basicType(), true)) + : Arrays.asList(this, newType); + } + return true; } // Decoding @@ -1336,9 +1379,15 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); } /*non-public*/ - MethodHandle withInternalMemberName(MemberName member) { + MethodHandleImpl.Intrinsic intrinsicName() { + // no special intrinsic meaning to most MHs + return MethodHandleImpl.Intrinsic.NONE; + } + + /*non-public*/ + MethodHandle withInternalMemberName(MemberName member, boolean isInvokeSpecial) { if (member != null) { - return MethodHandleImpl.makeWrappedMember(this, member); + return MethodHandleImpl.makeWrappedMember(this, member, isInvokeSpecial); } else if (internalMemberName() == null) { // The required internaMemberName is null, and this MH (like most) doesn't have one. return this; @@ -1362,7 +1411,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*non-public*/ Object internalProperties() { - // Override to something like "/FOO=bar" + // Override to something to follow this.form, like "\n& FOO=bar" return ""; } @@ -1370,114 +1419,14 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); //// Sub-classes can override these default implementations. //// All these methods assume arguments are already validated. - /*non-public*/ MethodHandle convertArguments(MethodType newType) { - // Override this if it can be improved. - return MethodHandleImpl.makePairwiseConvert(this, newType, 1); - } - - /*non-public*/ - MethodHandle bindArgument(int pos, char basicType, Object value) { - // Override this if it can be improved. - return rebind().bindArgument(pos, basicType, value); - } - - /*non-public*/ - MethodHandle bindReceiver(Object receiver) { - // Override this if it can be improved. - return bindArgument(0, 'L', receiver); - } - - /*non-public*/ - MethodHandle bindImmediate(int pos, char basicType, Object value) { - // Bind an immediate value to a position in the arguments. - // This means, elide the respective argument, - // and replace all references to it in NamedFunction args with the specified value. - - // CURRENT RESTRICTIONS - // * only for pos 0 and UNSAFE (position is adjusted in MHImpl to make API usable for others) - assert pos == 0 && basicType == 'L' && value instanceof Unsafe; - MethodType type2 = type.dropParameterTypes(pos, pos + 1); // adjustment: ignore receiver! - LambdaForm form2 = form.bindImmediate(pos + 1, basicType, value); // adjust pos to form-relative pos - return copyWith(type2, form2); - } - - /*non-public*/ - MethodHandle copyWith(MethodType mt, LambdaForm lf) { - throw new InternalError("copyWith: " + this.getClass()); - } - /*non-public*/ - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - // Override this if it can be improved. - return rebind().dropArguments(srcType, pos, drops); - } - - /*non-public*/ - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - // Override this if it can be improved. - return rebind().permuteArguments(newType, reorder); - } + abstract MethodHandle copyWith(MethodType mt, LambdaForm lf); - /*non-public*/ - MethodHandle rebind() { - // Bind 'this' into a new invoker, of the known class BMH. - MethodType type2 = type(); - LambdaForm form2 = reinvokerForm(this); - // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) } - return BoundMethodHandle.bindSingle(type2, form2, this); - } - - /*non-public*/ - MethodHandle reinvokerTarget() { - throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this); - } - - /** Create a LF which simply reinvokes a target of the given basic type. - * The target MH must override {@link #reinvokerTarget} to provide the target. + /** Require this method handle to be a BMH, or else replace it with a "wrapper" BMH. + * Many transforms are implemented only for BMHs. + * @return a behaviorally equivalent BMH */ - static LambdaForm reinvokerForm(MethodHandle target) { - MethodType mtype = target.type().basicType(); - LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE); - if (reinvoker != null) return reinvoker; - if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY) - return makeReinvokerForm(target.type(), target); // cannot cache this - reinvoker = makeReinvokerForm(mtype, null); - return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker); - } - private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) { - boolean customized = (customTargetOrNull != null); - MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype); - final int THIS_BMH = 0; - final int ARG_BASE = 1; - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); - int nameCursor = ARG_LIMIT; - final int NEXT_MH = customized ? -1 : nameCursor++; - final int REINVOKE = nameCursor++; - LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); - Object[] targetArgs; - MethodHandle targetMH; - if (customized) { - targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class); - targetMH = customTargetOrNull; - } else { - names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]); - targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class); - targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH - targetMH = MethodHandles.basicInvoker(mtype); - } - names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs); - return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names); - } - - private static final LambdaForm.NamedFunction NF_reinvokerTarget; - static { - try { - NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class - .getDeclaredMethod("reinvokerTarget")); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - } + abstract BoundMethodHandle rebind(); /** * Replace the old lambda form of this method handle with a new one. @@ -1489,6 +1438,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*non-public*/ void updateForm(LambdaForm newForm) { if (form == newForm) return; + assert(this instanceof DirectMethodHandle && this.internalMemberName().isStatic()); // ISSUE: Should we have a memory fence here? UNSAFE.putObject(this, FORM_OFFSET, newForm); this.form.prepare(); // as in MethodHandle. diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java index ee1584f80f64307c12bb6ea07c836e66ab46fc2a..026b2cd40350850300f70a4c0fe5a9f2a12ddca7 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -27,8 +27,10 @@ package java.lang.invoke; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; + import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; @@ -44,6 +46,20 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * @author jrose */ /*non-public*/ abstract class MethodHandleImpl { + // Do not adjust this except for special platforms: + private static final int MAX_ARITY; + static { + final Object[] values = { 255 }; + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + values[0] = Integer.getInteger(MethodHandleImpl.class.getName()+".MAX_ARITY", 255); + return null; + } + }); + MAX_ARITY = (Integer) values[0]; + } + /// Factory methods to create method handles: static void initStatics() { @@ -52,27 +68,55 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; } static MethodHandle makeArrayElementAccessor(Class arrayClass, boolean isSetter) { + if (arrayClass == Object[].class) + return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER); if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); - MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter); - MethodType srcType = accessor.type().erase(); - MethodType lambdaType = srcType.invokerType(); - Name[] names = arguments(1, lambdaType); - Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount()); - names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args); - LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names); - MethodHandle mh = SimpleMethodHandle.make(srcType, form); - if (ArrayAccessor.needCast(arrayClass)) { - mh = mh.bindTo(arrayClass); - } - mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter)); + MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass); + int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX); + MethodHandle mh = cache[cacheIndex]; + if (mh != null) return mh; + mh = ArrayAccessor.getAccessor(arrayClass, isSetter); + MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter); + if (mh.type() != correctType) { + assert(mh.type().parameterType(0) == Object[].class); + assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class); + assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType()); + // safe to view non-strictly, because element type follows from array type + mh = mh.viewAsType(correctType, false); + } + mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD)); + // Atomically update accessor cache. + synchronized(cache) { + if (cache[cacheIndex] == null) { + cache[cacheIndex] = mh; + } else { + // Throw away newly constructed accessor and use cached version. + mh = cache[cacheIndex]; + } + } return mh; } static final class ArrayAccessor { /// Support for array element access - static final HashMap, MethodHandle> GETTER_CACHE = new HashMap<>(); // TODO use it - static final HashMap, MethodHandle> SETTER_CACHE = new HashMap<>(); // TODO use it + static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2; + static final ClassValue TYPED_ACCESSORS + = new ClassValue() { + @Override + protected MethodHandle[] computeValue(Class type) { + return new MethodHandle[INDEX_LIMIT]; + } + }; + static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER; + static { + MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class); + cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD); + cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true), Intrinsic.ARRAY_STORE); + + assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName())); + assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName())); + } static int getElementI(int[] a, int i) { return a[i]; } static long getElementJ(long[] a, int i) { return a[i]; } @@ -94,45 +138,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static void setElementC(char[] a, int i, char x) { a[i] = x; } static void setElementL(Object[] a, int i, Object x) { a[i] = x; } - static Object getElementL(Class arrayClass, Object[] a, int i) { arrayClass.cast(a); return a[i]; } - static void setElementL(Class arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; } - - // Weakly typed wrappers of Object[] accessors: - static Object getElementL(Object a, int i) { return getElementL((Object[])a, i); } - static void setElementL(Object a, int i, Object x) { setElementL((Object[]) a, i, x); } - static Object getElementL(Object arrayClass, Object a, int i) { return getElementL((Class) arrayClass, (Object[])a, i); } - static void setElementL(Object arrayClass, Object a, int i, Object x) { setElementL((Class) arrayClass, (Object[])a, i, x); } - - static boolean needCast(Class arrayClass) { - Class elemClass = arrayClass.getComponentType(); - return !elemClass.isPrimitive() && elemClass != Object.class; - } static String name(Class arrayClass, boolean isSetter) { Class elemClass = arrayClass.getComponentType(); - if (elemClass == null) throw new IllegalArgumentException(); + if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass); return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass); } - static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false; // FIXME: decide static MethodType type(Class arrayClass, boolean isSetter) { Class elemClass = arrayClass.getComponentType(); Class arrayArgClass = arrayClass; if (!elemClass.isPrimitive()) { arrayArgClass = Object[].class; - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS) - arrayArgClass = Object.class; + elemClass = Object.class; } - if (!needCast(arrayClass)) { - return !isSetter ? + return !isSetter ? MethodType.methodType(elemClass, arrayArgClass, int.class) : MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); - } else { - Class classArgClass = Class.class; - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS) - classArgClass = Object.class; - return !isSetter ? - MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) : - MethodType.methodType(void.class, classArgClass, arrayArgClass, int.class, Object.class); - } } static MethodType correctType(Class arrayClass, boolean isSetter) { Class elemClass = arrayClass.getComponentType(); @@ -159,40 +179,110 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * integral widening or narrowing, and floating point widening or narrowing. * @param srcType required call type * @param target original method handle - * @param level which strength of conversion is allowed + * @param strict if true, only asType conversions are allowed; if false, explicitCastArguments conversions allowed + * @param monobox if true, unboxing conversions are assumed to be exactly typed (Integer to int only, not long or double) * @return an adapter to the original handle with the desired new type, * or the original target if the types are already identical * or null if the adaptation cannot be made */ - static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) { - assert(level >= 0 && level <= 2); + static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, + boolean strict, boolean monobox) { MethodType dstType = target.type(); assert(dstType.parameterCount() == target.type().parameterCount()); if (srcType == dstType) return target; + if (USE_LAMBDA_FORM_EDITOR) { + return makePairwiseConvertByEditor(target, srcType, strict, monobox); + } else { + return makePairwiseConvertIndirect(target, srcType, strict, monobox); + } + } + + private static int countNonNull(Object[] array) { + int count = 0; + for (Object x : array) { + if (x != null) ++count; + } + return count; + } + static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType srcType, + boolean strict, boolean monobox) { + Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); + int convCount = countNonNull(convSpecs); + if (convCount == 0) + return target.viewAsType(srcType, strict); + MethodType basicSrcType = srcType.basicType(); + MethodType midType = target.type().basicType(); + BoundMethodHandle mh = target.rebind(); + // FIXME: Reduce number of bindings when there is more than one Class conversion. + // FIXME: Reduce number of bindings when there are repeated conversions. + for (int i = 0; i < convSpecs.length-1; i++) { + Object convSpec = convSpecs[i]; + if (convSpec == null) continue; + MethodHandle fn; + if (convSpec instanceof Class) { + fn = Lazy.MH_castReference.bindTo(convSpec); + } else { + fn = (MethodHandle) convSpec; + } + Class newType = basicSrcType.parameterType(i); + if (--convCount == 0) + midType = srcType; + else + midType = midType.changeParameterType(i, newType); + LambdaForm form2 = mh.editor().filterArgumentForm(1+i, BasicType.basicType(newType)); + mh = mh.copyWithExtendL(midType, form2, fn); + mh = mh.rebind(); + } + Object convSpec = convSpecs[convSpecs.length-1]; + if (convSpec != null) { + MethodHandle fn; + if (convSpec instanceof Class) { + if (convSpec == void.class) + fn = null; + else + fn = Lazy.MH_castReference.bindTo(convSpec); + } else { + fn = (MethodHandle) convSpec; + } + Class newType = basicSrcType.returnType(); + assert(--convCount == 0); + midType = srcType; + if (fn != null) { + mh = mh.rebind(); // rebind if too complex + LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), false); + mh = mh.copyWithExtendL(midType, form2, fn); + } else { + LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), true); + mh = mh.copyWith(midType, form2); + } + } + assert(convCount == 0); + assert(mh.type().equals(srcType)); + return mh; + } + + static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType, + boolean strict, boolean monobox) { // Calculate extra arguments (temporaries) required in the names array. - // FIXME: Use an ArrayList. Some arguments require more than one conversion step. + Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); final int INARG_COUNT = srcType.parameterCount(); - int conversions = 0; - boolean[] needConv = new boolean[1+INARG_COUNT]; - for (int i = 0; i <= INARG_COUNT; i++) { - Class src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i); - Class dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i); - if (!VerifyType.isNullConversion(src, dst) || - level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) { - needConv[i] = true; - conversions++; - } + int convCount = countNonNull(convSpecs); + boolean retConv = (convSpecs[INARG_COUNT] != null); + boolean retVoid = srcType.returnType() == void.class; + if (retConv && retVoid) { + convCount -= 1; + retConv = false; } - boolean retConv = needConv[INARG_COUNT]; final int IN_MH = 0; final int INARG_BASE = 1; final int INARG_LIMIT = INARG_BASE + INARG_COUNT; - final int NAME_LIMIT = INARG_LIMIT + conversions + 1; + final int NAME_LIMIT = INARG_LIMIT + convCount + 1; final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; + final int RESULT = (retVoid ? -1 : NAME_LIMIT - 1); // Now build a LambdaForm. MethodType lambdaType = srcType.basicType().invokerType(); @@ -204,59 +294,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; int nameCursor = INARG_LIMIT; for (int i = 0; i < INARG_COUNT; i++) { - Class src = srcType.parameterType(i); - Class dst = dstType.parameterType(i); - - if (!needConv[i]) { + Object convSpec = convSpecs[i]; + if (convSpec == null) { // do nothing: difference is trivial outArgs[OUTARG_BASE + i] = names[INARG_BASE + i]; continue; } - // Tricky case analysis follows. - MethodHandle fn = null; - if (src.isPrimitive()) { - if (dst.isPrimitive()) { - fn = ValueConversions.convertPrimitive(src, dst); - } else { - Wrapper w = Wrapper.forPrimitiveType(src); - MethodHandle boxMethod = ValueConversions.box(w); - if (dst == w.wrapperType()) - fn = boxMethod; - else - fn = boxMethod.asType(MethodType.methodType(dst, src)); - } + Name conv; + if (convSpec instanceof Class) { + Class convClass = (Class) convSpec; + conv = new Name(Lazy.MH_castReference, convClass, names[INARG_BASE + i]); } else { - if (dst.isPrimitive()) { - // Caller has boxed a primitive. Unbox it for the target. - Wrapper w = Wrapper.forPrimitiveType(dst); - if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) { - fn = ValueConversions.unbox(dst); - } else if (src == Object.class || !Wrapper.isWrapperType(src)) { - // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int - // must include additional conversions - // src must be examined at runtime, to detect Byte, Character, etc. - MethodHandle unboxMethod = (level == 1 - ? ValueConversions.unbox(dst) - : ValueConversions.unboxCast(dst)); - fn = unboxMethod; - } else { - // Example: Byte->int - // Do this by reformulating the problem to Byte->byte. - Class srcPrim = Wrapper.forWrapperType(src).primitiveType(); - MethodHandle unbox = ValueConversions.unbox(srcPrim); - // Compose the two conversions. FIXME: should make two Names for this job - fn = unbox.asType(MethodType.methodType(dst, src)); - } - } else { - // Simple reference conversion. - // Note: Do not check for a class hierarchy relation - // between src and dst. In all cases a 'null' argument - // will pass the cast conversion. - fn = ValueConversions.cast(dst, Lazy.MH_castReference); - } + MethodHandle fn = (MethodHandle) convSpec; + conv = new Name(fn, names[INARG_BASE + i]); } - Name conv = new Name(fn, names[INARG_BASE + i]); assert(names[nameCursor] == null); names[nameCursor++] = conv; assert(outArgs[OUTARG_BASE + i] == null); @@ -267,29 +319,29 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(nameCursor == OUT_CALL); names[OUT_CALL] = new Name(target, outArgs); - if (RETURN_CONV < 0) { + Object convSpec = convSpecs[INARG_COUNT]; + if (!retConv) { assert(OUT_CALL == names.length-1); } else { - Class needReturn = srcType.returnType(); - Class haveReturn = dstType.returnType(); - MethodHandle fn; - Object[] arg = { names[OUT_CALL] }; - if (haveReturn == void.class) { - // synthesize a zero value for the given void - Object zero = Wrapper.forBasicType(needReturn).zero(); - fn = MethodHandles.constant(needReturn, zero); - arg = new Object[0]; // don't pass names[OUT_CALL] to conversion + Name conv; + if (convSpec == void.class) { + conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType()))); + } else if (convSpec instanceof Class) { + Class convClass = (Class) convSpec; + conv = new Name(Lazy.MH_castReference, convClass, names[OUT_CALL]); } else { - MethodHandle identity = MethodHandles.identity(needReturn); - MethodType needConversion = identity.type().changeParameterType(0, haveReturn); - fn = makePairwiseConvert(identity, needConversion, level); + MethodHandle fn = (MethodHandle) convSpec; + if (fn.type().parameterCount() == 0) + conv = new Name(fn); // don't pass retval to void conversion + else + conv = new Name(fn, names[OUT_CALL]); } assert(names[RETURN_CONV] == null); - names[RETURN_CONV] = new Name(fn, arg); + names[RETURN_CONV] = conv; assert(RETURN_CONV == names.length-1); } - LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names); + LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT); return SimpleMethodHandle.make(srcType, form); } @@ -312,12 +364,79 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); } - static MethodHandle makeReferenceIdentity(Class refType) { - MethodType lambdaType = MethodType.genericMethodType(1).invokerType(); - Name[] names = arguments(1, lambdaType); - names[names.length - 1] = new Name(ValueConversions.identity(), names[1]); - LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names); - return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form); + static Object[] computeValueConversions(MethodType srcType, MethodType dstType, + boolean strict, boolean monobox) { + final int INARG_COUNT = srcType.parameterCount(); + Object[] convSpecs = new Object[INARG_COUNT+1]; + for (int i = 0; i <= INARG_COUNT; i++) { + boolean isRet = (i == INARG_COUNT); + Class src = isRet ? dstType.returnType() : srcType.parameterType(i); + Class dst = isRet ? srcType.returnType() : dstType.parameterType(i); + if (!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)) { + convSpecs[i] = valueConversion(src, dst, strict, monobox); + } + } + return convSpecs; + } + static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, + boolean strict) { + return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false); + } + + /** + * Find a conversion function from the given source to the given destination. + * This conversion function will be used as a LF NamedFunction. + * Return a Class object if a simple cast is needed. + * Return void.class if void is involved. + */ + static Object valueConversion(Class src, Class dst, boolean strict, boolean monobox) { + assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)); // caller responsibility + if (dst == void.class) + return dst; + MethodHandle fn; + if (src.isPrimitive()) { + if (src == void.class) { + return void.class; // caller must recognize this specially + } else if (dst.isPrimitive()) { + // Examples: int->byte, byte->int, boolean->int (!strict) + fn = ValueConversions.convertPrimitive(src, dst); + } else { + // Examples: int->Integer, boolean->Object, float->Number + Wrapper wsrc = Wrapper.forPrimitiveType(src); + fn = ValueConversions.boxExact(wsrc); + assert(fn.type().parameterType(0) == wsrc.primitiveType()); + assert(fn.type().returnType() == wsrc.wrapperType()); + if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) { + // Corner case, such as int->Long, which will probably fail. + MethodType mt = MethodType.methodType(dst, src); + if (strict) + fn = fn.asType(mt); + else + fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false); + } + } + } else if (dst.isPrimitive()) { + Wrapper wdst = Wrapper.forPrimitiveType(dst); + if (monobox || src == wdst.wrapperType()) { + // Use a strongly-typed unboxer, if possible. + fn = ValueConversions.unboxExact(wdst, strict); + } else { + // Examples: Object->int, Number->int, Comparable->int, Byte->int + // must include additional conversions + // src must be examined at runtime, to detect Byte, Character, etc. + fn = (strict + ? ValueConversions.unboxWiden(wdst) + : ValueConversions.unboxCast(wdst)); + } + } else { + // Simple reference conversion. + // Note: Do not check for a class hierarchy relation + // between src and dst. In all cases a 'null' argument + // will pass the cast conversion. + return dst; + } + assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn); + return fn; } static MethodHandle makeVarargsCollector(MethodHandle target, Class arrayType) { @@ -326,33 +445,45 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; if (type.parameterType(last) != arrayType) target = target.asType(type.changeParameterType(last, arrayType)); target = target.asFixedArity(); // make sure this attribute is turned off - return new AsVarargsCollector(target, target.type(), arrayType); + return new AsVarargsCollector(target, arrayType); } - static class AsVarargsCollector extends MethodHandle { + private static final class AsVarargsCollector extends DelegatingMethodHandle { private final MethodHandle target; private final Class arrayType; - private /*@Stable*/ MethodHandle asCollectorCache; + private @Stable MethodHandle asCollectorCache; - AsVarargsCollector(MethodHandle target, MethodType type, Class arrayType) { - super(type, reinvokerForm(target)); + AsVarargsCollector(MethodHandle target, Class arrayType) { + this(target.type(), target, arrayType); + } + AsVarargsCollector(MethodType type, MethodHandle target, Class arrayType) { + super(type, target); this.target = target; this.arrayType = arrayType; this.asCollectorCache = target.asCollector(arrayType, 0); } - @Override MethodHandle reinvokerTarget() { return target; } - @Override public boolean isVarargsCollector() { return true; } + @Override + protected MethodHandle getTarget() { + return target; + } + @Override public MethodHandle asFixedArity() { return target; } + @Override + MethodHandle setVarargs(MemberName member) { + if (member.isVarargs()) return this; + return asFixedArity(); + } + @Override public MethodHandle asTypeUncached(MethodType newType) { MethodType type = this.type(); @@ -381,54 +512,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; } @Override - MethodHandle setVarargs(MemberName member) { - if (member.isVarargs()) return this; - return asFixedArity(); - } - - @Override - MethodHandle viewAsType(MethodType newType) { - if (newType.lastParameterType() != type().lastParameterType()) - throw new InternalError(); - MethodHandle newTarget = asFixedArity().viewAsType(newType); - // put back the varargs bit: - return new AsVarargsCollector(newTarget, newType, arrayType); - } - - @Override - MemberName internalMemberName() { - return asFixedArity().internalMemberName(); - } - @Override - Class internalCallerClass() { - return asFixedArity().internalCallerClass(); - } - - /*non-public*/ - @Override - boolean isInvokeSpecial() { - return asFixedArity().isInvokeSpecial(); - } - - - @Override - MethodHandle bindArgument(int pos, char basicType, Object value) { - return asFixedArity().bindArgument(pos, basicType, value); - } - - @Override - MethodHandle bindReceiver(Object receiver) { - return asFixedArity().bindReceiver(receiver); - } - - @Override - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - return asFixedArity().dropArguments(srcType, pos, drops); - } - - @Override - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - return asFixedArity().permuteArguments(newType, reorder); + boolean viewAsTypeChecks(MethodType newType, boolean strict) { + super.viewAsTypeChecks(newType, true); + if (strict) return true; + // extra assertion for non-strict checks: + assert (type().lastParameterType().getComponentType() + .isAssignableFrom( + newType.lastParameterType().getComponentType())) + : Arrays.asList(this, newType); + return true; } } @@ -499,32 +591,46 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * Pre-initialized NamedFunctions for bootstrapping purposes. * Factored in an inner class to delay initialization until first usage. */ - private static class Lazy { + static class Lazy { private static final Class MHI = MethodHandleImpl.class; static final NamedFunction NF_checkSpreadArgument; static final NamedFunction NF_guardWithCatch; - static final NamedFunction NF_selectAlternative; static final NamedFunction NF_throwException; static final MethodHandle MH_castReference; + static final MethodHandle MH_selectAlternative; + static final MethodHandle MH_copyAsPrimitiveArray; + static final MethodHandle MH_fillNewTypedArray; + static final MethodHandle MH_fillNewArray; + static final MethodHandle MH_arrayIdentity; static { try { NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); NF_guardWithCatch = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class, MethodHandle.class, Object[].class)); - NF_selectAlternative = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class, - MethodHandle.class)); NF_throwException = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class)); NF_checkSpreadArgument.resolve(); NF_guardWithCatch.resolve(); - NF_selectAlternative.resolve(); NF_throwException.resolve(); - MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class); - MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt); + MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", + MethodType.methodType(Object.class, Class.class, Object.class)); + MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray", + MethodType.methodType(Object.class, Wrapper.class, Object[].class)); + MH_arrayIdentity = IMPL_LOOKUP.findStatic(MHI, "identity", + MethodType.methodType(Object[].class, Object[].class)); + MH_fillNewArray = IMPL_LOOKUP.findStatic(MHI, "fillNewArray", + MethodType.methodType(Object[].class, Integer.class, Object[].class)); + MH_fillNewTypedArray = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray", + MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); + + MH_selectAlternative = makeIntrinsic( + IMPL_LOOKUP.findStatic(MHI, "selectAlternative", + MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)), + Intrinsic.SELECT_ALTERNATIVE); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } @@ -595,29 +701,66 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle makeGuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) { - MethodType basicType = target.type().basicType(); - MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType); - int arity = basicType.parameterCount(); - int extraNames = 3; + MethodType type = target.type(); + assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type)); + MethodType basicType = type.basicType(); + LambdaForm form = makeGuardWithTestForm(basicType); + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); + BoundMethodHandle mh; + try { + mh = (BoundMethodHandle) + data.constructor().invokeBasic(type, form, + (Object) test, (Object) target, (Object) fallback); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + assert(mh.type() == type); + return mh; + } + + static + LambdaForm makeGuardWithTestForm(MethodType basicType) { + LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT); + if (lform != null) return lform; + final int THIS_MH = 0; // the BMH_LLL + final int ARG_BASE = 1; // start of incoming arguments + final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); + int nameCursor = ARG_LIMIT; + final int GET_TEST = nameCursor++; + final int GET_TARGET = nameCursor++; + final int GET_FALLBACK = nameCursor++; + final int CALL_TEST = nameCursor++; + final int SELECT_ALT = nameCursor++; + final int CALL_TARGET = nameCursor++; + assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative + MethodType lambdaType = basicType.invokerType(); - Name[] names = arguments(extraNames, lambdaType); + Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); + + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); + names[THIS_MH] = names[THIS_MH].withConstraint(data); + names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]); + names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]); + names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]); - Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class); - Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class); + Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class); // call test - names[arity + 1] = new Name(test, testArgs); + MethodType testType = basicType.changeReturnType(boolean.class).basicType(); + invokeArgs[0] = names[GET_TEST]; + names[CALL_TEST] = new Name(testType, invokeArgs); // call selectAlternative - Object[] selectArgs = { names[arity + 1], target, fallback }; - names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs); - targetArgs[0] = names[arity + 2]; + names[SELECT_ALT] = new Name(Lazy.MH_selectAlternative, names[CALL_TEST], + names[GET_TARGET], names[GET_FALLBACK]); // call target or fallback - names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs); + invokeArgs[0] = names[SELECT_ALT]; + names[CALL_TARGET] = new Name(basicType, invokeArgs); - LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names); - return SimpleMethodHandle.make(target.type(), form); + lform = new LambdaForm("guard", lambdaType.parameterCount(), names); + + return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform); } /** @@ -665,6 +808,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); + names[THIS_MH] = names[THIS_MH].withConstraint(data); names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]); names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]); names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]); @@ -679,7 +823,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; Object[] args = new Object[invokeBasic.type().parameterCount()]; args[0] = names[GET_COLLECT_ARGS]; System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE); - names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args); + names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.GUARD_WITH_CATCH), args); // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L); Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]}; @@ -688,7 +832,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L); MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class)); Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]}; - names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs); + names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs); lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names); @@ -705,22 +849,27 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // Prepare auxiliary method handles used during LambdaForm interpreation. // Box arguments and wrap them into Object[]: ValueConversions.array(). MethodType varargsType = type.changeReturnType(Object[].class); - MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount()) - .asType(varargsType); + MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType); // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). MethodHandle unboxResult; - if (type.returnType().isPrimitive()) { - unboxResult = ValueConversions.unbox(type.returnType()); + Class rtype = type.returnType(); + if (rtype.isPrimitive()) { + if (rtype == void.class) { + unboxResult = ValueConversions.ignore(); + } else { + Wrapper w = Wrapper.forPrimitiveType(type.returnType()); + unboxResult = ValueConversions.unboxExact(w); + } } else { - unboxResult = ValueConversions.identity(); + unboxResult = MethodHandles.identity(Object.class); } BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); BoundMethodHandle mh; try { mh = (BoundMethodHandle) - data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher, - (Object) collectArgs, (Object) unboxResult); + data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher, + (Object) collectArgs, (Object) unboxResult); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -758,9 +907,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(Throwable.class.isAssignableFrom(type.parameterType(0))); int arity = type.parameterCount(); if (arity > 1) { - return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1); + MethodHandle mh = throwException(type.dropParameterTypes(1, arity)); + mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity)); + return mh; } - return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2); + return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, false, true); } static Empty throwException(T t) throws T { throw t; } @@ -782,7 +933,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle")); if (!method.getInvocationType().equals(mh.type())) throw new InternalError(method.toString()); - mh = mh.withInternalMemberName(method); + mh = mh.withInternalMemberName(method, false); mh = mh.asVarargsCollector(Object[].class); assert(method.isVarargs()); FAKE_METHOD_HANDLE_INVOKE[idx] = mh; @@ -819,7 +970,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle vamh = prepareForInvoker(mh); // Cache the result of makeInjectedInvoker once per argument class. MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); - return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass); + return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass); } private static MethodHandle makeInjectedInvoker(Class hostClass) { @@ -874,12 +1025,14 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; } // Undo the adapter effect of prepareForInvoker: - private static MethodHandle restoreToType(MethodHandle vamh, MethodType type, - MemberName member, + private static MethodHandle restoreToType(MethodHandle vamh, + MethodHandle original, Class hostClass) { + MethodType type = original.type(); MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount()); + MemberName member = original.internalMemberName(); mh = mh.asType(type); - mh = new WrappedMember(mh, type, member, hostClass); + mh = new WrappedMember(mh, type, member, original.isInvokeSpecial(), hostClass); return mh; } @@ -945,20 +1098,36 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */ - static class WrappedMember extends MethodHandle { + private static final class WrappedMember extends DelegatingMethodHandle { private final MethodHandle target; private final MemberName member; private final Class callerClass; + private final boolean isInvokeSpecial; - private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class callerClass) { - super(type, reinvokerForm(target)); + private WrappedMember(MethodHandle target, MethodType type, + MemberName member, boolean isInvokeSpecial, + Class callerClass) { + super(type, target); this.target = target; this.member = member; this.callerClass = callerClass; + this.isInvokeSpecial = isInvokeSpecial; } @Override - MethodHandle reinvokerTarget() { + MemberName internalMemberName() { + return member; + } + @Override + Class internalCallerClass() { + return callerClass; + } + @Override + boolean isInvokeSpecial() { + return isInvokeSpecial; + } + @Override + protected MethodHandle getTarget() { return target; } @Override @@ -967,28 +1136,355 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // Drop the MemberName if there is any conversion. return asTypeCache = target.asType(newType); } + } + + static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) { + if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial()) + return target; + return new WrappedMember(target, target.type(), member, isInvokeSpecial, null); + } + + /** Intrinsic IDs */ + /*non-public*/ + enum Intrinsic { + SELECT_ALTERNATIVE, + GUARD_WITH_CATCH, + NEW_ARRAY, + ARRAY_LOAD, + ARRAY_STORE, + IDENTITY, + ZERO, + NONE // no intrinsic associated + } + + /** Mark arbitrary method handle as intrinsic. + * InvokerBytecodeGenerator uses this info to produce more efficient bytecode shape. */ + private static final class IntrinsicMethodHandle extends DelegatingMethodHandle { + private final MethodHandle target; + private final Intrinsic intrinsicName; + + IntrinsicMethodHandle(MethodHandle target, Intrinsic intrinsicName) { + super(target.type(), target); + this.target = target; + this.intrinsicName = intrinsicName; + } + @Override - MemberName internalMemberName() { - return member; + protected MethodHandle getTarget() { + return target; } + @Override - Class internalCallerClass() { - return callerClass; + Intrinsic intrinsicName() { + return intrinsicName; } + @Override - boolean isInvokeSpecial() { - return target.isInvokeSpecial(); + public MethodHandle asTypeUncached(MethodType newType) { + // This MH is an alias for target, except for the intrinsic name + // Drop the name if there is any conversion. + return asTypeCache = target.asType(newType); } + @Override - MethodHandle viewAsType(MethodType newType) { - return new WrappedMember(target, newType, member, callerClass); + String internalProperties() { + return super.internalProperties() + + "\n& Intrinsic="+intrinsicName; + } + + @Override + public MethodHandle asCollector(Class arrayType, int arrayLength) { + if (intrinsicName == Intrinsic.IDENTITY) { + MethodType resultType = type().asCollectorType(arrayType, arrayLength); + MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); + return newArray.asType(resultType); + } + return super.asCollector(arrayType, arrayLength); } } - static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) { - if (member.equals(target.internalMemberName())) + static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic intrinsicName) { + if (intrinsicName == target.intrinsicName()) return target; - return new WrappedMember(target, target.type(), member, null); + return new IntrinsicMethodHandle(target, intrinsicName); + } + + static MethodHandle makeIntrinsic(MethodType type, LambdaForm form, Intrinsic intrinsicName) { + return new IntrinsicMethodHandle(SimpleMethodHandle.make(type, form), intrinsicName); + } + + /// Collection of multiple arguments. + + private static MethodHandle findCollector(String name, int nargs, Class rtype, Class... ptypes) { + MethodType type = MethodType.genericMethodType(nargs) + .changeReturnType(rtype) + .insertParameterTypes(0, ptypes); + try { + return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type); + } catch (ReflectiveOperationException ex) { + return null; + } + } + + private static final Object[] NO_ARGS_ARRAY = {}; + private static Object[] makeArray(Object... args) { return args; } + private static Object[] array() { return NO_ARGS_ARRAY; } + private static Object[] array(Object a0) + { return makeArray(a0); } + private static Object[] array(Object a0, Object a1) + { return makeArray(a0, a1); } + private static Object[] array(Object a0, Object a1, Object a2) + { return makeArray(a0, a1, a2); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3) + { return makeArray(a0, a1, a2, a3); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4) + { return makeArray(a0, a1, a2, a3, a4); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) + { return makeArray(a0, a1, a2, a3, a4, a5); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) + { return makeArray(a0, a1, a2, a3, a4, a5, a6); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + private static MethodHandle[] makeArrays() { + ArrayList mhs = new ArrayList<>(); + for (;;) { + MethodHandle mh = findCollector("array", mhs.size(), Object[].class); + if (mh == null) break; + mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); + mhs.add(mh); + } + assert(mhs.size() == 11); // current number of methods + return mhs.toArray(new MethodHandle[MAX_ARITY+1]); + } + private static final MethodHandle[] ARRAYS = makeArrays(); + + // filling versions of the above: + // using Integer len instead of int len and no varargs to avoid bootstrapping problems + private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { + Object[] a = new Object[len]; + fillWithArguments(a, 0, args); + return a; + } + private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { + Object[] a = Arrays.copyOf(example, len); + assert(a.getClass() != Object[].class); + fillWithArguments(a, 0, args); + return a; + } + private static void fillWithArguments(Object[] a, int pos, Object... args) { + System.arraycopy(args, 0, a, pos, args.length); + } + // using Integer pos instead of int pos to avoid bootstrapping problems + private static Object[] fillArray(Integer pos, Object[] a, Object a0) + { fillWithArguments(a, pos, a0); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) + { fillWithArguments(a, pos, a0, a1); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) + { fillWithArguments(a, pos, a0, a1, a2); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) + { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, + Object a4) + { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) + { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) + { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) + { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) + { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) + { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } + private static MethodHandle[] makeFillArrays() { + ArrayList mhs = new ArrayList<>(); + mhs.add(null); // there is no empty fill; at least a0 is required + for (;;) { + MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class); + if (mh == null) break; + mhs.add(mh); + } + assert(mhs.size() == 11); // current number of methods + return mhs.toArray(new MethodHandle[0]); + } + private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); + + private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { + Object a = w.makeArray(boxes.length); + w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); + return a; + } + + /** Return a method handle that takes the indicated number of Object + * arguments and returns an Object array of them, as if for varargs. + */ + static MethodHandle varargsArray(int nargs) { + MethodHandle mh = ARRAYS[nargs]; + if (mh != null) return mh; + mh = findCollector("array", nargs, Object[].class); + if (mh != null) mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); + if (mh != null) return ARRAYS[nargs] = mh; + mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs); + assert(assertCorrectArity(mh, nargs)); + mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); + return ARRAYS[nargs] = mh; } + private static boolean assertCorrectArity(MethodHandle mh, int arity) { + assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; + return true; + } + + // Array identity function (used as Lazy.MH_arrayIdentity). + static T[] identity(T[] x) { + return x; + } + + private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) { + // Build up the result mh as a sequence of fills like this: + // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23)) + // The various fill(_,10*I,___*[J]) are reusable. + int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately + int rightLen = nargs - leftLen; + MethodHandle leftCollector = newArray.bindTo(nargs); + leftCollector = leftCollector.asCollector(Object[].class, leftLen); + MethodHandle mh = finisher; + if (rightLen > 0) { + MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); + if (mh == Lazy.MH_arrayIdentity) + mh = rightFiller; + else + mh = MethodHandles.collectArguments(mh, 0, rightFiller); + } + if (mh == Lazy.MH_arrayIdentity) + mh = leftCollector; + else + mh = MethodHandles.collectArguments(mh, 0, leftCollector); + return mh; + } + + private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); + private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; + /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) + * fills a[L]..a[N-1] with corresponding arguments, + * and then returns a. The value L is a global constant (LEFT_ARGS). + */ + private static MethodHandle fillToRight(int nargs) { + MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; + if (filler != null) return filler; + filler = buildFiller(nargs); + assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); + return FILL_ARRAY_TO_RIGHT[nargs] = filler; + } + private static MethodHandle buildFiller(int nargs) { + if (nargs <= LEFT_ARGS) + return Lazy.MH_arrayIdentity; // no args to fill; return the array unchanged + // we need room for both mh and a in mh.invoke(a, arg*[nargs]) + final int CHUNK = LEFT_ARGS; + int rightLen = nargs % CHUNK; + int midLen = nargs - rightLen; + if (rightLen == 0) { + midLen = nargs - (rightLen = CHUNK); + if (FILL_ARRAY_TO_RIGHT[midLen] == null) { + // build some precursors from left to right + for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) + if (j > LEFT_ARGS) fillToRight(j); + } + } + if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); + assert(rightLen > 0); + MethodHandle midFill = fillToRight(midLen); // recursive fill + MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] + assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); + assert(rightFill.type().parameterCount() == 1 + rightLen); + + // Combine the two fills: + // right(mid(a, x10..x19), x20..x23) + // The final product will look like this: + // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) + if (midLen == LEFT_ARGS) + return rightFill; + else + return MethodHandles.collectArguments(rightFill, 0, midFill); + } + + // Type-polymorphic version of varargs maker. + private static final ClassValue TYPED_COLLECTORS + = new ClassValue() { + @Override + protected MethodHandle[] computeValue(Class type) { + return new MethodHandle[256]; + } + }; + + static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM + + /** Return a method handle that takes the indicated number of + * typed arguments and returns an array of them. + * The type argument is the array type. + */ + static MethodHandle varargsArray(Class arrayType, int nargs) { + Class elemType = arrayType.getComponentType(); + if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); + // FIXME: Need more special casing and caching here. + if (nargs >= MAX_JVM_ARITY/2 - 1) { + int slots = nargs; + final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH + if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive()) + slots *= Wrapper.forPrimitiveType(elemType).stackSlots(); + if (slots > MAX_ARRAY_SLOTS) + throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); + } + if (elemType == Object.class) + return varargsArray(nargs); + // other cases: primitive arrays, subtypes of Object[] + MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); + MethodHandle mh = nargs < cache.length ? cache[nargs] : null; + if (mh != null) return mh; + if (nargs == 0) { + Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0); + mh = MethodHandles.constant(arrayType, example); + } else if (elemType.isPrimitive()) { + MethodHandle builder = Lazy.MH_fillNewArray; + MethodHandle producer = buildArrayProducer(arrayType); + mh = buildVarargsArray(builder, producer, nargs); + } else { + Class objArrayType = arrayType.asSubclass(Object[].class); + Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); + MethodHandle builder = Lazy.MH_fillNewTypedArray.bindTo(example); + MethodHandle producer = Lazy.MH_arrayIdentity; // must be weakly typed + mh = buildVarargsArray(builder, producer, nargs); + } + mh = mh.asType(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType))); + mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); + assert(assertCorrectArity(mh, nargs)); + if (nargs < cache.length) + cache[nargs] = mh; + return mh; + } + + private static MethodHandle buildArrayProducer(Class arrayType) { + Class elemType = arrayType.getComponentType(); + assert(elemType.isPrimitive()); + return Lazy.MH_copyAsPrimitiveArray.bindTo(Wrapper.forPrimitiveType(elemType)); + } } diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java index fd5cac8cd7b1c6ae0d80f0f8034566149def4fa2..0f5169e95e29c3de3b36872508bd413a9929caa5 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -78,7 +78,7 @@ class MethodHandleNatives { // The JVM calls MethodHandleNatives.. Cascade the calls as needed: MethodHandleImpl.initStatics(); -} + } // All compile-time constants go here. // There is an opportunity to check them against the JVM's idea of them. @@ -293,6 +293,17 @@ class MethodHandleNatives { Class caller = (Class)callerObj; String name = nameObj.toString().intern(); MethodType type = (MethodType)typeObj; + if (!TRACE_METHOD_LINKAGE) + return linkCallSiteImpl(caller, bootstrapMethod, name, type, + staticArguments, appendixResult); + return linkCallSiteTracing(caller, bootstrapMethod, name, type, + staticArguments, appendixResult); + } + static MemberName linkCallSiteImpl(Class caller, + MethodHandle bootstrapMethod, + String name, MethodType type, + Object staticArguments, + Object[] appendixResult) { CallSite callSite = CallSite.makeSite(bootstrapMethod, name, type, @@ -306,6 +317,30 @@ class MethodHandleNatives { return Invokers.linkToCallSiteMethod(type); } } + // Tracing logic: + static MemberName linkCallSiteTracing(Class caller, + MethodHandle bootstrapMethod, + String name, MethodType type, + Object staticArguments, + Object[] appendixResult) { + Object bsmReference = bootstrapMethod.internalMemberName(); + if (bsmReference == null) bsmReference = bootstrapMethod; + Object staticArglist = (staticArguments instanceof Object[] ? + java.util.Arrays.asList((Object[]) staticArguments) : + staticArguments); + System.out.println("linkCallSite "+caller.getName()+" "+ + bsmReference+" "+ + name+type+"/"+staticArglist); + try { + MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type, + staticArguments, appendixResult); + System.out.println("linkCallSite => "+res+" + "+appendixResult[0]); + return res; + } catch (Throwable ex) { + System.out.println("linkCallSite => throw "+ex); + throw ex; + } + } /** * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one. diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java index 8d5ee2c53523b147e9ce48ae4e6eeac349a13b17..d549b63254d957ac59e1f184e9e1ad9a7d42c640 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.reflect.misc.ReflectUtil; +import static java.lang.invoke.MethodHandleStatics.*; /** * This class consists exclusively of static methods that help adapt @@ -148,7 +149,7 @@ public class MethodHandleProxies { public static T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) - throw new IllegalArgumentException("not a public interface: "+intfc.getName()); + throw newIllegalArgumentException("not a public interface", intfc.getName()); final MethodHandle mh; if (System.getSecurityManager() != null) { final Class caller = Reflection.getCallerClass(); @@ -165,7 +166,7 @@ public class MethodHandleProxies { } final Method[] methods = getSingleNameMethods(intfc); if (methods == null) - throw new IllegalArgumentException("not a single-method interface: "+intfc.getName()); + throw newIllegalArgumentException("not a single-method interface", intfc.getName()); final MethodHandle[] vaTargets = new MethodHandle[methods.length]; for (int i = 0; i < methods.length; i++) { Method sm = methods[i]; @@ -189,7 +190,7 @@ public class MethodHandleProxies { return getArg(method.getName()); if (isObjectMethod(method)) return callObjectMethod(proxy, method, args); - throw new InternalError("bad proxy method: "+method); + throw newInternalError("bad proxy method: "+method); } }; @@ -240,7 +241,7 @@ public class MethodHandleProxies { return (WrapperInstance) x; } catch (ClassCastException ex) { } - throw new IllegalArgumentException("not a wrapper instance"); + throw newIllegalArgumentException("not a wrapper instance"); } /** diff --git a/src/share/classes/java/lang/invoke/MethodHandleStatics.java b/src/share/classes/java/lang/invoke/MethodHandleStatics.java index 8a8eedfe1bf012b829b1a041b77e955c6bac7fef..c3d9ac12c09f0ce503d03b394b4cf4a2fd48d291 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/src/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -45,16 +45,21 @@ import sun.misc.Unsafe; static final boolean DUMP_CLASS_FILES; static final boolean TRACE_INTERPRETER; static final boolean TRACE_METHOD_LINKAGE; - static final Integer COMPILE_THRESHOLD; + static final boolean USE_LAMBDA_FORM_EDITOR; + static final int COMPILE_THRESHOLD; + static final int PROFILE_LEVEL; + static { - final Object[] values = { false, false, false, false, null }; + final Object[] values = { false, false, false, false, false, null, null }; AccessController.doPrivileged(new PrivilegedAction() { public Void run() { values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"); values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"); values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"); - values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD"); + values[4] = Boolean.getBoolean("java.lang.invoke.MethodHandle.USE_LF_EDITOR"); + values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30); + values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); return null; } }); @@ -62,7 +67,19 @@ import sun.misc.Unsafe; DUMP_CLASS_FILES = (Boolean) values[1]; TRACE_INTERPRETER = (Boolean) values[2]; TRACE_METHOD_LINKAGE = (Boolean) values[3]; - COMPILE_THRESHOLD = (Integer) values[4]; + USE_LAMBDA_FORM_EDITOR = (Boolean) values[4]; + COMPILE_THRESHOLD = (Integer) values[5]; + PROFILE_LEVEL = (Integer) values[6]; + } + + /** Tell if any of the debugging switches are turned on. + * If this is the case, it is reasonable to perform extra checks or save extra information. + */ + /*non-public*/ static boolean debugEnabled() { + return (DEBUG_METHOD_HANDLE_NAMES | + DUMP_CLASS_FILES | + TRACE_INTERPRETER | + TRACE_METHOD_LINKAGE); } /*non-public*/ static String getNameString(MethodHandle target, MethodType type) { @@ -93,6 +110,9 @@ import sun.misc.Unsafe; } // handy shared exception makers (they simplify the common case code) + /*non-public*/ static InternalError newInternalError(String message) { + return new InternalError(message); + } /*non-public*/ static InternalError newInternalError(String message, Throwable cause) { return new InternalError(message, cause); } @@ -114,7 +134,10 @@ import sun.misc.Unsafe; /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) { return new IllegalArgumentException(message(message, obj, obj2)); } + /** Propagate unchecked exceptions and errors, but wrap anything checked and throw that instead. */ /*non-public*/ static Error uncaughtException(Throwable ex) { + if (ex instanceof Error) throw (Error) ex; + if (ex instanceof RuntimeException) throw (RuntimeException) ex; throw newInternalError("uncaught exception", ex); } static Error NYI() { diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java index 09103d534a68dc658aace5704c3a4f74aeb86fe0..68ff317a44ea2cfeb0643cc404edec34a1e06b6e 100644 --- a/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/share/classes/java/lang/invoke/MethodHandles.java @@ -26,8 +26,8 @@ package java.lang.invoke; import java.lang.reflect.*; +import java.util.BitSet; import java.util.List; -import java.util.ArrayList; import java.util.Arrays; import sun.invoke.util.ValueConversions; @@ -37,13 +37,14 @@ import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; +import java.lang.invoke.LambdaForm.BasicType; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; +import static java.lang.invoke.MethodHandleImpl.Intrinsic; import static java.lang.invoke.MethodHandleNatives.Constants.*; import java.util.concurrent.ConcurrentHashMap; -import sun.security.util.SecurityConstants; - /** * This class consists exclusively of static methods that operate on or return * method handles. They fall into several categories: @@ -863,6 +864,8 @@ assertEquals("", (String) MH_newString.invokeExact()); return invoker(type); if ("invokeExact".equals(name)) return exactInvoker(type); + if ("invokeBasic".equals(name)) + return basicInvoker(type); assert(!MemberName.isMethodHandleInvokeName(name)); return null; } @@ -1142,7 +1145,7 @@ return mh1; Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); - return mh.bindReceiver(receiver).setVarargs(method); + return mh.bindArgumentL(0, receiver).setVarargs(method); } /** @@ -1577,7 +1580,7 @@ return mh1; return false; return true; } - private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class caller) throws IllegalAccessException { + private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class caller) throws IllegalAccessException { assert(!method.isStatic()); // receiver type of mh is too wide; narrow to caller if (!method.getDeclaringClass().isAssignableFrom(caller)) { @@ -1586,7 +1589,9 @@ return mh1; MethodType rawType = mh.type(); if (rawType.parameterType(0) == caller) return mh; MethodType narrowType = rawType.changeParameterType(0, caller); - return mh.viewAsType(narrowType); + assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness + assert(mh.viewAsTypeChecks(narrowType, true)); + return mh.copyWith(narrowType, mh.form); } /** Check access and get the requested method. */ @@ -1648,15 +1653,17 @@ return mh1; checkMethod(refKind, refc, method); } - MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); - mh = maybeBindCaller(method, mh, callerClass); - mh = mh.setVarargs(method); + DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method); + MethodHandle mh = dmh; // Optionally narrow the receiver argument to refc using restrictReceiver. if (doRestrict && (refKind == REF_invokeSpecial || (MethodHandleNatives.refKindHasReceiver(refKind) && - restrictProtectedReceiver(method)))) - mh = restrictReceiver(method, mh, lookupClass()); + restrictProtectedReceiver(method)))) { + mh = restrictReceiver(method, dmh, lookupClass()); + } + mh = maybeBindCaller(method, mh, callerClass); + mh = mh.setVarargs(method); return mh; } private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, @@ -1688,12 +1695,12 @@ return mh1; // Optionally check with the security manager; this isn't needed for unreflect* calls. if (checkSecurity) checkSecurityManager(refc, field); - MethodHandle mh = DirectMethodHandle.make(refc, field); + DirectMethodHandle dmh = DirectMethodHandle.make(refc, field); boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) && restrictProtectedReceiver(field)); if (doRestrict) - mh = restrictReceiver(field, mh, lookupClass()); - return mh; + return restrictReceiver(field, dmh, lookupClass()); + return dmh; } /** Check access and get the requested constructor. */ private MethodHandle getDirectConstructor(Class refc, MemberName ctor) throws IllegalAccessException { @@ -1880,7 +1887,8 @@ return invoker; static public MethodHandle spreadInvoker(MethodType type, int leadingArgCount) { if (leadingArgCount < 0 || leadingArgCount > type.parameterCount()) - throw new IllegalArgumentException("bad argument count "+leadingArgCount); + throw newIllegalArgumentException("bad argument count", leadingArgCount); + type = type.asSpreaderType(Object[].class, type.parameterCount() - leadingArgCount); return type.invokers().spreadInvoker(leadingArgCount); } @@ -1960,12 +1968,12 @@ return invoker; */ static public MethodHandle invoker(MethodType type) { - return type.invokers().generalInvoker(); + return type.invokers().genericInvoker(); } static /*non-public*/ MethodHandle basicInvoker(MethodType type) { - return type.form().basicInvoker(); + return type.invokers().basicInvoker(); } /// method handle modification (creation from other method handles) @@ -2019,7 +2027,7 @@ return invoker; if (!target.type().isCastableTo(newType)) { throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType); } - return MethodHandleImpl.makePairwiseConvert(target, newType, 2); + return MethodHandleImpl.makePairwiseConvert(target, newType, false); } /** @@ -2083,12 +2091,165 @@ assert((int)twice.invokeExact(21) == 42); */ public static MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { - reorder = reorder.clone(); - checkReorder(reorder, newType, target.type()); - return target.permuteArguments(newType, reorder); + reorder = reorder.clone(); // get a private copy + MethodType oldType = target.type(); + permuteArgumentChecks(reorder, newType, oldType); + if (USE_LAMBDA_FORM_EDITOR) { + // first detect dropped arguments and handle them separately + int[] originalReorder = reorder; + BoundMethodHandle result = target.rebind(); + LambdaForm form = result.form; + int newArity = newType.parameterCount(); + // Normalize the reordering into a real permutation, + // by removing duplicates and adding dropped elements. + // This somewhat improves lambda form caching, as well + // as simplifying the transform by breaking it up into steps. + for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) { + if (ddIdx > 0) { + // We found a duplicated entry at reorder[ddIdx]. + // Example: (x,y,z)->asList(x,y,z) + // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1) + // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0) + // The starred element corresponds to the argument + // deleted by the dupArgumentForm transform. + int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos]; + boolean killFirst = false; + for (int val; (val = reorder[--dstPos]) != dupVal; ) { + // Set killFirst if the dup is larger than an intervening position. + // This will remove at least one inversion from the permutation. + if (dupVal > val) killFirst = true; + } + if (!killFirst) { + srcPos = dstPos; + dstPos = ddIdx; + } + form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos); + assert (reorder[srcPos] == reorder[dstPos]); + oldType = oldType.dropParameterTypes(dstPos, dstPos + 1); + // contract the reordering by removing the element at dstPos + int tailPos = dstPos + 1; + System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos); + reorder = Arrays.copyOf(reorder, reorder.length - 1); + } else { + int dropVal = ~ddIdx, insPos = 0; + while (insPos < reorder.length && reorder[insPos] < dropVal) { + // Find first element of reorder larger than dropVal. + // This is where we will insert the dropVal. + insPos += 1; + } + Class ptype = newType.parameterType(dropVal); + form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype)); + oldType = oldType.insertParameterTypes(insPos, ptype); + // expand the reordering by inserting an element at insPos + int tailPos = insPos + 1; + reorder = Arrays.copyOf(reorder, reorder.length + 1); + System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos); + reorder[insPos] = dropVal; + } + assert (permuteArgumentChecks(reorder, newType, oldType)); + } + assert (reorder.length == newArity); // a perfect permutation + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + form = form.editor().permuteArgumentsForm(1, reorder); + if (newType == result.type() && form == result.internalForm()) + return result; + return result.copyWith(newType, form); + } else { + // first detect dropped arguments and handle them separately + MethodHandle originalTarget = target; + int newArity = newType.parameterCount(); + for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) { + // dropIdx is missing from reorder; add it in at the end + int oldArity = reorder.length; + target = dropArguments(target, oldArity, newType.parameterType(dropIdx)); + reorder = Arrays.copyOf(reorder, oldArity+1); + reorder[oldArity] = dropIdx; + } + assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + BoundMethodHandle result = target.rebind(); + LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList())); + return result.copyWith(newType, form); + } + } + + /** Return the first value in [0..newArity-1] that is not present in reorder. */ + private static int findFirstDrop(int[] reorder, int newArity) { + final int BIT_LIMIT = 63; // max number of bits in bit mask + if (newArity < BIT_LIMIT) { + long mask = 0; + for (int arg : reorder) { + assert(arg < newArity); + mask |= (1 << arg); + } + if (mask == (1 << newArity) - 1) { + assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); + return -1; + } + // find first zero + long zeroBit = Long.lowestOneBit(~mask); + int zeroPos = Long.numberOfTrailingZeros(zeroBit); + assert(zeroPos < newArity); + return zeroPos; + } + BitSet mask = new BitSet(newArity); + for (int arg : reorder) { + assert(arg < newArity); + mask.set(arg); + } + int zeroPos = mask.nextClearBit(0); + if (zeroPos == newArity) + return -1; + return zeroPos; + } + + /** + * Return an indication of any duplicate or omission in reorder. + * If the reorder contains a duplicate entry, return the index of the second occurrence. + * Otherwise, return ~(n), for the first n in [0..newArity-1] that is not present in reorder. + * Otherwise, return zero. + * If an element not in [0..newArity-1] is encountered, return reorder.length. + */ + private static int findFirstDupOrDrop(int[] reorder, int newArity) { + final int BIT_LIMIT = 63; // max number of bits in bit mask + if (newArity < BIT_LIMIT) { + long mask = 0; + for (int i = 0; i < reorder.length; i++) { + int arg = reorder[i]; + if (arg >= newArity) return reorder.length; + int bit = 1 << arg; + if ((mask & bit) != 0) + return i; // >0 indicates a dup + mask |= bit; + } + if (mask == (1 << newArity) - 1) { + assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); + return 0; + } + // find first zero + long zeroBit = Long.lowestOneBit(~mask); + int zeroPos = Long.numberOfTrailingZeros(zeroBit); + assert(zeroPos < newArity); + return ~zeroPos; + } else { + // same algorithm, different bit set + BitSet mask = new BitSet(newArity); + for (int i = 0; i < reorder.length; i++) { + int arg = reorder[i]; + if (arg >= newArity) return reorder.length; + if (mask.get(arg)) + return i; // >0 indicates a dup + mask.set(arg); + } + int zeroPos = mask.nextClearBit(0); + if (zeroPos == newArity) { + return 0; + } + return ~zeroPos; + } } - private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) { + private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) { if (newType.returnType() != oldType.returnType()) throw newIllegalArgumentException("return types do not match", oldType, newType); @@ -2106,7 +2267,7 @@ assert((int)twice.invokeExact(21) == 42); throw newIllegalArgumentException("parameter types do not match after reorder", oldType, newType); } - if (!bad) return; + if (!bad) return true; } throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder)); } @@ -2132,9 +2293,14 @@ assert((int)twice.invokeExact(21) == 42); if (type == void.class) throw newIllegalArgumentException("void type"); Wrapper w = Wrapper.forPrimitiveType(type); - return insertArguments(identity(type), 0, w.convert(value, type)); + value = w.convert(value, type); + if (w.zero().equals(value)) + return zero(w, type); + return insertArguments(identity(type), 0, value); } else { - return identity(type).bindTo(type.cast(value)); + if (value == null) + return zero(Wrapper.OBJECT, type); + return identity(type).bindTo(value); } } @@ -2147,14 +2313,48 @@ assert((int)twice.invokeExact(21) == 42); */ public static MethodHandle identity(Class type) { - if (type == void.class) - throw newIllegalArgumentException("void type"); - else if (type == Object.class) - return ValueConversions.identity(); - else if (type.isPrimitive()) - return ValueConversions.identity(Wrapper.forPrimitiveType(type)); - else - return MethodHandleImpl.makeReferenceIdentity(type); + Wrapper btw = (type.isPrimitive() ? Wrapper.forPrimitiveType(type) : Wrapper.OBJECT); + int pos = btw.ordinal(); + MethodHandle ident = IDENTITY_MHS[pos]; + if (ident == null) { + ident = setCachedMethodHandle(IDENTITY_MHS, pos, makeIdentity(btw.primitiveType())); + } + if (ident.type().returnType() == type) + return ident; + // something like identity(Foo.class); do not bother to intern these + assert(btw == Wrapper.OBJECT); + return makeIdentity(type); + } + private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length]; + private static MethodHandle makeIdentity(Class ptype) { + MethodType mtype = MethodType.methodType(ptype, ptype); + LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype)); + return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY); + } + + private static MethodHandle zero(Wrapper btw, Class rtype) { + int pos = btw.ordinal(); + MethodHandle zero = ZERO_MHS[pos]; + if (zero == null) { + zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType())); + } + if (zero.type().returnType() == rtype) + return zero; + assert(btw == Wrapper.OBJECT); + return makeZero(rtype); + } + private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length]; + private static MethodHandle makeZero(Class rtype) { + MethodType mtype = MethodType.methodType(rtype); + LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype)); + return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO); + } + + synchronized private static MethodHandle setCachedMethodHandle(MethodHandle[] cache, int pos, MethodHandle value) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = cache[pos]; + if (prev != null) return prev; + return cache[pos] = value; } /** @@ -2190,40 +2390,47 @@ assert((int)twice.invokeExact(21) == 42); public static MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { int insCount = values.length; - MethodType oldType = target.type(); - int outargs = oldType.parameterCount(); - int inargs = outargs - insCount; - if (inargs < 0) - throw newIllegalArgumentException("too many values to insert"); - if (pos < 0 || pos > inargs) - throw newIllegalArgumentException("no argument type to append"); - MethodHandle result = target; + Class[] ptypes = insertArgumentsChecks(target, insCount, pos); + if (insCount == 0) return target; + BoundMethodHandle result = target.rebind(); for (int i = 0; i < insCount; i++) { Object value = values[i]; - Class ptype = oldType.parameterType(pos+i); + Class ptype = ptypes[pos+i]; if (ptype.isPrimitive()) { - char btype = 'I'; - Wrapper w = Wrapper.forPrimitiveType(ptype); - switch (w) { - case LONG: btype = 'J'; break; - case FLOAT: btype = 'F'; break; - case DOUBLE: btype = 'D'; break; - } - // perform unboxing and/or primitive conversion - value = w.convert(value, ptype); - result = result.bindArgument(pos, btype, value); - continue; - } - value = ptype.cast(value); // throw CCE if needed - if (pos == 0) { - result = result.bindReceiver(value); + result = insertArgumentPrimitive(result, pos, ptype, value); } else { - result = result.bindArgument(pos, 'L', value); + value = ptype.cast(value); // throw CCE if needed + result = result.bindArgumentL(pos, value); } } return result; } + private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos, + Class ptype, Object value) { + Wrapper w = Wrapper.forPrimitiveType(ptype); + // perform unboxing and/or primitive conversion + value = w.convert(value, ptype); + switch (w) { + case INT: return result.bindArgumentI(pos, (int)value); + case LONG: return result.bindArgumentJ(pos, (long)value); + case FLOAT: return result.bindArgumentF(pos, (float)value); + case DOUBLE: return result.bindArgumentD(pos, (double)value); + default: return result.bindArgumentI(pos, ValueConversions.widenSubword(value)); + } + } + + private static Class[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException { + MethodType oldType = target.type(); + int outargs = oldType.parameterCount(); + int inargs = outargs - insCount; + if (inargs < 0) + throw newIllegalArgumentException("too many values to insert"); + if (pos < 0 || pos > inargs) + throw newIllegalArgumentException("no argument type to append"); + return oldType.ptypes(); + } + /** * Produces a method handle which will discard some dummy arguments * before calling some other specified target method handle. @@ -2269,18 +2476,33 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); public static MethodHandle dropArguments(MethodHandle target, int pos, List> valueTypes) { MethodType oldType = target.type(); // get NPE + int dropped = dropArgumentChecks(oldType, pos, valueTypes); + if (dropped == 0) return target; + BoundMethodHandle result = target.rebind(); + LambdaForm lform = result.form; + if (USE_LAMBDA_FORM_EDITOR) { + int insertFormArg = 1 + pos; + for (Class ptype : valueTypes) { + lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype)); + } + } else { + lform = lform.addArguments(pos, valueTypes); + } + MethodType newType = oldType.insertParameterTypes(pos, valueTypes); + result = result.copyWith(newType, lform); + return result; + } + + private static int dropArgumentChecks(MethodType oldType, int pos, List> valueTypes) { int dropped = valueTypes.size(); MethodType.checkSlotCount(dropped); - if (dropped == 0) return target; int outargs = oldType.parameterCount(); int inargs = outargs + dropped; - if (pos < 0 || pos >= inargs) - throw newIllegalArgumentException("no argument type to remove"); - ArrayList> ptypes = new ArrayList<>(oldType.parameterList()); - ptypes.addAll(pos, valueTypes); - if (ptypes.size() != inargs) throw newIllegalArgumentException("valueTypes"); - MethodType newType = MethodType.methodType(oldType.returnType(), ptypes); - return target.dropArguments(newType, pos, dropped); + if (pos < 0 || pos > outargs) + throw newIllegalArgumentException("no argument type to remove" + + Arrays.asList(oldType, pos, valueTypes, inargs, outargs) + ); + return dropped; } /** @@ -2402,32 +2624,47 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY */ public static MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { - MethodType targetType = target.type(); + filterArgumentsCheckArity(target, pos, filters); MethodHandle adapter = target; - MethodType adapterType = null; - assert((adapterType = targetType) != null); - int maxPos = targetType.parameterCount(); - if (pos + filters.length > maxPos) - throw newIllegalArgumentException("too many filters"); int curPos = pos-1; // pre-incremented for (MethodHandle filter : filters) { curPos += 1; if (filter == null) continue; // ignore null elements of filters adapter = filterArgument(adapter, curPos, filter); - assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null); } - assert(adapterType.equals(adapter.type())); return adapter; } /*non-public*/ static MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) { + filterArgumentChecks(target, pos, filter); + if (USE_LAMBDA_FORM_EDITOR) { + MethodType targetType = target.type(); + MethodType filterType = filter.type(); + BoundMethodHandle result = target.rebind(); + Class newParamType = filterType.parameterType(0); + LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType)); + MethodType newType = targetType.changeParameterType(pos, newParamType); + result = result.copyWithExtendL(newType, lform, filter); + return result; + } else { + return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); + } + } + + private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) { + MethodType targetType = target.type(); + int maxPos = targetType.parameterCount(); + if (pos + filters.length > maxPos) + throw newIllegalArgumentException("too many filters"); + } + + private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException { MethodType targetType = target.type(); MethodType filterType = filter.type(); if (filterType.parameterCount() != 1 || filterType.returnType() != targetType.parameterType(pos)) throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); } /** @@ -2538,12 +2775,36 @@ assertEquals("[top, [[up, down, strange], charm], bottom]", */ public static MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) { + MethodType newType = collectArgumentsChecks(target, pos, filter); + if (USE_LAMBDA_FORM_EDITOR) { + MethodType collectorType = filter.type(); + BoundMethodHandle result = target.rebind(); + LambdaForm lform; + if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) { + lform = result.editor().collectArgumentArrayForm(1 + pos, filter); + if (lform != null) { + return result.copyWith(newType, lform); + } + } + lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType()); + return result.copyWithExtendL(newType, lform, filter); + } else { + return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); + } + } + + private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException { MethodType targetType = target.type(); MethodType filterType = filter.type(); - if (filterType.returnType() != void.class && - filterType.returnType() != targetType.parameterType(pos)) + Class rtype = filterType.returnType(); + List> filterArgs = filterType.parameterList(); + if (rtype == void.class) { + return targetType.insertParameterTypes(pos, filterArgs); + } + if (rtype != targetType.parameterType(pos)) { throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); + } + return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs); } /** @@ -2607,15 +2868,26 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { MethodType targetType = target.type(); MethodType filterType = filter.type(); + filterReturnValueChecks(targetType, filterType); + if (USE_LAMBDA_FORM_EDITOR) { + BoundMethodHandle result = target.rebind(); + BasicType rtype = BasicType.basicType(filterType.returnType()); + LambdaForm lform = result.editor().filterReturnForm(rtype, false); + MethodType newType = targetType.changeReturnType(filterType.returnType()); + result = result.copyWithExtendL(newType, lform, filter); + return result; + } else { + return MethodHandleImpl.makeCollectArguments(filter, target, 0, false); + } + } + + private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException { Class rtype = targetType.returnType(); int filterValues = filterType.parameterCount(); if (filterValues == 0 ? (rtype != void.class) : (rtype != filterType.parameterType(0))) - throw newIllegalArgumentException("target and filter types do not match", target, filter); - // result = fold( lambda(retval, arg...) { filter(retval) }, - // lambda( arg...) { target(arg...) } ) - return MethodHandleImpl.makeCollectArguments(filter, target, 0, false); + throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); } /** @@ -2696,24 +2968,40 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); */ public static MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) { - int pos = 0; + int foldPos = 0; MethodType targetType = target.type(); MethodType combinerType = combiner.type(); - int foldPos = pos; - int foldArgs = combinerType.parameterCount(); - int foldVals = combinerType.returnType() == void.class ? 0 : 1; + Class rtype = foldArgumentChecks(foldPos, targetType, combinerType); + if (USE_LAMBDA_FORM_EDITOR) { + BoundMethodHandle result = target.rebind(); + boolean dropResult = (rtype == void.class); + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType()); + MethodType newType = targetType; + if (!dropResult) + newType = newType.dropParameterTypes(foldPos, foldPos + 1); + result = result.copyWithExtendL(newType, lform, combiner); + return result; + } else { + return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true); + } + } + + private static Class foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) { + int foldArgs = combinerType.parameterCount(); + Class rtype = combinerType.returnType(); + int foldVals = rtype == void.class ? 0 : 1; int afterInsertPos = foldPos + foldVals; boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs); if (ok && !(combinerType.parameterList() .equals(targetType.parameterList().subList(afterInsertPos, afterInsertPos + foldArgs)))) ok = false; - if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0))) + if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0)) ok = false; if (!ok) throw misMatchedTypes("target and combiner types", targetType, combinerType); - MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos); - return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true); + return rtype; } /** diff --git a/src/share/classes/java/lang/invoke/MethodType.java b/src/share/classes/java/lang/invoke/MethodType.java index 08c17d789f4cd3aa90b3a4dc62479f46dff2c6de..077126e73a0e31a0ccc31ccfb40be5b7bc5c40d4 100644 --- a/src/share/classes/java/lang/invoke/MethodType.java +++ b/src/share/classes/java/lang/invoke/MethodType.java @@ -466,6 +466,75 @@ class MethodType implements java.io.Serializable { return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert); } + /** Replace the last arrayLength parameter types with the component type of arrayType. + * @param arrayType any array type + * @param arrayLength the number of parameter types to change + * @return the resulting type + */ + /*non-public*/ MethodType asSpreaderType(Class arrayType, int arrayLength) { + assert(parameterCount() >= arrayLength); + int spreadPos = ptypes.length - arrayLength; + if (arrayLength == 0) return this; // nothing to change + if (arrayType == Object[].class) { + if (isGeneric()) return this; // nothing to change + if (spreadPos == 0) { + // no leading arguments to preserve; go generic + MethodType res = genericMethodType(arrayLength); + if (rtype != Object.class) { + res = res.changeReturnType(rtype); + } + return res; + } + } + Class elemType = arrayType.getComponentType(); + assert(elemType != null); + for (int i = spreadPos; i < ptypes.length; i++) { + if (ptypes[i] != elemType) { + Class[] fixedPtypes = ptypes.clone(); + Arrays.fill(fixedPtypes, i, ptypes.length, elemType); + return methodType(rtype, fixedPtypes); + } + } + return this; // arguments check out; no change + } + + /** Return the leading parameter type, which must exist and be a reference. + * @return the leading parameter type, after error checks + */ + /*non-public*/ Class leadingReferenceParameter() { + Class ptype; + if (ptypes.length == 0 || + (ptype = ptypes[0]).isPrimitive()) + throw newIllegalArgumentException("no leading reference parameter"); + return ptype; + } + + /** Delete the last parameter type and replace it with arrayLength copies of the component type of arrayType. + * @param arrayType any array type + * @param arrayLength the number of parameter types to insert + * @return the resulting type + */ + /*non-public*/ MethodType asCollectorType(Class arrayType, int arrayLength) { + assert(parameterCount() >= 1); + assert(lastParameterType().isAssignableFrom(arrayType)); + MethodType res; + if (arrayType == Object[].class) { + res = genericMethodType(arrayLength); + if (rtype != Object.class) { + res = res.changeReturnType(rtype); + } + } else { + Class elemType = arrayType.getComponentType(); + assert(elemType != null); + res = methodType(rtype, Collections.nCopies(arrayLength, elemType)); + } + if (ptypes.length == 1) { + return res; + } else { + return res.insertParameterTypes(0, parameterList().subList(0, ptypes.length-1)); + } + } + /** * Finds or creates a method type with some parameter types omitted. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. @@ -573,6 +642,10 @@ class MethodType implements java.io.Serializable { return genericMethodType(parameterCount()); } + /*non-public*/ boolean isGeneric() { + return this == erase() && !hasPrimitives(); + } + /** * Converts all primitive types to their corresponding wrapper types. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. @@ -728,44 +801,114 @@ class MethodType implements java.io.Serializable { return sb.toString(); } - + /** True if the old return type can always be viewed (w/o casting) under new return type, + * and the new parameters can be viewed (w/o casting) under the old parameter types. + */ /*non-public*/ - boolean isViewableAs(MethodType newType) { - if (!VerifyType.isNullConversion(returnType(), newType.returnType())) + boolean isViewableAs(MethodType newType, boolean keepInterfaces) { + if (!VerifyType.isNullConversion(returnType(), newType.returnType(), keepInterfaces)) return false; + return parametersAreViewableAs(newType, keepInterfaces); + } + /** True if the new parameters can be viewed (w/o casting) under the old parameter types. */ + /*non-public*/ + boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) { + if (form == newType.form && form.erasedType == this) + return true; // my reference parameters are all Object + if (ptypes == newType.ptypes) + return true; int argc = parameterCount(); if (argc != newType.parameterCount()) return false; for (int i = 0; i < argc; i++) { - if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i))) + if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), keepInterfaces)) return false; } return true; } /*non-public*/ boolean isCastableTo(MethodType newType) { + MethodTypeForm oldForm = this.form(); + MethodTypeForm newForm = newType.form(); + if (oldForm == newForm) + // same parameter count, same primitive/object mix + return true; int argc = parameterCount(); if (argc != newType.parameterCount()) return false; - return true; + // Corner case: boxing (primitive-to-reference) must have a plausible target type + // Therefore, we may have to return false for a boxing operation. + if (!canCast(returnType(), newType.returnType())) + return false; + if (newForm.primitiveParameterCount() == 0) + return true; // no primitive sources to mess things up + if (oldForm.erasedType == this) + return true; // no funny target references to mess things up + return canCastParameters(newType.ptypes, ptypes); } /*non-public*/ boolean isConvertibleTo(MethodType newType) { + MethodTypeForm oldForm = this.form(); + MethodTypeForm newForm = newType.form(); + if (oldForm == newForm) + // same parameter count, same primitive/object mix + return true; if (!canConvert(returnType(), newType.returnType())) return false; - int argc = parameterCount(); - if (argc != newType.parameterCount()) + Class[] srcTypes = newType.ptypes; + Class[] dstTypes = ptypes; + if (srcTypes == dstTypes) + return true; + int argc; + if ((argc = srcTypes.length) != dstTypes.length) return false; - for (int i = 0; i < argc; i++) { - if (!canConvert(newType.parameterType(i), parameterType(i))) + if (argc <= 1) { + if (argc == 1 && !canConvert(srcTypes[0], dstTypes[0])) return false; + return true; + } + if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) || + (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) { + // Somewhat complicated test to avoid a loop of 2 or more trips. + // If either type has only Object parameters, we know we can convert. + assert(canConvertParameters(srcTypes, dstTypes)); + return true; + } + return canConvertParameters(srcTypes, dstTypes); + } + + private boolean canCastParameters(Class[] srcTypes, Class[] dstTypes) { + for (int i = 0; i < srcTypes.length; i++) { + if (!canCast(srcTypes[i], dstTypes[i])) { + return false; + } + } + return true; + } + + private boolean canConvertParameters(Class[] srcTypes, Class[] dstTypes) { + for (int i = 0; i < srcTypes.length; i++) { + if (!canConvert(srcTypes[i], dstTypes[i])) { + return false; + } } return true; } + + private static boolean canCast(Class src, Class dst) { + if (src.isPrimitive() && !dst.isPrimitive()) { + if (dst == Object.class || dst.isInterface()) return true; + // Here is the corner case that is not castable. Example: int -> String + Wrapper sw = Wrapper.forPrimitiveType(src); + return dst.isAssignableFrom(sw.wrapperType()); + } + return true; + } + /*non-public*/ static boolean canConvert(Class src, Class dst) { // short-circuit a few cases: - if (src == dst || dst == Object.class) return true; + if (src == dst || src == Object.class || dst == Object.class) return true; // the remainder of this logic is documented in MethodHandle.asType if (src.isPrimitive()) { // can force void to an explicit null, a la reflect.Method.invoke @@ -907,7 +1050,7 @@ class MethodType implements java.io.Serializable { if (!descriptor.startsWith("(") || // also generates NPE if needed descriptor.indexOf(')') < 0 || descriptor.indexOf('.') >= 0) - throw new IllegalArgumentException("not a method descriptor: "+descriptor); + throw newIllegalArgumentException("not a method descriptor: "+descriptor); List> types = BytecodeDescriptor.parseMethod(descriptor, loader); Class rtype = types.remove(types.size() - 1); checkSlotCount(types.size()); diff --git a/src/share/classes/java/lang/invoke/MethodTypeForm.java b/src/share/classes/java/lang/invoke/MethodTypeForm.java index d34a2998caba9cd8cc319e60ffe8501e9bcf98c5..43e85589410e91734bd8058af9d909604a572ef9 100644 --- a/src/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/src/share/classes/java/lang/invoke/MethodTypeForm.java @@ -47,15 +47,17 @@ final class MethodTypeForm { final int[] argToSlotTable, slotToArgTable; final long argCounts; // packed slot & value counts final long primCounts; // packed prim & double counts - final int vmslots; // total number of parameter slots final MethodType erasedType; // the canonical erasure final MethodType basicType; // the canonical erasure, with primitives simplified // Cached adapter information: - @Stable String typeString; // argument type signature characters - @Stable MethodHandle genericInvoker; // JVM hook for inexact invoke - @Stable MethodHandle basicInvoker; // cached instance of MH.invokeBasic - @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction + @Stable final MethodHandle[] methodHandles; + // Indexes into methodHandles: + static final int + MH_BASIC_INV = 0, // cached instance of MH.invokeBasic + MH_NF_INV = 1, // cached helper for LF.NamedFunction + MH_UNINIT_CS = 2, // uninitialized call site + MH_LIMIT = 3; // Cached lambda form information, for basic types only: final @Stable LambdaForm[] lambdaForms; @@ -68,26 +70,55 @@ final class MethodTypeForm { LF_INVINTERFACE = 4, LF_INVSTATIC_INIT = 5, // DMH invokeStatic with barrier LF_INTERPRET = 6, // LF interpreter - LF_COUNTER = 7, // CMH wrapper - LF_REINVOKE = 8, // other wrapper - LF_EX_LINKER = 9, // invokeExact_MT - LF_EX_INVOKER = 10, // invokeExact MH - LF_GEN_LINKER = 11, - LF_GEN_INVOKER = 12, + LF_REBIND = 7, // BoundMethodHandle + LF_DELEGATE = 8, // DelegatingMethodHandle + LF_EX_LINKER = 9, // invokeExact_MT (for invokehandle) + LF_EX_INVOKER = 10, // MHs.invokeExact + LF_GEN_LINKER = 11, // generic invoke_MT (for invokehandle) + LF_GEN_INVOKER = 12, // generic MHs.invoke LF_CS_LINKER = 13, // linkToCallSite_CS LF_MH_LINKER = 14, // linkToCallSite_MH - LF_GWC = 15, - LF_LIMIT = 16; + LF_GWC = 15, // guardWithCatch (catchException) + LF_GWT = 16, // guardWithTest + LF_LIMIT = 17; + /** Return the type corresponding uniquely (1-1) to this MT-form. + * It might have any primitive returns or arguments, but will have no references except Object. + */ public MethodType erasedType() { return erasedType; } + /** Return the basic type derived from the erased type of this MT-form. + * A basic type is erased (all references Object) and also has all primitive + * types (except int, long, float, double, void) normalized to int. + * Such basic types correspond to low-level JVM calling sequences. + */ public MethodType basicType() { return basicType; } + private boolean assertIsBasicType() { + // primitives must be flattened also + assert(erasedType == basicType) + : "erasedType: " + erasedType + " != basicType: " + basicType; + return true; + } + + public MethodHandle cachedMethodHandle(int which) { + assert(assertIsBasicType()); + return methodHandles[which]; + } + + synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = methodHandles[which]; + if (prev != null) return prev; + return methodHandles[which] = mh; + } + public LambdaForm cachedLambdaForm(int which) { + assert(assertIsBasicType()); return lambdaForms[which]; } @@ -98,28 +129,6 @@ final class MethodTypeForm { return lambdaForms[which] = form; } - public MethodHandle basicInvoker() { - assert(erasedType == basicType) : "erasedType: " + erasedType + " != basicType: " + basicType; // primitives must be flattened also - MethodHandle invoker = basicInvoker; - if (invoker != null) return invoker; - invoker = DirectMethodHandle.make(invokeBasicMethod(basicType)); - basicInvoker = invoker; - return invoker; - } - - // This next one is called from LambdaForm.NamedFunction.. - /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) { - assert(basicType == basicType.basicType()); - try { - // Do approximately the same as this public API call: - // Lookup.findVirtual(MethodHandle.class, name, type); - // But bypass access and corner case checks, since we know exactly what we need. - return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType); - } catch (ReflectiveOperationException ex) { - throw newInternalError("JVM cannot find invoker for "+basicType, ex); - } - } - /** * Build an MTF for a given type, which must have all references erased to Object. * This MTF will stand for that type and all un-erased variations. @@ -172,6 +181,16 @@ final class MethodTypeForm { this.basicType = erasedType; } else { this.basicType = MethodType.makeImpl(bt, bpts, true); + // fill in rest of data from the basic type: + MethodTypeForm that = this.basicType.form(); + assert(this != that); + this.primCounts = that.primCounts; + this.argCounts = that.argCounts; + this.argToSlotTable = that.argToSlotTable; + this.slotToArgTable = that.slotToArgTable; + this.methodHandles = null; + this.lambdaForms = null; + return; } if (lac != 0) { int slot = ptypeCount + lac; @@ -187,10 +206,14 @@ final class MethodTypeForm { argToSlotTab[1+i] = slot; } assert(slot == 0); // filled the table - } - this.primCounts = pack(lrc, prc, lac, pac); - this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount); - if (slotToArgTab == null) { + } else if (pac != 0) { + // have primitives but no long primitives; share slot counts with generic + assert(ptypeCount == pslotCount); + MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form(); + assert(this != that); + slotToArgTab = that.slotToArgTable; + argToSlotTab = that.argToSlotTable; + } else { int slot = ptypeCount; // first arg is deepest in stack slotToArgTab = new int[slot+1]; argToSlotTab = new int[1+ptypeCount]; @@ -201,19 +224,17 @@ final class MethodTypeForm { argToSlotTab[1+i] = slot; } } + this.primCounts = pack(lrc, prc, lac, pac); + this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount); this.argToSlotTable = argToSlotTab; this.slotToArgTable = slotToArgTab; if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments"); - // send a few bits down to the JVM: - this.vmslots = parameterSlotCount(); - - if (basicType == erasedType) { - lambdaForms = new LambdaForm[LF_LIMIT]; - } else { - lambdaForms = null; // could be basicType.form().lambdaForms; - } + // Initialize caches, but only for basic types + assert(basicType == erasedType); + this.lambdaForms = new LambdaForm[LF_LIMIT]; + this.methodHandles = new MethodHandle[MH_LIMIT]; } private static long pack(int a, int b, int c, int d) { @@ -300,7 +321,7 @@ final class MethodTypeForm { */ public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) { Class[] ptypes = mt.ptypes(); - Class[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs); + Class[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs); Class rtype = mt.returnType(); Class rtc = MethodTypeForm.canonicalize(rtype, howRet); if (ptc == null && rtc == null) { @@ -368,7 +389,7 @@ final class MethodTypeForm { /** Canonicalize each param type in the given array. * Return null if all types are already canonicalized. */ - static Class[] canonicalizes(Class[] ts, int how) { + static Class[] canonicalizeAll(Class[] ts, int how) { Class[] cs = null; for (int imax = ts.length, i = 0; i < imax; i++) { Class c = canonicalize(ts[i], how); diff --git a/src/share/classes/java/lang/invoke/SimpleMethodHandle.java b/src/share/classes/java/lang/invoke/SimpleMethodHandle.java index c2d8e583a88111979f0b3844218f29b0ef7e9008..c9e37a81ff431102663ef43ac0f495dce5d7dd08 100644 --- a/src/share/classes/java/lang/invoke/SimpleMethodHandle.java +++ b/src/share/classes/java/lang/invoke/SimpleMethodHandle.java @@ -25,46 +25,77 @@ package java.lang.invoke; -import static java.lang.invoke.LambdaForm.*; -import static java.lang.invoke.MethodHandleNatives.Constants.*; -import java.util.logging.Level; -import java.util.logging.Logger; +import static java.lang.invoke.LambdaForm.BasicType.*; +import static java.lang.invoke.MethodHandleStatics.*; /** * A method handle whose behavior is determined only by its LambdaForm. * @author jrose */ -final class SimpleMethodHandle extends MethodHandle { +final class SimpleMethodHandle extends BoundMethodHandle { private SimpleMethodHandle(MethodType type, LambdaForm form) { super(type, form); } - /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) { + /*non-public*/ static BoundMethodHandle make(MethodType type, LambdaForm form) { return new SimpleMethodHandle(type, form); } - @Override - MethodHandle bindArgument(int pos, char basicType, Object value) { - MethodType type2 = type().dropParameterTypes(pos, pos+1); - LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY); - return BoundMethodHandle.bindSingle(type2, form2, basicType, value); + /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY; + + /*non-public*/ public SpeciesData speciesData() { + return SPECIES_DATA; } @Override - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - LambdaForm newForm = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops)); - return new SimpleMethodHandle(srcType, newForm); + /*non-public*/ BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) { + return make(mt, lf); } @Override - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - LambdaForm form2 = internalForm().permuteArguments(1, reorder, basicTypes(newType.parameterList())); - return new SimpleMethodHandle(newType, form2); + String internalProperties() { + return "\n& Class="+getClass().getSimpleName(); } @Override - MethodHandle copyWith(MethodType mt, LambdaForm lf) { - return new SimpleMethodHandle(mt, lf); + /*non-public*/ public int fieldCount() { + return 0; } + @Override + /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { + return BoundMethodHandle.bindSingle(mt, lf, narg); // Use known fast path. + } + @Override + /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + } + @Override + /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + } + @Override + /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + } + @Override + /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + } } diff --git a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java index aecbeb6d084566a196631e9551ec317f87a71f4c..6bfbf6b601a96ecc0fe9e4cbb565e15e7bbd1252 100644 --- a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java +++ b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java @@ -158,19 +158,19 @@ class TypeConvertingMethodAdapter extends MethodVisitor { visitMethodInsn(Opcodes.INVOKESTATIC, wrapperName(w), NAME_BOX_METHOD, - boxingDescriptor(w)); + boxingDescriptor(w), false); } /** * Convert types by unboxing. The source type is known to be a primitive wrapper. - * @param ws A primitive wrapper corresponding to wrapped reference source type + * @param sname A primitive wrapper corresponding to wrapped reference source type * @param wt A primitive wrapper being converted to */ void unbox(String sname, Wrapper wt) { visitMethodInsn(Opcodes.INVOKEVIRTUAL, sname, unboxMethod(wt), - unboxingDescriptor(wt)); + unboxingDescriptor(wt), false); } private String descriptorToName(String desc) { diff --git a/src/share/classes/java/lang/reflect/AccessibleObject.java b/src/share/classes/java/lang/reflect/AccessibleObject.java index f98aed5db25e3f29e19df4e8d2314fbd92a719a9..0bf5e0eea417d12b264bb493258acecb535917b0 100644 --- a/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,16 +129,24 @@ public class AccessibleObject implements AnnotatedElement { setAccessible0(this, flag); } - /* Check that you aren't exposing java.lang.Class.. */ + /* Check that you aren't exposing java.lang.Class. or sensitive + fields in java.lang.Class. */ private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException { if (obj instanceof Constructor && flag == true) { Constructor c = (Constructor)obj; if (c.getDeclaringClass() == Class.class) { - throw new SecurityException("Can not make a java.lang.Class" + + throw new SecurityException("Cannot make a java.lang.Class" + " constructor accessible"); } + } else if (obj instanceof Field && flag == true) { + Field f = (Field)obj; + if (f.getDeclaringClass() == Class.class && + f.getName().equals("classLoader")) { + throw new SecurityException("Cannot make java.lang.Class.classLoader" + + " accessible"); + } } obj.override = flag; } diff --git a/src/share/classes/java/lang/reflect/Constructor.java b/src/share/classes/java/lang/reflect/Constructor.java index 7a85545752fda0e7e445e6cfb5974d13b894b67f..16671eba2a2abc85e833f741f272596e8e517862 100644 --- a/src/share/classes/java/lang/reflect/Constructor.java +++ b/src/share/classes/java/lang/reflect/Constructor.java @@ -94,8 +94,19 @@ public final class Constructor extends Executable { // For sharing of ConstructorAccessors. This branching structure // is currently only two levels deep (i.e., one root Constructor // and potentially many Constructor objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. private Constructor root; + /** + * Used by Excecutable for annotation sharing. + */ + @Override + Executable getRoot() { + return root; + } + /** * Package-private constructor used by ReflectAccess to enable * instantiation of these objects in Java code from the java.lang @@ -132,6 +143,9 @@ public final class Constructor extends Executable { // which implicitly requires that new java.lang.reflect // objects be fabricated for each reflective call on Class // objects.) + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root Constructor"); + Constructor res = new Constructor<>(clazz, parameterTypes, exceptionTypes, modifiers, slot, diff --git a/src/share/classes/java/lang/reflect/Executable.java b/src/share/classes/java/lang/reflect/Executable.java index b4e88748cb6baf7c287e394e6ea59c99bc50413b..70d87d8f16967297ea9ab0252e666b22e7e74bf7 100644 --- a/src/share/classes/java/lang/reflect/Executable.java +++ b/src/share/classes/java/lang/reflect/Executable.java @@ -52,6 +52,11 @@ public abstract class Executable extends AccessibleObject */ abstract byte[] getAnnotationBytes(); + /** + * Accessor method to allow code sharing + */ + abstract Executable getRoot(); + /** * Does the Executable have generic information. */ @@ -543,11 +548,16 @@ public abstract class Executable extends AccessibleObject private synchronized Map, Annotation> declaredAnnotations() { if (declaredAnnotations == null) { - declaredAnnotations = AnnotationParser.parseAnnotations( - getAnnotationBytes(), - sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - getDeclaringClass()); + Executable root = getRoot(); + if (root != null) { + declaredAnnotations = root.declaredAnnotations(); + } else { + declaredAnnotations = AnnotationParser.parseAnnotations( + getAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + getDeclaringClass()); + } } return declaredAnnotations; } diff --git a/src/share/classes/java/lang/reflect/Field.java b/src/share/classes/java/lang/reflect/Field.java index 6e243bc82b69761e210009f598d357f5cfc209dd..bb23b22dc94d49f599dadc36056b18057b81ba14 100644 --- a/src/share/classes/java/lang/reflect/Field.java +++ b/src/share/classes/java/lang/reflect/Field.java @@ -81,6 +81,9 @@ class Field extends AccessibleObject implements Member { // For sharing of FieldAccessors. This branching structure is // currently only two levels deep (i.e., one root Field and // potentially many Field objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. private Field root; // Generics infrastructure @@ -141,6 +144,9 @@ class Field extends AccessibleObject implements Member { // which implicitly requires that new java.lang.reflect // objects be fabricated for each reflective call on Class // objects.) + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root Field"); + Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations); res.root = this; // Might as well eagerly propagate this if already present @@ -1137,10 +1143,15 @@ class Field extends AccessibleObject implements Member { private synchronized Map, Annotation> declaredAnnotations() { if (declaredAnnotations == null) { - declaredAnnotations = AnnotationParser.parseAnnotations( - annotations, sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - getDeclaringClass()); + Field root = this.root; + if (root != null) { + declaredAnnotations = root.declaredAnnotations(); + } else { + declaredAnnotations = AnnotationParser.parseAnnotations( + annotations, + sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()), + getDeclaringClass()); + } } return declaredAnnotations; } diff --git a/src/share/classes/java/lang/reflect/Method.java b/src/share/classes/java/lang/reflect/Method.java index b046a7a1d3d780c48e2c68d29fbe5012ae7f64ba..786aac6382b0aaa8fd2e30418b6a4de9a22fb660 100644 --- a/src/share/classes/java/lang/reflect/Method.java +++ b/src/share/classes/java/lang/reflect/Method.java @@ -79,6 +79,9 @@ public final class Method extends Executable { // For sharing of MethodAccessors. This branching structure is // currently only two levels deep (i.e., one root Method and // potentially many Method objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. private Method root; // Generics infrastructure @@ -144,6 +147,9 @@ public final class Method extends Executable { // which implicitly requires that new java.lang.reflect // objects be fabricated for each reflective call on Class // objects.) + if (this.root != null) + throw new IllegalArgumentException("Can not copy a non-root Method"); + Method res = new Method(clazz, name, parameterTypes, returnType, exceptionTypes, modifiers, slot, signature, annotations, parameterAnnotations, annotationDefault); @@ -153,6 +159,14 @@ public final class Method extends Executable { return res; } + /** + * Used by Excecutable for annotation sharing. + */ + @Override + Executable getRoot() { + return root; + } + @Override boolean hasGenericInformation() { return (getGenericSignature() != null); diff --git a/src/share/classes/java/util/CurrencyData.properties b/src/share/classes/java/util/CurrencyData.properties index a22ddd4b3b66795cda196be07918ec6f84a841af..2b5a5704959c9a1818d54814d8640f68b5c20aed 100644 --- a/src/share/classes/java/util/CurrencyData.properties +++ b/src/share/classes/java/util/CurrencyData.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ formatVersion=1 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=156 +dataVersion=159 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -332,7 +332,7 @@ LY=LYD # LIECHTENSTEIN LI=CHF # LITHUANIA -LT=LTL +LT=LTL;2014-12-31-22-00-00;EUR # LUXEMBOURG LU=EUR # MACAU diff --git a/src/share/classes/java/util/concurrent/CompletableFuture.java b/src/share/classes/java/util/concurrent/CompletableFuture.java index 9e89169e15f08a0f159691b46395c518ff29c07a..8476dcc12379bc6b0ac6050bd6a14b826bbb66f9 100644 --- a/src/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/share/classes/java/util/concurrent/CompletableFuture.java @@ -50,7 +50,6 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; /** @@ -77,9 +76,9 @@ import java.util.concurrent.locks.LockSupport; *

  • All async methods without an explicit Executor * argument are performed using the {@link ForkJoinPool#commonPool()} * (unless it does not support a parallelism level of at least two, in - * which case, a new Thread is used). To simplify monitoring, - * debugging, and tracking, all generated asynchronous tasks are - * instances of the marker interface {@link + * which case, a new Thread is created to run each task). To simplify + * monitoring, debugging, and tracking, all generated asynchronous + * tasks are instances of the marker interface {@link * AsynchronousCompletionTask}.
  • * *
  • All CompletionStage methods are implemented independently of @@ -113,301 +112,273 @@ public class CompletableFuture implements Future, CompletionStage { /* * Overview: * - * 1. Non-nullness of field result (set via CAS) indicates done. - * An AltResult is used to box null as a result, as well as to - * hold exceptions. Using a single field makes completion fast - * and simple to detect and trigger, at the expense of a lot of - * encoding and decoding that infiltrates many methods. One minor - * simplification relies on the (static) NIL (to box null results) - * being the only AltResult with a null exception field, so we - * don't usually need explicit comparisons with NIL. The CF - * exception propagation mechanics surrounding decoding rely on - * unchecked casts of decoded results really being unchecked, - * where user type errors are caught at point of use, as is - * currently the case in Java. These are highlighted by using - * SuppressWarnings-annotated temporaries. + * A CompletableFuture may have dependent completion actions, + * collected in a linked stack. It atomically completes by CASing + * a result field, and then pops off and runs those actions. This + * applies across normal vs exceptional outcomes, sync vs async + * actions, binary triggers, and various forms of completions. * - * 2. Waiters are held in a Treiber stack similar to the one used - * in FutureTask, Phaser, and SynchronousQueue. See their - * internal documentation for algorithmic details. + * Non-nullness of field result (set via CAS) indicates done. An + * AltResult is used to box null as a result, as well as to hold + * exceptions. Using a single field makes completion simple to + * detect and trigger. Encoding and decoding is straightforward + * but adds to the sprawl of trapping and associating exceptions + * with targets. Minor simplifications rely on (static) NIL (to + * box null results) being the only AltResult with a null + * exception field, so we don't usually need explicit comparisons. + * Even though some of the generics casts are unchecked (see + * SuppressWarnings annotations), they are placed to be + * appropriate even if checked. * - * 3. Completions are also kept in a list/stack, and pulled off - * and run when completion is triggered. (We could even use the - * same stack as for waiters, but would give up the potential - * parallelism obtained because woken waiters help release/run - * others -- see method postComplete). Because post-processing - * may race with direct calls, class Completion opportunistically - * extends AtomicInteger so callers can claim the action via - * compareAndSet(0, 1). The Completion.run methods are all - * written a boringly similar uniform way (that sometimes includes - * unnecessary-looking checks, kept to maintain uniformity). - * There are enough dimensions upon which they differ that - * attempts to factor commonalities while maintaining efficiency - * require more lines of code than they would save. + * Dependent actions are represented by Completion objects linked + * as Treiber stacks headed by field "stack". There are Completion + * classes for each kind of action, grouped into single-input + * (UniCompletion), two-input (BiCompletion), projected + * (BiCompletions using either (not both) of two inputs), shared + * (CoCompletion, used by the second of two sources), zero-input + * source actions, and Signallers that unblock waiters. Class + * Completion extends ForkJoinTask to enable async execution + * (adding no space overhead because we exploit its "tag" methods + * to maintain claims). It is also declared as Runnable to allow + * usage with arbitrary executors. * - * 4. The exported then/and/or methods do support a bit of - * factoring (see doThenApply etc). They must cope with the - * intrinsic races surrounding addition of a dependent action - * versus performing the action directly because the task is - * already complete. For example, a CF may not be complete upon - * entry, so a dependent completion is added, but by the time it - * is added, the target CF is complete, so must be directly - * executed. This is all done while avoiding unnecessary object - * construction in safe-bypass cases. + * Support for each kind of CompletionStage relies on a separate + * class, along with two CompletableFuture methods: + * + * * A Completion class with name X corresponding to function, + * prefaced with "Uni", "Bi", or "Or". Each class contains + * fields for source(s), actions, and dependent. They are + * boringly similar, differing from others only with respect to + * underlying functional forms. We do this so that users don't + * encounter layers of adaptors in common usages. We also + * include "Relay" classes/methods that don't correspond to user + * methods; they copy results from one stage to another. + * + * * Boolean CompletableFuture method x(...) (for example + * uniApply) takes all of the arguments needed to check that an + * action is triggerable, and then either runs the action or + * arranges its async execution by executing its Completion + * argument, if present. The method returns true if known to be + * complete. + * + * * Completion method tryFire(int mode) invokes the associated x + * method with its held arguments, and on success cleans up. + * The mode argument allows tryFire to be called twice (SYNC, + * then ASYNC); the first to screen and trap exceptions while + * arranging to execute, and the second when called from a + * task. (A few classes are not used async so take slightly + * different forms.) The claim() callback suppresses function + * invocation if already claimed by another thread. + * + * * CompletableFuture method xStage(...) is called from a public + * stage method of CompletableFuture x. It screens user + * arguments and invokes and/or creates the stage object. If + * not async and x is already complete, the action is run + * immediately. Otherwise a Completion c is created, pushed to + * x's stack (unless done), and started or triggered via + * c.tryFire. This also covers races possible if x completes + * while pushing. Classes with two inputs (for example BiApply) + * deal with races across both while pushing actions. The + * second completion is a CoCompletion pointing to the first, + * shared so that at most one performs the action. The + * multiple-arity methods allOf and anyOf do this pairwise to + * form trees of completions. + * + * Note that the generic type parameters of methods vary according + * to whether "this" is a source, dependent, or completion. + * + * Method postComplete is called upon completion unless the target + * is guaranteed not to be observable (i.e., not yet returned or + * linked). Multiple threads can call postComplete, which + * atomically pops each dependent action, and tries to trigger it + * via method tryFire, in NESTED mode. Triggering can propagate + * recursively, so NESTED mode returns its completed dependent (if + * one exists) for further processing by its caller (see method + * postFire). + * + * Blocking methods get() and join() rely on Signaller Completions + * that wake up waiting threads. The mechanics are similar to + * Treiber stack wait-nodes used in FutureTask, Phaser, and + * SynchronousQueue. See their internal documentation for + * algorithmic details. + * + * Without precautions, CompletableFutures would be prone to + * garbage accumulation as chains of Completions build up, each + * pointing back to its sources. So we null out fields as soon as + * possible (see especially method Completion.detach). The + * screening checks needed anyway harmlessly ignore null arguments + * that may have been obtained during races with threads nulling + * out fields. We also try to unlink fired Completions from + * stacks that might never be popped (see method postFire). + * Completion fields need not be declared as final or volatile + * because they are only visible to other threads upon safe + * publication. */ - // preliminaries + volatile Object result; // Either the result or boxed AltResult + volatile Completion stack; // Top of Treiber stack of dependent actions + + final boolean internalComplete(Object r) { // CAS from null to r + return UNSAFE.compareAndSwapObject(this, RESULT, null, r); + } + + final boolean casStack(Completion cmp, Completion val) { + return UNSAFE.compareAndSwapObject(this, STACK, cmp, val); + } + + /** Returns true if successfully pushed c onto stack. */ + final boolean tryPushStack(Completion c) { + Completion h = stack; + lazySetNext(c, h); + return UNSAFE.compareAndSwapObject(this, STACK, h, c); + } + + /** Unconditionally pushes c onto stack, retrying if necessary. */ + final void pushStack(Completion c) { + do {} while (!tryPushStack(c)); + } + + /* ------------- Encoding and decoding outcomes -------------- */ - static final class AltResult { - final Throwable ex; // null only for NIL - AltResult(Throwable ex) { this.ex = ex; } + static final class AltResult { // See above + final Throwable ex; // null only for NIL + AltResult(Throwable x) { this.ex = x; } } + /** The encoding of the null value. */ static final AltResult NIL = new AltResult(null); - // Fields + /** Completes with the null value, unless already completed. */ + final boolean completeNull() { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + NIL); + } - volatile Object result; // Either the result or boxed AltResult - volatile WaitNode waiters; // Treiber stack of threads blocked on get() - volatile CompletionNode completions; // list (Treiber stack) of completions + /** Returns the encoding of the given non-exceptional value. */ + final Object encodeValue(T t) { + return (t == null) ? NIL : t; + } - // Basic utilities for triggering and processing completions + /** Completes with a non-exceptional result, unless already completed. */ + final boolean completeValue(T t) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + (t == null) ? NIL : t); + } /** - * Removes and signals all waiting threads and runs all completions. + * Returns the encoding of the given (non-null) exception as a + * wrapped CompletionException unless it is one already. */ - final void postComplete() { - WaitNode q; Thread t; - while ((q = waiters) != null) { - if (UNSAFE.compareAndSwapObject(this, WAITERS, q, q.next) && - (t = q.thread) != null) { - q.thread = null; - LockSupport.unpark(t); - } - } + static AltResult encodeThrowable(Throwable x) { + return new AltResult((x instanceof CompletionException) ? x : + new CompletionException(x)); + } - CompletionNode h; Completion c; - while ((h = completions) != null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, h, h.next) && - (c = h.completion) != null) - c.run(); - } + /** Completes with an exceptional result, unless already completed. */ + final boolean completeThrowable(Throwable x) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + encodeThrowable(x)); } /** - * Triggers completion with the encoding of the given arguments: - * if the exception is non-null, encodes it as a wrapped - * CompletionException unless it is one already. Otherwise uses - * the given result, boxed as NIL if null. + * Returns the encoding of the given (non-null) exception as a + * wrapped CompletionException unless it is one already. May + * return the given Object r (which must have been the result of a + * source future) if it is equivalent, i.e. if this is a simple + * relay of an existing CompletionException. */ - final void internalComplete(T v, Throwable ex) { - if (result == null) - UNSAFE.compareAndSwapObject - (this, RESULT, null, - (ex == null) ? (v == null) ? NIL : v : - new AltResult((ex instanceof CompletionException) ? ex : - new CompletionException(ex))); - postComplete(); // help out even if not triggered + static Object encodeThrowable(Throwable x, Object r) { + if (!(x instanceof CompletionException)) + x = new CompletionException(x); + else if (r instanceof AltResult && x == ((AltResult)r).ex) + return r; + return new AltResult(x); } /** - * If triggered, helps release and/or process completions. + * Completes with the given (non-null) exceptional result as a + * wrapped CompletionException unless it is one already, unless + * already completed. May complete with the given Object r + * (which must have been the result of a source future) if it is + * equivalent, i.e. if this is a simple propagation of an + * existing CompletionException. */ - final void helpPostComplete() { - if (result != null) - postComplete(); + final boolean completeThrowable(Throwable x, Object r) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + encodeThrowable(x, r)); } - /* ------------- waiting for completions -------------- */ - - /** Number of processors, for spin control */ - static final int NCPU = Runtime.getRuntime().availableProcessors(); - /** - * Heuristic spin value for waitingGet() before blocking on - * multiprocessors + * Returns the encoding of the given arguments: if the exception + * is non-null, encodes as AltResult. Otherwise uses the given + * value, boxed as NIL if null. */ - static final int SPINS = (NCPU > 1) ? 1 << 8 : 0; + Object encodeOutcome(T t, Throwable x) { + return (x == null) ? (t == null) ? NIL : t : encodeThrowable(x); + } /** - * Linked nodes to record waiting threads in a Treiber stack. See - * other classes such as Phaser and SynchronousQueue for more - * detailed explanation. This class implements ManagedBlocker to - * avoid starvation when blocking actions pile up in - * ForkJoinPools. + * Returns the encoding of a copied outcome; if exceptional, + * rewraps as a CompletionException, else returns argument. */ - static final class WaitNode implements ForkJoinPool.ManagedBlocker { - long nanos; // wait time if timed - final long deadline; // non-zero if timed - volatile int interruptControl; // > 0: interruptible, < 0: interrupted - volatile Thread thread; - volatile WaitNode next; - WaitNode(boolean interruptible, long nanos, long deadline) { - this.thread = Thread.currentThread(); - this.interruptControl = interruptible ? 1 : 0; - this.nanos = nanos; - this.deadline = deadline; - } - public boolean isReleasable() { - if (thread == null) - return true; - if (Thread.interrupted()) { - int i = interruptControl; - interruptControl = -1; - if (i > 0) - return true; - } - if (deadline != 0L && - (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) { - thread = null; - return true; - } - return false; - } - public boolean block() { - if (isReleasable()) - return true; - else if (deadline == 0L) - LockSupport.park(this); - else if (nanos > 0L) - LockSupport.parkNanos(this, nanos); - return isReleasable(); - } + static Object encodeRelay(Object r) { + Throwable x; + return (((r instanceof AltResult) && + (x = ((AltResult)r).ex) != null && + !(x instanceof CompletionException)) ? + new AltResult(new CompletionException(x)) : r); } /** - * Returns raw result after waiting, or null if interruptible and - * interrupted. + * Completes with r or a copy of r, unless already completed. + * If exceptional, r is first coerced to a CompletionException. */ - private Object waitingGet(boolean interruptible) { - WaitNode q = null; - boolean queued = false; - int spins = SPINS; - for (Object r;;) { - if ((r = result) != null) { - if (q != null) { // suppress unpark - q.thread = null; - if (q.interruptControl < 0) { - if (interruptible) { - removeWaiter(q); - return null; - } - Thread.currentThread().interrupt(); - } - } - postComplete(); // help release others - return r; - } - else if (spins > 0) { - int rnd = ThreadLocalRandom.nextSecondarySeed(); - if (rnd == 0) - rnd = ThreadLocalRandom.current().nextInt(); - if (rnd >= 0) - --spins; - } - else if (q == null) - q = new WaitNode(interruptible, 0L, 0L); - else if (!queued) - queued = UNSAFE.compareAndSwapObject(this, WAITERS, - q.next = waiters, q); - else if (interruptible && q.interruptControl < 0) { - removeWaiter(q); - return null; - } - else if (q.thread != null && result == null) { - try { - ForkJoinPool.managedBlock(q); - } catch (InterruptedException ex) { - q.interruptControl = -1; - } - } - } + final boolean completeRelay(Object r) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + encodeRelay(r)); } /** - * Awaits completion or aborts on interrupt or timeout. - * - * @param nanos time to wait - * @return raw result + * Reports result using Future.get conventions. */ - private Object timedAwaitDone(long nanos) - throws InterruptedException, TimeoutException { - WaitNode q = null; - boolean queued = false; - for (Object r;;) { - if ((r = result) != null) { - if (q != null) { - q.thread = null; - if (q.interruptControl < 0) { - removeWaiter(q); - throw new InterruptedException(); - } - } - postComplete(); - return r; - } - else if (q == null) { - if (nanos <= 0L) - throw new TimeoutException(); - long d = System.nanoTime() + nanos; - q = new WaitNode(true, nanos, d == 0L ? 1L : d); // avoid 0 - } - else if (!queued) - queued = UNSAFE.compareAndSwapObject(this, WAITERS, - q.next = waiters, q); - else if (q.interruptControl < 0) { - removeWaiter(q); - throw new InterruptedException(); - } - else if (q.nanos <= 0L) { - if (result == null) { - removeWaiter(q); - throw new TimeoutException(); - } - } - else if (q.thread != null && result == null) { - try { - ForkJoinPool.managedBlock(q); - } catch (InterruptedException ex) { - q.interruptControl = -1; - } - } + private static T reportGet(Object r) + throws InterruptedException, ExecutionException { + if (r == null) // by convention below, null means interrupted + throw new InterruptedException(); + if (r instanceof AltResult) { + Throwable x, cause; + if ((x = ((AltResult)r).ex) == null) + return null; + if (x instanceof CancellationException) + throw (CancellationException)x; + if ((x instanceof CompletionException) && + (cause = x.getCause()) != null) + x = cause; + throw new ExecutionException(x); } + @SuppressWarnings("unchecked") T t = (T) r; + return t; } /** - * Tries to unlink a timed-out or interrupted wait node to avoid - * accumulating garbage. Internal nodes are simply unspliced - * without CAS since it is harmless if they are traversed anyway - * by releasers. To avoid effects of unsplicing from already - * removed nodes, the list is retraversed in case of an apparent - * race. This is slow when there are a lot of nodes, but we don't - * expect lists to be long enough to outweigh higher-overhead - * schemes. + * Decodes outcome to return result or throw unchecked exception. */ - private void removeWaiter(WaitNode node) { - if (node != null) { - node.thread = null; - retry: - for (;;) { // restart on removeWaiter race - for (WaitNode pred = null, q = waiters, s; q != null; q = s) { - s = q.next; - if (q.thread != null) - pred = q; - else if (pred != null) { - pred.next = s; - if (pred.thread == null) // check for race - continue retry; - } - else if (!UNSAFE.compareAndSwapObject(this, WAITERS, q, s)) - continue retry; - } - break; - } + private static T reportJoin(Object r) { + if (r instanceof AltResult) { + Throwable x; + if ((x = ((AltResult)r).ex) == null) + return null; + if (x instanceof CancellationException) + throw (CancellationException)x; + if (x instanceof CompletionException) + throw (CompletionException)x; + throw new CompletionException(x); } + @SuppressWarnings("unchecked") T t = (T) r; + return t; } - /* ------------- Async tasks -------------- */ + /* ------------- Async task preliminaries -------------- */ /** * A marker interface identifying asynchronous tasks produced by @@ -419,1693 +390,1394 @@ public class CompletableFuture implements Future, CompletionStage { public static interface AsynchronousCompletionTask { } - /** Base class can act as either FJ or plain Runnable */ + private static final boolean useCommonPool = + (ForkJoinPool.getCommonPoolParallelism() > 1); + + /** + * Default executor -- ForkJoinPool.commonPool() unless it cannot + * support parallelism. + */ + private static final Executor asyncPool = useCommonPool ? + ForkJoinPool.commonPool() : new ThreadPerTaskExecutor(); + + /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */ + static final class ThreadPerTaskExecutor implements Executor { + public void execute(Runnable r) { new Thread(r).start(); } + } + + /** + * Null-checks user executor argument, and translates uses of + * commonPool to asyncPool in case parallelism disabled. + */ + static Executor screenExecutor(Executor e) { + if (!useCommonPool && e == ForkJoinPool.commonPool()) + return asyncPool; + if (e == null) throw new NullPointerException(); + return e; + } + + // Modes for Completion.tryFire. Signedness matters. + static final int SYNC = 0; + static final int ASYNC = 1; + static final int NESTED = -1; + + /* ------------- Base Completion classes and operations -------------- */ + @SuppressWarnings("serial") - abstract static class Async extends ForkJoinTask + abstract static class Completion extends ForkJoinTask implements Runnable, AsynchronousCompletionTask { - public final Void getRawResult() { return null; } - public final void setRawResult(Void v) { } - public final void run() { exec(); } + volatile Completion next; // Treiber stack link + + /** + * Performs completion action if triggered, returning a + * dependent that may need propagation, if one exists. + * + * @param mode SYNC, ASYNC, or NESTED + */ + abstract CompletableFuture tryFire(int mode); + + /** Returns true if possibly still triggerable. Used by cleanStack. */ + abstract boolean isLive(); + + public final void run() { tryFire(ASYNC); } + public final boolean exec() { tryFire(ASYNC); return true; } + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) {} + } + + static void lazySetNext(Completion c, Completion next) { + UNSAFE.putOrderedObject(c, NEXT, next); } /** - * Starts the given async task using the given executor, unless - * the executor is ForkJoinPool.commonPool and it has been - * disabled, in which case starts a new thread. + * Pops and tries to trigger all reachable dependents. Call only + * when known to be done. */ - static void execAsync(Executor e, Async r) { - if (e == ForkJoinPool.commonPool() && - ForkJoinPool.getCommonPoolParallelism() <= 1) - new Thread(r).start(); - else - e.execute(r); - } - - static final class AsyncRun extends Async { - final Runnable fn; - final CompletableFuture dst; - AsyncRun(Runnable fn, CompletableFuture dst) { - this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - fn.run(); - ex = null; - } catch (Throwable rex) { - ex = rex; + final void postComplete() { + /* + * On each step, variable f holds current dependents to pop + * and run. It is extended along only one path at a time, + * pushing others to avoid unbounded recursion. + */ + CompletableFuture f = this; Completion h; + while ((h = f.stack) != null || + (f != this && (h = (f = this).stack) != null)) { + CompletableFuture d; Completion t; + if (f.casStack(h, t = h.next)) { + if (t != null) { + if (f != this) { + pushStack(h); + continue; + } + h.next = null; // detach } - d.internalComplete(null, ex); + f = (d = h.tryFire(NESTED)) == null ? this : d; } - return true; } - private static final long serialVersionUID = 5232453952276885070L; } - static final class AsyncSupply extends Async { - final Supplier fn; - final CompletableFuture dst; - AsyncSupply(Supplier fn, CompletableFuture dst) { - this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; U u; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - u = fn.get(); - ex = null; - } catch (Throwable rex) { - ex = rex; - u = null; + /** Traverses stack and unlinks dead Completions. */ + final void cleanStack() { + for (Completion p = null, q = stack; q != null;) { + Completion s = q.next; + if (q.isLive()) { + p = q; + q = s; + } + else if (p == null) { + casStack(q, s); + q = stack; + } + else { + p.next = s; + if (p.isLive()) + q = s; + else { + p = null; // restart + q = stack; } - d.internalComplete(u, ex); } - return true; } - private static final long serialVersionUID = 5232453952276885070L; } - static final class AsyncApply extends Async { - final T arg; - final Function fn; - final CompletableFuture dst; - AsyncApply(T arg, Function fn, - CompletableFuture dst) { - this.arg = arg; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; U u; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - u = fn.apply(arg); - ex = null; - } catch (Throwable rex) { - ex = rex; - u = null; - } - d.internalComplete(u, ex); + /* ------------- One-input Completions -------------- */ + + /** A Completion with a source, dependent, and executor. */ + @SuppressWarnings("serial") + abstract static class UniCompletion extends Completion { + Executor executor; // executor to use (null if none) + CompletableFuture dep; // the dependent to complete + CompletableFuture src; // source for action + + UniCompletion(Executor executor, CompletableFuture dep, + CompletableFuture src) { + this.executor = executor; this.dep = dep; this.src = src; + } + + /** + * Returns true if action can be run. Call only when known to + * be triggerable. Uses FJ tag bit to ensure that only one + * thread claims ownership. If async, starts as task -- a + * later call to tryFire will run action. + */ + final boolean claim() { + Executor e = executor; + if (compareAndSetForkJoinTaskTag((short)0, (short)1)) { + if (e == null) + return true; + executor = null; // disable + e.execute(this); } - return true; + return false; } - private static final long serialVersionUID = 5232453952276885070L; + + final boolean isLive() { return dep != null; } } - static final class AsyncCombine extends Async { - final T arg1; - final U arg2; - final BiFunction fn; - final CompletableFuture dst; - AsyncCombine(T arg1, U arg2, - BiFunction fn, - CompletableFuture dst) { - this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; + /** Pushes the given completion (if it exists) unless done. */ + final void push(UniCompletion c) { + if (c != null) { + while (result == null && !tryPushStack(c)) + lazySetNext(c, null); // clear on failure } - public final boolean exec() { - CompletableFuture d; V v; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - v = fn.apply(arg1, arg2); - ex = null; - } catch (Throwable rex) { - ex = rex; - v = null; - } - d.internalComplete(v, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; } - static final class AsyncAccept extends Async { - final T arg; - final Consumer fn; - final CompletableFuture dst; - AsyncAccept(T arg, Consumer fn, - CompletableFuture dst) { - this.arg = arg; this.fn = fn; this.dst = dst; + /** + * Post-processing by dependent after successful UniCompletion + * tryFire. Tries to clean stack of source a, and then either runs + * postComplete or returns this to caller, depending on mode. + */ + final CompletableFuture postFire(CompletableFuture a, int mode) { + if (a != null && a.stack != null) { + if (mode < 0 || a.result == null) + a.cleanStack(); + else + a.postComplete(); } - public final boolean exec() { - CompletableFuture d; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - fn.accept(arg); - ex = null; - } catch (Throwable rex) { - ex = rex; - } - d.internalComplete(null, ex); - } - return true; + if (result != null && stack != null) { + if (mode < 0) + return this; + else + postComplete(); } - private static final long serialVersionUID = 5232453952276885070L; + return null; } - static final class AsyncAcceptBoth extends Async { - final T arg1; - final U arg2; - final BiConsumer fn; - final CompletableFuture dst; - AsyncAcceptBoth(T arg1, U arg2, - BiConsumer fn, - CompletableFuture dst) { - this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; + @SuppressWarnings("serial") + static final class UniApply extends UniCompletion { + Function fn; + UniApply(Executor executor, CompletableFuture dep, + CompletableFuture src, + Function fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniApply(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); } - public final boolean exec() { - CompletableFuture d; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - fn.accept(arg1, arg2); - ex = null; - } catch (Throwable rex) { - ex = rex; + } + + final boolean uniApply(CompletableFuture a, + Function f, + UniApply c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; } - d.internalComplete(null, ex); + r = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") S s = (S) r; + completeValue(f.apply(s)); + } catch (Throwable ex) { + completeThrowable(ex); } - return true; } - private static final long serialVersionUID = 5232453952276885070L; + return true; } - static final class AsyncCompose extends Async { - final T arg; - final Function> fn; - final CompletableFuture dst; - AsyncCompose(T arg, - Function> fn, - CompletableFuture dst) { - this.arg = arg; this.fn = fn; this.dst = dst; + private CompletableFuture uniApplyStage( + Executor e, Function f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniApply(this, f, null)) { + UniApply c = new UniApply(e, d, this, f); + push(c); + c.tryFire(SYNC); } - public final boolean exec() { - CompletableFuture d, fr; U u; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - CompletionStage cs = fn.apply(arg); - fr = (cs == null) ? null : cs.toCompletableFuture(); - ex = (fr == null) ? new NullPointerException() : null; - } catch (Throwable rex) { - ex = rex; - fr = null; - } - if (ex != null) - u = null; - else { - Object r = fr.result; - if (r == null) - r = fr.waitingGet(false); - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U ur = (U) r; - u = ur; - } + return d; + } + + @SuppressWarnings("serial") + static final class UniAccept extends UniCompletion { + Consumer fn; + UniAccept(Executor executor, CompletableFuture dep, + CompletableFuture src, Consumer fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniAccept(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniAccept(CompletableFuture a, + Consumer f, UniAccept c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; } - d.internalComplete(u, ex); + r = null; } - return true; + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") S s = (S) r; + f.accept(s); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniAcceptStage(Executor e, + Consumer f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniAccept(this, f, null)) { + UniAccept c = new UniAccept(e, d, this, f); + push(c); + c.tryFire(SYNC); } - private static final long serialVersionUID = 5232453952276885070L; + return d; } - static final class AsyncWhenComplete extends Async { - final T arg1; - final Throwable arg2; - final BiConsumer fn; - final CompletableFuture dst; - AsyncWhenComplete(T arg1, Throwable arg2, - BiConsumer fn, - CompletableFuture dst) { - this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; + @SuppressWarnings("serial") + static final class UniRun extends UniCompletion { + Runnable fn; + UniRun(Executor executor, CompletableFuture dep, + CompletableFuture src, Runnable fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniRun(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); } - public final boolean exec() { - CompletableFuture d; - if ((d = this.dst) != null && d.result == null) { - Throwable ex = arg2; + } + + final boolean uniRun(CompletableFuture a, Runnable f, UniRun c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else try { - fn.accept(arg1, ex); - } catch (Throwable rex) { - if (ex == null) - ex = rex; + if (c != null && !c.claim()) + return false; + f.run(); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); } - d.internalComplete(arg1, ex); - } - return true; } - private static final long serialVersionUID = 5232453952276885070L; + return true; } - /* ------------- Completions -------------- */ - - /** - * Simple linked list nodes to record completions, used in - * basically the same way as WaitNodes. (We separate nodes from - * the Completions themselves mainly because for the And and Or - * methods, the same Completion object resides in two lists.) - */ - static final class CompletionNode { - final Completion completion; - volatile CompletionNode next; - CompletionNode(Completion completion) { this.completion = completion; } + private CompletableFuture uniRunStage(Executor e, Runnable f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniRun(this, f, null)) { + UniRun c = new UniRun(e, d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; } - // Opportunistically subclass AtomicInteger to use compareAndSet to claim. @SuppressWarnings("serial") - abstract static class Completion extends AtomicInteger implements Runnable { - } - - static final class ThenApply extends Completion { - final CompletableFuture src; - final Function fn; - final CompletableFuture dst; - final Executor executor; - ThenApply(CompletableFuture src, - Function fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Function fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } + static final class UniWhenComplete extends UniCompletion { + BiConsumer fn; + UniWhenComplete(Executor executor, CompletableFuture dep, + CompletableFuture src, + BiConsumer fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniWhenComplete(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenAccept extends Completion { - final CompletableFuture src; - final Consumer fn; - final CompletableFuture dst; - final Executor executor; - ThenAccept(CompletableFuture src, - Consumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Consumer fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { + } + + final boolean uniWhenComplete(CompletableFuture a, + BiConsumer f, + UniWhenComplete c) { + Object r; T t; Throwable x = null; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + try { + if (c != null && !c.claim()) + return false; if (r instanceof AltResult) { - ex = ((AltResult)r).ex; + x = ((AltResult)r).ex; t = null; - } - else { - ex = null; + } else { @SuppressWarnings("unchecked") T tr = (T) r; t = tr; } - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } + f.accept(t, x); + if (x == null) { + internalComplete(r); + return true; } - if (e == null || ex != null) - dst.internalComplete(null, ex); + } catch (Throwable ex) { + if (x == null) + x = ex; } + completeThrowable(x, r); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenRun extends Completion { - final CompletableFuture src; - final Runnable fn; - final CompletableFuture dst; - final Executor executor; - ThenRun(CompletableFuture src, - Runnable fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Runnable fn; - final CompletableFuture dst; - Object r; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(fn, dst)); - else - fn.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } + return true; + } + + private CompletableFuture uniWhenCompleteStage( + Executor e, BiConsumer f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniWhenComplete(this, f, null)) { + UniWhenComplete c = new UniWhenComplete(e, d, this, f); + push(c); + c.tryFire(SYNC); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenCombine extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final BiFunction fn; - final CompletableFuture dst; - final Executor executor; - ThenCombine(CompletableFuture src, - CompletableFuture snd, - BiFunction fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final BiFunction fn; - final CompletableFuture dst; - Object r, s; T t; U u; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - Executor e = executor; - V v = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncCombine(t, u, fn, dst)); - else - v = fn.apply(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(v, ex); - } + return d; + } + + @SuppressWarnings("serial") + static final class UniHandle extends UniCompletion { + BiFunction fn; + UniHandle(Executor executor, CompletableFuture dep, + CompletableFuture src, + BiFunction fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniHandle(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenAcceptBoth extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final BiConsumer fn; - final CompletableFuture dst; - final Executor executor; - ThenAcceptBoth(CompletableFuture src, - CompletableFuture snd, - BiConsumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final BiConsumer fn; - final CompletableFuture dst; - Object r, s; T t; U u; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { + } + + final boolean uniHandle(CompletableFuture a, + BiFunction f, + UniHandle c) { + Object r; S s; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + try { + if (c != null && !c.claim()) + return false; if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; + x = ((AltResult)r).ex; + s = null; + } else { + x = null; + @SuppressWarnings("unchecked") S ss = (S) r; + s = ss; } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAcceptBoth(t, u, fn, dst)); - else - fn.accept(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); + completeValue(f.apply(s, x)); + } catch (Throwable ex) { + completeThrowable(ex); } } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class RunAfterBoth extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Runnable fn; - final CompletableFuture dst; - final Executor executor; - RunAfterBoth(CompletableFuture src, - CompletableFuture snd, - Runnable fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Runnable fn; - final CompletableFuture dst; - Object r, s; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(fn, dst)); - else - fn.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } + return true; + } + + private CompletableFuture uniHandleStage( + Executor e, BiFunction f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniHandle(this, f, null)) { + UniHandle c = new UniHandle(e, d, this, f); + push(c); + c.tryFire(SYNC); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AndCompletion extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final CompletableFuture dst; - AndCompletion(CompletableFuture src, - CompletableFuture snd, - CompletableFuture dst) { - this.src = src; this.snd = snd; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final CompletableFuture dst; - Object r, s; Throwable ex; - if ((dst = this.dst) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - dst.internalComplete(null, ex); - } + return d; + } + + @SuppressWarnings("serial") + static final class UniExceptionally extends UniCompletion { + Function fn; + UniExceptionally(CompletableFuture dep, CompletableFuture src, + Function fn) { + super(null, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { // never ASYNC + // assert mode != ASYNC; + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || !d.uniExceptionally(a = src, fn, this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ApplyToEither extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Function fn; - final CompletableFuture dst; - final Executor executor; - ApplyToEither(CompletableFuture src, - CompletableFuture snd, - Function fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Function fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); + } + + final boolean uniExceptionally(CompletableFuture a, + Function f, + UniExceptionally c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + try { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) { + if (c != null && !c.claim()) + return false; + completeValue(f.apply(x)); + } else + internalComplete(r); + } catch (Throwable ex) { + completeThrowable(ex); } } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AcceptEither extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Consumer fn; - final CompletableFuture dst; - final Executor executor; - AcceptEither(CompletableFuture src, - CompletableFuture snd, - Consumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Consumer fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } + return true; + } + + private CompletableFuture uniExceptionallyStage( + Function f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (!d.uniExceptionally(this, f, null)) { + UniExceptionally c = new UniExceptionally(d, this, f); + push(c); + c.tryFire(SYNC); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class RunAfterEither extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Runnable fn; - final CompletableFuture dst; - final Executor executor; - RunAfterEither(CompletableFuture src, - CompletableFuture snd, - Runnable fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Runnable fn; - final CompletableFuture dst; - Object r; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(fn, dst)); - else - fn.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } + return d; + } + + @SuppressWarnings("serial") + static final class UniRelay extends UniCompletion { // for Compose + UniRelay(CompletableFuture dep, CompletableFuture src) { + super(null, dep, src); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class OrCompletion extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final CompletableFuture dst; - OrCompletion(CompletableFuture src, - CompletableFuture snd, - CompletableFuture dst) { - this.src = src; this.snd = snd; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final CompletableFuture dst; - Object r, t; Throwable ex; - if ((dst = this.dst) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - t = r; - } - dst.internalComplete(t, ex); - } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || !d.uniRelay(a = src)) + return null; + src = null; dep = null; + return d.postFire(a, mode); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ExceptionCompletion extends Completion { - final CompletableFuture src; - final Function fn; - final CompletableFuture dst; - ExceptionCompletion(CompletableFuture src, - Function fn, - CompletableFuture dst) { - this.src = src; this.fn = fn; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final Function fn; - final CompletableFuture dst; - Object r; T t = null; Throwable ex, dx = null; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if ((r instanceof AltResult) && - (ex = ((AltResult)r).ex) != null) { - try { - t = fn.apply(ex); - } catch (Throwable rex) { - dx = rex; - } - } - else { - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - dst.internalComplete(t, dx); - } + } + + final boolean uniRelay(CompletableFuture a) { + Object r; + if (a == null || (r = a.result) == null) + return false; + if (result == null) // no need to claim + completeRelay(r); + return true; + } + + @SuppressWarnings("serial") + static final class UniCompose extends UniCompletion { + Function> fn; + UniCompose(Executor executor, CompletableFuture dep, + CompletableFuture src, + Function> fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniCompose(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class WhenCompleteCompletion extends Completion { - final CompletableFuture src; - final BiConsumer fn; - final CompletableFuture dst; - final Executor executor; - WhenCompleteCompletion(CompletableFuture src, - BiConsumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final BiConsumer fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; + } + + final boolean uniCompose( + CompletableFuture a, + Function> f, + UniCompose c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; } - Executor e = executor; - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncWhenComplete(t, ex, fn, dst)); - else - fn.accept(t, ex); - } catch (Throwable rex) { - dx = rex; + r = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") S s = (S) r; + CompletableFuture g = f.apply(s).toCompletableFuture(); + if (g.result == null || !uniRelay(g)) { + UniRelay copy = new UniRelay(this, g); + g.push(copy); + copy.tryFire(SYNC); + if (result == null) + return false; + } + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniComposeStage( + Executor e, Function> f) { + if (f == null) throw new NullPointerException(); + Object r; Throwable x; + if (e == null && (r = result) != null) { + // try to return function result directly + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + return new CompletableFuture(encodeThrowable(x, r)); } - if (e == null || dx != null) - dst.internalComplete(t, ex != null ? ex : dx); + r = null; + } + try { + @SuppressWarnings("unchecked") T t = (T) r; + return f.apply(t).toCompletableFuture(); + } catch (Throwable ex) { + return new CompletableFuture(encodeThrowable(ex)); } } - private static final long serialVersionUID = 5232453952276885070L; + CompletableFuture d = new CompletableFuture(); + UniCompose c = new UniCompose(e, d, this, f); + push(c); + c.tryFire(SYNC); + return d; } - static final class ThenCopy extends Completion { - final CompletableFuture src; - final CompletableFuture dst; - ThenCopy(CompletableFuture src, - CompletableFuture dst) { - this.src = src; this.dst = dst; + /* ------------- Two-input Completions -------------- */ + + /** A Completion for an action with two sources */ + @SuppressWarnings("serial") + abstract static class BiCompletion extends UniCompletion { + CompletableFuture snd; // second source for action + BiCompletion(Executor executor, CompletableFuture dep, + CompletableFuture src, CompletableFuture snd) { + super(executor, dep, src); this.snd = snd; } - public final void run() { - final CompletableFuture a; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - dst.internalComplete(t, ex); - } + } + + /** A Completion delegating to a BiCompletion */ + @SuppressWarnings("serial") + static final class CoCompletion extends Completion { + BiCompletion base; + CoCompletion(BiCompletion base) { this.base = base; } + final CompletableFuture tryFire(int mode) { + BiCompletion c; CompletableFuture d; + if ((c = base) == null || (d = c.tryFire(mode)) == null) + return null; + base = null; // detach + return d; } - private static final long serialVersionUID = 5232453952276885070L; - } - - // version of ThenCopy for CompletableFuture dst - static final class ThenPropagate extends Completion { - final CompletableFuture src; - final CompletableFuture dst; - ThenPropagate(CompletableFuture src, - CompletableFuture dst) { - this.src = src; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture dst; - Object r; Throwable ex; - if ((dst = this.dst) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - dst.internalComplete(null, ex); - } + final boolean isLive() { + BiCompletion c; + return (c = base) != null && c.dep != null; } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class HandleCompletion extends Completion { - final CompletableFuture src; - final BiFunction fn; - final CompletableFuture dst; - final Executor executor; - HandleCompletion(CompletableFuture src, - BiFunction fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final BiFunction fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - U u = null; - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncCombine(t, ex, fn, dst)); - else - u = fn.apply(t, ex); - } catch (Throwable rex) { - dx = rex; - } - if (e == null || dx != null) - dst.internalComplete(u, dx); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenCompose extends Completion { - final CompletableFuture src; - final Function> fn; - final CompletableFuture dst; - final Executor executor; - ThenCompose(CompletableFuture src, - Function> fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Function> fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; Executor e; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - CompletableFuture c = null; - U u = null; - boolean complete = false; - if (ex == null) { - if ((e = executor) != null) - execAsync(e, new AsyncCompose(t, fn, dst)); - else { - try { - CompletionStage cs = fn.apply(t); - c = (cs == null) ? null : cs.toCompletableFuture(); - if (c == null) - ex = new NullPointerException(); - } catch (Throwable rex) { - ex = rex; - } - } - } - if (c != null) { - ThenCopy d = null; - Object s; - if ((s = c.result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenCopy(c, dst)); - while ((s = c.result) == null) { - if (UNSAFE.compareAndSwapObject - (c, COMPLETIONS, p.next = c.completions, p)) - break; - } - } - if (s != null && (d == null || d.compareAndSet(0, 1))) { - complete = true; - if (s instanceof AltResult) { - ex = ((AltResult)s).ex; // no rewrap - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - } - } - if (complete || ex != null) - dst.internalComplete(u, ex); - if (c != null) - c.helpPostComplete(); + } + + /** Pushes completion to this and b unless both done. */ + final void bipush(CompletableFuture b, BiCompletion c) { + if (c != null) { + Object r; + while ((r = result) == null && !tryPushStack(c)) + lazySetNext(c, null); // clear on failure + if (b != null && b != this && b.result == null) { + Completion q = (r != null) ? c : new CoCompletion(c); + while (b.result == null && !b.tryPushStack(q)) + lazySetNext(q, null); // clear on failure } } - private static final long serialVersionUID = 5232453952276885070L; } - // Implementations of stage methods with (plain, async, Executor) forms + /** Post-processing after successful BiCompletion tryFire. */ + final CompletableFuture postFire(CompletableFuture a, + CompletableFuture b, int mode) { + if (b != null && b.stack != null) { // clean second source + if (mode < 0 || b.result == null) + b.cleanStack(); + else + b.postComplete(); + } + return postFire(a, mode); + } - private CompletableFuture doThenApply - (Function fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenApply d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenApply(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } + @SuppressWarnings("serial") + static final class BiApply extends BiCompletion { + BiFunction fn; + BiApply(Executor executor, CompletableFuture dep, + CompletableFuture src, CompletableFuture snd, + BiFunction fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.biApply(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; + } + + final boolean biApply(CompletableFuture a, + CompletableFuture b, + BiFunction f, + BiApply c) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null || f == null) + return false; + tryComplete: if (result == null) { if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; } - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; + if (s instanceof AltResult) { + if ((x = ((AltResult)s).ex) != null) { + completeThrowable(x, s); + break tryComplete; } + s = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") R rr = (R) r; + @SuppressWarnings("unchecked") S ss = (S) s; + completeValue(f.apply(rr, ss)); + } catch (Throwable ex) { + completeThrowable(ex); } - if (e == null || ex != null) - dst.internalComplete(u, ex); } - helpPostComplete(); - return dst; + return true; } - private CompletableFuture doThenAccept(Consumer fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenAccept d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenAccept(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } + private CompletableFuture biApplyStage( + Executor e, CompletionStage o, + BiFunction f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.biApply(this, b, f, null)) { + BiApply c = new BiApply(e, d, this, b, f); + bipush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class BiAccept extends BiCompletion { + BiConsumer fn; + BiAccept(Executor executor, CompletableFuture dep, + CompletableFuture src, CompletableFuture snd, + BiConsumer fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.biAccept(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; + } + + final boolean biAccept(CompletableFuture a, + CompletableFuture b, + BiConsumer f, + BiAccept c) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null || f == null) + return false; + tryComplete: if (result == null) { if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; } - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; + if (s instanceof AltResult) { + if ((x = ((AltResult)s).ex) != null) { + completeThrowable(x, s); + break tryComplete; } + s = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") R rr = (R) r; + @SuppressWarnings("unchecked") S ss = (S) s; + f.accept(rr, ss); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); } - if (e == null || ex != null) - dst.internalComplete(null, ex); } - helpPostComplete(); - return dst; + return true; } - private CompletableFuture doThenRun(Runnable action, - Executor e) { - if (action == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenRun d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenRun(this, action, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } + private CompletableFuture biAcceptStage( + Executor e, CompletionStage o, + BiConsumer f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.biAccept(this, b, f, null)) { + BiAccept c = new BiAccept(e, d, this, b, f); + bipush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class BiRun extends BiCompletion { + Runnable fn; + BiRun(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Runnable fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.biRun(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; + } + + final boolean biRun(CompletableFuture a, CompletableFuture b, + Runnable f, BiRun c) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null || f == null) + return false; + if (result == null) { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null) + completeThrowable(x, s); else - ex = null; - if (ex == null) { try { - if (e != null) - execAsync(e, new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - return dst; - } - - private CompletableFuture doThenCombine - (CompletableFuture other, - BiFunction fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenCombine d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new ThenCombine(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); + if (c != null && !c.claim()) + return false; + f.run(); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); } - } } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - T t; U u; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - V v = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncCombine(t, u, fn, dst)); - else - v = fn.apply(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(v, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doThenAcceptBoth - (CompletableFuture other, - BiConsumer fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenAcceptBoth d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new ThenAcceptBoth(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } + return true; + } + + private CompletableFuture biRunStage(Executor e, CompletionStage o, + Runnable f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.biRun(this, b, f, null)) { + BiRun c = new BiRun<>(e, d, this, b, f); + bipush(b, c); + c.tryFire(SYNC); } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - T t; U u; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAcceptBoth(t, u, fn, dst)); - else - fn.accept(t, u); - } catch (Throwable rex) { - ex = rex; - } + return d; + } + + @SuppressWarnings("serial") + static final class BiRelay extends BiCompletion { // for And + BiRelay(CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd) { + super(null, dep, src, snd); + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || !d.biRelay(a = src, b = snd)) + return null; + src = null; snd = null; dep = null; + return d.postFire(a, b, mode); + } + } + + boolean biRelay(CompletableFuture a, CompletableFuture b) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null) + return false; + if (result == null) { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null) + completeThrowable(x, s); + else + completeNull(); + } + return true; + } + + /** Recursively constructs a tree of completions. */ + static CompletableFuture andTree(CompletableFuture[] cfs, + int lo, int hi) { + CompletableFuture d = new CompletableFuture(); + if (lo > hi) // empty + d.result = NIL; + else { + CompletableFuture a, b; + int mid = (lo + hi) >>> 1; + if ((a = (lo == mid ? cfs[lo] : + andTree(cfs, lo, mid))) == null || + (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] : + andTree(cfs, mid+1, hi))) == null) + throw new NullPointerException(); + if (!d.biRelay(a, b)) { + BiRelay c = new BiRelay<>(d, a, b); + a.bipush(b, c); + c.tryFire(SYNC); } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doRunAfterBoth(CompletableFuture other, - Runnable action, - Executor e) { - if (other == null || action == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - RunAfterBoth d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new RunAfterBoth(this, other, action, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); + } + return d; + } + + /* ------------- Projected (Ored) BiCompletions -------------- */ + + /** Pushes completion to this and b unless either done. */ + final void orpush(CompletableFuture b, BiCompletion c) { + if (c != null) { + while ((b == null || b.result == null) && result == null) { + if (tryPushStack(c)) { + if (b != null && b != this && b.result == null) { + Completion q = new CoCompletion(c); + while (result == null && b.result == null && + !b.tryPushStack(q)) + lazySetNext(q, null); // clear on failure + } + break; } + lazySetNext(c, null); // clear on failure } } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); + } + + @SuppressWarnings("serial") + static final class OrApply extends BiCompletion { + Function fn; + OrApply(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Function fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.orApply(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); } - helpPostComplete(); - other.helpPostComplete(); - return dst; } - private CompletableFuture doApplyToEither - (CompletableFuture other, - Function fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ApplyToEither d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new ApplyToEither(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; + final boolean orApply(CompletableFuture a, + CompletableFuture b, + Function f, + OrApply c) { + Object r; Throwable x; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null) || f == null) + return false; + tryComplete: if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); + @SuppressWarnings("unchecked") R rr = (R) r; + completeValue(f.apply(rr)); + } catch (Throwable ex) { + completeThrowable(ex); } } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); + return true; + } + + private CompletableFuture orApplyStage( + Executor e, CompletionStage o, + Function f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.orApply(this, b, f, null)) { + OrApply c = new OrApply(e, d, this, b, f); + orpush(b, c); + c.tryFire(SYNC); } - helpPostComplete(); - other.helpPostComplete(); - return dst; + return d; } - private CompletableFuture doAcceptEither - (CompletableFuture other, - Consumer fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - AcceptEither d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new AcceptEither(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; + @SuppressWarnings("serial") + static final class OrAccept extends BiCompletion { + Consumer fn; + OrAccept(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Consumer fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.orAccept(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean orAccept(CompletableFuture a, + CompletableFuture b, + Consumer f, + OrAccept c) { + Object r; Throwable x; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null) || f == null) + return false; + tryComplete: if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); + @SuppressWarnings("unchecked") R rr = (R) r; + f.accept(rr); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); } } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; + return true; + } + + private CompletableFuture orAcceptStage( + Executor e, CompletionStage o, Consumer f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.orAccept(this, b, f, null)) { + OrAccept c = new OrAccept(e, d, this, b, f); + orpush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class OrRun extends BiCompletion { + Runnable fn; + OrRun(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Runnable fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.orRun(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean orRun(CompletableFuture a, CompletableFuture b, + Runnable f, OrRun c) { + Object r; Throwable x; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null) || f == null) + return false; + if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else { + f.run(); + completeNull(); } + } catch (Throwable ex) { + completeThrowable(ex); } - if (e == null || ex != null) - dst.internalComplete(null, ex); } - helpPostComplete(); - other.helpPostComplete(); - return dst; + return true; + } + + private CompletableFuture orRunStage(Executor e, CompletionStage o, + Runnable f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.orRun(this, b, f, null)) { + OrRun c = new OrRun<>(e, d, this, b, f); + orpush(b, c); + c.tryFire(SYNC); + } + return d; } - private CompletableFuture doRunAfterEither - (CompletableFuture other, - Runnable action, - Executor e) { - if (other == null || action == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - RunAfterEither d = null; + @SuppressWarnings("serial") + static final class OrRelay extends BiCompletion { // for Or + OrRelay(CompletableFuture dep, CompletableFuture src, + CompletableFuture snd) { + super(null, dep, src, snd); + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || !d.orRelay(a = src, b = snd)) + return null; + src = null; snd = null; dep = null; + return d.postFire(a, b, mode); + } + } + + final boolean orRelay(CompletableFuture a, CompletableFuture b) { Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new RunAfterEither(this, other, action, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null)) + return false; + if (result == null) + completeRelay(r); + return true; + } + + /** Recursively constructs a tree of completions. */ + static CompletableFuture orTree(CompletableFuture[] cfs, + int lo, int hi) { + CompletableFuture d = new CompletableFuture(); + if (lo <= hi) { + CompletableFuture a, b; + int mid = (lo + hi) >>> 1; + if ((a = (lo == mid ? cfs[lo] : + orTree(cfs, lo, mid))) == null || + (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] : + orTree(cfs, mid+1, hi))) == null) + throw new NullPointerException(); + if (!d.orRelay(a, b)) { + OrRelay c = new OrRelay<>(d, a, b); + a.orpush(b, c); + c.tryFire(SYNC); } } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; + return d; + } + + /* ------------- Zero-input Async forms -------------- */ + + @SuppressWarnings("serial") + static final class AsyncSupply extends ForkJoinTask + implements Runnable, AsynchronousCompletionTask { + CompletableFuture dep; Supplier fn; + AsyncSupply(CompletableFuture dep, Supplier fn) { + this.dep = dep; this.fn = fn; + } + + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) {} + public final boolean exec() { run(); return true; } + + public void run() { + CompletableFuture d; Supplier f; + if ((d = dep) != null && (f = fn) != null) { + dep = null; fn = null; + if (d.result == null) { + try { + d.completeValue(f.get()); + } catch (Throwable ex) { + d.completeThrowable(ex); + } } + d.postComplete(); } - if (e == null || ex != null) - dst.internalComplete(null, ex); } - helpPostComplete(); - other.helpPostComplete(); - return dst; } - private CompletableFuture doThenCompose - (Function> fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = null; - ThenCompose d = null; - Object r; - if ((r = result) == null) { - dst = new CompletableFuture(); - CompletionNode p = new CompletionNode - (d = new ThenCompose(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } + static CompletableFuture asyncSupplyStage(Executor e, + Supplier f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + e.execute(new AsyncSupply(d, f)); + return d; + } + + @SuppressWarnings("serial") + static final class AsyncRun extends ForkJoinTask + implements Runnable, AsynchronousCompletionTask { + CompletableFuture dep; Runnable fn; + AsyncRun(CompletableFuture dep, Runnable fn) { + this.dep = dep; this.fn = fn; } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - if (e != null) { - if (dst == null) - dst = new CompletableFuture(); - execAsync(e, new AsyncCompose(t, fn, dst)); - } - else { + + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) {} + public final boolean exec() { run(); return true; } + + public void run() { + CompletableFuture d; Runnable f; + if ((d = dep) != null && (f = fn) != null) { + dep = null; fn = null; + if (d.result == null) { try { - CompletionStage cs = fn.apply(t); - if (cs == null || - (dst = cs.toCompletableFuture()) == null) - ex = new NullPointerException(); - } catch (Throwable rex) { - ex = rex; + f.run(); + d.completeNull(); + } catch (Throwable ex) { + d.completeThrowable(ex); } } - } - if (dst == null) - dst = new CompletableFuture(); - if (ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - dst.helpPostComplete(); - return dst; - } - - private CompletableFuture doWhenComplete - (BiConsumer fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - WhenCompleteCompletion d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new WhenCompleteCompletion - (this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; + d.postComplete(); } } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; + } + + static CompletableFuture asyncRunStage(Executor e, Runnable f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + e.execute(new AsyncRun(d, f)); + return d; + } + + /* ------------- Signallers -------------- */ + + /** + * Completion for recording and releasing a waiting thread. This + * class implements ManagedBlocker to avoid starvation when + * blocking actions pile up in ForkJoinPools. + */ + @SuppressWarnings("serial") + static final class Signaller extends Completion + implements ForkJoinPool.ManagedBlocker { + long nanos; // wait time if timed + final long deadline; // non-zero if timed + volatile int interruptControl; // > 0: interruptible, < 0: interrupted + volatile Thread thread; + + Signaller(boolean interruptible, long nanos, long deadline) { + this.thread = Thread.currentThread(); + this.interruptControl = interruptible ? 1 : 0; + this.nanos = nanos; + this.deadline = deadline; + } + final CompletableFuture tryFire(int ignore) { + Thread w; // no need to atomically claim + if ((w = thread) != null) { + thread = null; + LockSupport.unpark(w); } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; + return null; + } + public boolean isReleasable() { + if (thread == null) + return true; + if (Thread.interrupted()) { + int i = interruptControl; + interruptControl = -1; + if (i > 0) + return true; } - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncWhenComplete(t, ex, fn, dst)); - else - fn.accept(t, ex); - } catch (Throwable rex) { - dx = rex; + if (deadline != 0L && + (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) { + thread = null; + return true; } - if (e == null || dx != null) - dst.internalComplete(t, ex != null ? ex : dx); + return false; + } + public boolean block() { + if (isReleasable()) + return true; + else if (deadline == 0L) + LockSupport.park(this); + else if (nanos > 0L) + LockSupport.parkNanos(this, nanos); + return isReleasable(); } - helpPostComplete(); - return dst; + final boolean isLive() { return thread != null; } } - private CompletableFuture doHandle - (BiFunction fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - HandleCompletion d = null; + /** + * Returns raw result after waiting, or null if interruptible and + * interrupted. + */ + private Object waitingGet(boolean interruptible) { + Signaller q = null; + boolean queued = false; + int spins = -1; Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new HandleCompletion - (this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; + while ((r = result) == null) { + if (spins < 0) + spins = (Runtime.getRuntime().availableProcessors() > 1) ? + 1 << 8 : 0; // Use brief spin-wait on multiprocessors + else if (spins > 0) { + if (ThreadLocalRandom.nextSecondarySeed() >= 0) + --spins; + } + else if (q == null) + q = new Signaller(interruptible, 0L, 0L); + else if (!queued) + queued = tryPushStack(q); + else if (interruptible && q.interruptControl < 0) { + q.thread = null; + cleanStack(); + return null; + } + else if (q.thread != null && result == null) { + try { + ForkJoinPool.managedBlock(q); + } catch (InterruptedException ie) { + q.interruptControl = -1; + } } } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; + if (q != null) { + q.thread = null; + if (q.interruptControl < 0) { + if (interruptible) + r = null; // report interruption + else + Thread.currentThread().interrupt(); } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; + } + postComplete(); + return r; + } + + /** + * Returns raw result after waiting, or null if interrupted, or + * throws TimeoutException on timeout. + */ + private Object timedGet(long nanos) throws TimeoutException { + if (Thread.interrupted()) + return null; + if (nanos <= 0L) + throw new TimeoutException(); + long d = System.nanoTime() + nanos; + Signaller q = new Signaller(true, nanos, d == 0L ? 1L : d); // avoid 0 + boolean queued = false; + Object r; + // We intentionally don't spin here (as waitingGet does) because + // the call to nanoTime() above acts much like a spin. + while ((r = result) == null) { + if (!queued) + queued = tryPushStack(q); + else if (q.interruptControl < 0 || q.nanos <= 0L) { + q.thread = null; + cleanStack(); + if (q.interruptControl < 0) + return null; + throw new TimeoutException(); } - U u = null; - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncCombine(t, ex, fn, dst)); - else { - u = fn.apply(t, ex); - dx = null; + else if (q.thread != null && result == null) { + try { + ForkJoinPool.managedBlock(q); + } catch (InterruptedException ie) { + q.interruptControl = -1; } - } catch (Throwable rex) { - dx = rex; - u = null; } - if (e == null || dx != null) - dst.internalComplete(u, dx); } - helpPostComplete(); - return dst; + if (q.interruptControl < 0) + r = null; + q.thread = null; + postComplete(); + return r; } - - // public methods + /* ------------- public methods -------------- */ /** * Creates a new incomplete CompletableFuture. @@ -2113,6 +1785,13 @@ public class CompletableFuture implements Future, CompletionStage { public CompletableFuture() { } + /** + * Creates a new complete CompletableFuture with given encoded result. + */ + private CompletableFuture(Object r) { + this.result = r; + } + /** * Returns a new CompletableFuture that is asynchronously completed * by a task running in the {@link ForkJoinPool#commonPool()} with @@ -2124,10 +1803,7 @@ public class CompletableFuture implements Future, CompletionStage { * @return the new CompletableFuture */ public static CompletableFuture supplyAsync(Supplier supplier) { - if (supplier == null) throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(ForkJoinPool.commonPool(), new AsyncSupply(supplier, f)); - return f; + return asyncSupplyStage(asyncPool, supplier); } /** @@ -2143,11 +1819,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public static CompletableFuture supplyAsync(Supplier supplier, Executor executor) { - if (executor == null || supplier == null) - throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(executor, new AsyncSupply(supplier, f)); - return f; + return asyncSupplyStage(screenExecutor(executor), supplier); } /** @@ -2160,10 +1832,7 @@ public class CompletableFuture implements Future, CompletionStage { * @return the new CompletableFuture */ public static CompletableFuture runAsync(Runnable runnable) { - if (runnable == null) throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(ForkJoinPool.commonPool(), new AsyncRun(runnable, f)); - return f; + return asyncRunStage(asyncPool, runnable); } /** @@ -2178,11 +1847,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public static CompletableFuture runAsync(Runnable runnable, Executor executor) { - if (executor == null || runnable == null) - throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(executor, new AsyncRun(runnable, f)); - return f; + return asyncRunStage(screenExecutor(executor), runnable); } /** @@ -2194,9 +1859,7 @@ public class CompletableFuture implements Future, CompletionStage { * @return the completed CompletableFuture */ public static CompletableFuture completedFuture(U value) { - CompletableFuture f = new CompletableFuture(); - f.result = (value == null) ? NIL : value; - return f; + return new CompletableFuture((value == null) ? NIL : value); } /** @@ -2220,21 +1883,8 @@ public class CompletableFuture implements Future, CompletionStage { * while waiting */ public T get() throws InterruptedException, ExecutionException { - Object r; Throwable ex, cause; - if ((r = result) == null && (r = waitingGet(true)) == null) - throw new InterruptedException(); - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if ((ex instanceof CompletionException) && - (cause = ex.getCause()) != null) - ex = cause; - throw new ExecutionException(ex); + Object r; + return reportGet((r = result) == null ? waitingGet(true) : r); } /** @@ -2252,24 +1902,9 @@ public class CompletableFuture implements Future, CompletionStage { */ public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - Object r; Throwable ex, cause; + Object r; long nanos = unit.toNanos(timeout); - if (Thread.interrupted()) - throw new InterruptedException(); - if ((r = result) == null) - r = timedAwaitDone(nanos); - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if ((ex instanceof CompletionException) && - (cause = ex.getCause()) != null) - ex = cause; - throw new ExecutionException(ex); + return reportGet((r = result) == null ? timedGet(nanos) : r); } /** @@ -2287,20 +1922,8 @@ public class CompletableFuture implements Future, CompletionStage { * exceptionally or a completion computation threw an exception */ public T join() { - Object r; Throwable ex; - if ((r = result) == null) - r = waitingGet(false); - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if (ex instanceof CompletionException) - throw (CompletionException)ex; - throw new CompletionException(ex); + Object r; + return reportJoin((r = result) == null ? waitingGet(false) : r); } /** @@ -2314,20 +1937,8 @@ public class CompletableFuture implements Future, CompletionStage { * exceptionally or a completion computation threw an exception */ public T getNow(T valueIfAbsent) { - Object r; Throwable ex; - if ((r = result) == null) - return valueIfAbsent; - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if (ex instanceof CompletionException) - throw (CompletionException)ex; - throw new CompletionException(ex); + Object r; + return ((r = result) == null) ? valueIfAbsent : reportJoin(r); } /** @@ -2339,9 +1950,7 @@ public class CompletableFuture implements Future, CompletionStage { * to transition to a completed state, else {@code false} */ public boolean complete(T value) { - boolean triggered = result == null && - UNSAFE.compareAndSwapObject(this, RESULT, null, - value == null ? NIL : value); + boolean triggered = completeValue(value); postComplete(); return triggered; } @@ -2356,244 +1965,200 @@ public class CompletableFuture implements Future, CompletionStage { */ public boolean completeExceptionally(Throwable ex) { if (ex == null) throw new NullPointerException(); - boolean triggered = result == null && - UNSAFE.compareAndSwapObject(this, RESULT, null, new AltResult(ex)); + boolean triggered = internalComplete(new AltResult(ex)); postComplete(); return triggered; } - // CompletionStage methods - - public CompletableFuture thenApply - (Function fn) { - return doThenApply(fn, null); + public CompletableFuture thenApply( + Function fn) { + return uniApplyStage(null, fn); } - public CompletableFuture thenApplyAsync - (Function fn) { - return doThenApply(fn, ForkJoinPool.commonPool()); + public CompletableFuture thenApplyAsync( + Function fn) { + return uniApplyStage(asyncPool, fn); } - public CompletableFuture thenApplyAsync - (Function fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenApply(fn, executor); + public CompletableFuture thenApplyAsync( + Function fn, Executor executor) { + return uniApplyStage(screenExecutor(executor), fn); } - public CompletableFuture thenAccept - (Consumer action) { - return doThenAccept(action, null); + public CompletableFuture thenAccept(Consumer action) { + return uniAcceptStage(null, action); } - public CompletableFuture thenAcceptAsync - (Consumer action) { - return doThenAccept(action, ForkJoinPool.commonPool()); + public CompletableFuture thenAcceptAsync(Consumer action) { + return uniAcceptStage(asyncPool, action); } - public CompletableFuture thenAcceptAsync - (Consumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenAccept(action, executor); + public CompletableFuture thenAcceptAsync(Consumer action, + Executor executor) { + return uniAcceptStage(screenExecutor(executor), action); } - public CompletableFuture thenRun - (Runnable action) { - return doThenRun(action, null); + public CompletableFuture thenRun(Runnable action) { + return uniRunStage(null, action); } - public CompletableFuture thenRunAsync - (Runnable action) { - return doThenRun(action, ForkJoinPool.commonPool()); + public CompletableFuture thenRunAsync(Runnable action) { + return uniRunStage(asyncPool, action); } - public CompletableFuture thenRunAsync - (Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenRun(action, executor); + public CompletableFuture thenRunAsync(Runnable action, + Executor executor) { + return uniRunStage(screenExecutor(executor), action); } - public CompletableFuture thenCombine - (CompletionStage other, - BiFunction fn) { - return doThenCombine(other.toCompletableFuture(), fn, null); + public CompletableFuture thenCombine( + CompletionStage other, + BiFunction fn) { + return biApplyStage(null, other, fn); } - public CompletableFuture thenCombineAsync - (CompletionStage other, - BiFunction fn) { - return doThenCombine(other.toCompletableFuture(), fn, - ForkJoinPool.commonPool()); + public CompletableFuture thenCombineAsync( + CompletionStage other, + BiFunction fn) { + return biApplyStage(asyncPool, other, fn); } - public CompletableFuture thenCombineAsync - (CompletionStage other, - BiFunction fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenCombine(other.toCompletableFuture(), fn, executor); + public CompletableFuture thenCombineAsync( + CompletionStage other, + BiFunction fn, Executor executor) { + return biApplyStage(screenExecutor(executor), other, fn); } - public CompletableFuture thenAcceptBoth - (CompletionStage other, - BiConsumer action) { - return doThenAcceptBoth(other.toCompletableFuture(), action, null); + public CompletableFuture thenAcceptBoth( + CompletionStage other, + BiConsumer action) { + return biAcceptStage(null, other, action); } - public CompletableFuture thenAcceptBothAsync - (CompletionStage other, - BiConsumer action) { - return doThenAcceptBoth(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture thenAcceptBothAsync( + CompletionStage other, + BiConsumer action) { + return biAcceptStage(asyncPool, other, action); } - public CompletableFuture thenAcceptBothAsync - (CompletionStage other, - BiConsumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenAcceptBoth(other.toCompletableFuture(), action, executor); + public CompletableFuture thenAcceptBothAsync( + CompletionStage other, + BiConsumer action, Executor executor) { + return biAcceptStage(screenExecutor(executor), other, action); } - public CompletableFuture runAfterBoth - (CompletionStage other, - Runnable action) { - return doRunAfterBoth(other.toCompletableFuture(), action, null); + public CompletableFuture runAfterBoth(CompletionStage other, + Runnable action) { + return biRunStage(null, other, action); } - public CompletableFuture runAfterBothAsync - (CompletionStage other, - Runnable action) { - return doRunAfterBoth(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture runAfterBothAsync(CompletionStage other, + Runnable action) { + return biRunStage(asyncPool, other, action); } - public CompletableFuture runAfterBothAsync - (CompletionStage other, - Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doRunAfterBoth(other.toCompletableFuture(), action, executor); + public CompletableFuture runAfterBothAsync(CompletionStage other, + Runnable action, + Executor executor) { + return biRunStage(screenExecutor(executor), other, action); } - - public CompletableFuture applyToEither - (CompletionStage other, - Function fn) { - return doApplyToEither(other.toCompletableFuture(), fn, null); + public CompletableFuture applyToEither( + CompletionStage other, Function fn) { + return orApplyStage(null, other, fn); } - public CompletableFuture applyToEitherAsync - (CompletionStage other, - Function fn) { - return doApplyToEither(other.toCompletableFuture(), fn, - ForkJoinPool.commonPool()); + public CompletableFuture applyToEitherAsync( + CompletionStage other, Function fn) { + return orApplyStage(asyncPool, other, fn); } - public CompletableFuture applyToEitherAsync - (CompletionStage other, - Function fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doApplyToEither(other.toCompletableFuture(), fn, executor); + public CompletableFuture applyToEitherAsync( + CompletionStage other, Function fn, + Executor executor) { + return orApplyStage(screenExecutor(executor), other, fn); } - public CompletableFuture acceptEither - (CompletionStage other, - Consumer action) { - return doAcceptEither(other.toCompletableFuture(), action, null); + public CompletableFuture acceptEither( + CompletionStage other, Consumer action) { + return orAcceptStage(null, other, action); } - public CompletableFuture acceptEitherAsync - (CompletionStage other, - Consumer action) { - return doAcceptEither(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture acceptEitherAsync( + CompletionStage other, Consumer action) { + return orAcceptStage(asyncPool, other, action); } - public CompletableFuture acceptEitherAsync - (CompletionStage other, - Consumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doAcceptEither(other.toCompletableFuture(), action, executor); + public CompletableFuture acceptEitherAsync( + CompletionStage other, Consumer action, + Executor executor) { + return orAcceptStage(screenExecutor(executor), other, action); } public CompletableFuture runAfterEither(CompletionStage other, Runnable action) { - return doRunAfterEither(other.toCompletableFuture(), action, null); + return orRunStage(null, other, action); } - public CompletableFuture runAfterEitherAsync - (CompletionStage other, - Runnable action) { - return doRunAfterEither(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture runAfterEitherAsync(CompletionStage other, + Runnable action) { + return orRunStage(asyncPool, other, action); } - public CompletableFuture runAfterEitherAsync - (CompletionStage other, - Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doRunAfterEither(other.toCompletableFuture(), action, executor); + public CompletableFuture runAfterEitherAsync(CompletionStage other, + Runnable action, + Executor executor) { + return orRunStage(screenExecutor(executor), other, action); } - public CompletableFuture thenCompose - (Function> fn) { - return doThenCompose(fn, null); + public CompletableFuture thenCompose( + Function> fn) { + return uniComposeStage(null, fn); } - public CompletableFuture thenComposeAsync - (Function> fn) { - return doThenCompose(fn, ForkJoinPool.commonPool()); + public CompletableFuture thenComposeAsync( + Function> fn) { + return uniComposeStage(asyncPool, fn); } - public CompletableFuture thenComposeAsync - (Function> fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenCompose(fn, executor); + public CompletableFuture thenComposeAsync( + Function> fn, + Executor executor) { + return uniComposeStage(screenExecutor(executor), fn); } - public CompletableFuture whenComplete - (BiConsumer action) { - return doWhenComplete(action, null); + public CompletableFuture whenComplete( + BiConsumer action) { + return uniWhenCompleteStage(null, action); } - public CompletableFuture whenCompleteAsync - (BiConsumer action) { - return doWhenComplete(action, ForkJoinPool.commonPool()); + public CompletableFuture whenCompleteAsync( + BiConsumer action) { + return uniWhenCompleteStage(asyncPool, action); } - public CompletableFuture whenCompleteAsync - (BiConsumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doWhenComplete(action, executor); + public CompletableFuture whenCompleteAsync( + BiConsumer action, Executor executor) { + return uniWhenCompleteStage(screenExecutor(executor), action); } - public CompletableFuture handle - (BiFunction fn) { - return doHandle(fn, null); + public CompletableFuture handle( + BiFunction fn) { + return uniHandleStage(null, fn); } - public CompletableFuture handleAsync - (BiFunction fn) { - return doHandle(fn, ForkJoinPool.commonPool()); + public CompletableFuture handleAsync( + BiFunction fn) { + return uniHandleStage(asyncPool, fn); } - public CompletableFuture handleAsync - (BiFunction fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doHandle(fn, executor); + public CompletableFuture handleAsync( + BiFunction fn, Executor executor) { + return uniHandleStage(screenExecutor(executor), fn); } /** - * Returns this CompletableFuture + * Returns this CompletableFuture. * * @return this CompletableFuture */ @@ -2618,52 +2183,13 @@ public class CompletableFuture implements Future, CompletionStage { * exceptionally * @return the new CompletableFuture */ - public CompletableFuture exceptionally - (Function fn) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ExceptionCompletion d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new ExceptionCompletion - (this, fn, dst)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t = null; Throwable ex, dx = null; - if (r instanceof AltResult) { - if ((ex = ((AltResult)r).ex) != null) { - try { - t = fn.apply(ex); - } catch (Throwable rex) { - dx = rex; - } - } - } - else { - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - dst.internalComplete(t, dx); - } - helpPostComplete(); - return dst; + public CompletableFuture exceptionally( + Function fn) { + return uniExceptionallyStage(fn); } /* ------------- Arbitrary-arity constructions -------------- */ - /* - * The basic plan of attack is to recursively form binary - * completion trees of elements. This can be overkill for small - * sets, but scales nicely. The And/All vs Or/Any forms use the - * same idea, but details differ. - */ - /** * Returns a new CompletableFuture that is completed when all of * the given CompletableFutures complete. If any of the given @@ -2688,82 +2214,7 @@ public class CompletableFuture implements Future, CompletionStage { * {@code null} */ public static CompletableFuture allOf(CompletableFuture... cfs) { - int len = cfs.length; // Directly handle empty and singleton cases - if (len > 1) - return allTree(cfs, 0, len - 1); - else { - CompletableFuture dst = new CompletableFuture(); - CompletableFuture f; - if (len == 0) - dst.result = NIL; - else if ((f = cfs[0]) == null) - throw new NullPointerException(); - else { - ThenPropagate d = null; - CompletionNode p = null; - Object r; - while ((r = f.result) == null) { - if (d == null) - d = new ThenPropagate(f, dst); - else if (p == null) - p = new CompletionNode(d); - else if (UNSAFE.compareAndSwapObject - (f, COMPLETIONS, p.next = f.completions, p)) - break; - } - if (r != null && (d == null || d.compareAndSet(0, 1))) - dst.internalComplete(null, (r instanceof AltResult) ? - ((AltResult)r).ex : null); - f.helpPostComplete(); - } - return dst; - } - } - - /** - * Recursively constructs an And'ed tree of CompletableFutures. - * Called only when array known to have at least two elements. - */ - private static CompletableFuture allTree(CompletableFuture[] cfs, - int lo, int hi) { - CompletableFuture fst, snd; - int mid = (lo + hi) >>> 1; - if ((fst = (lo == mid ? cfs[lo] : allTree(cfs, lo, mid))) == null || - (snd = (hi == mid+1 ? cfs[hi] : allTree(cfs, mid+1, hi))) == null) - throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - AndCompletion d = null; - CompletionNode p = null, q = null; - Object r = null, s = null; - while ((r = fst.result) == null || (s = snd.result) == null) { - if (d == null) - d = new AndCompletion(fst, snd, dst); - else if (p == null) - p = new CompletionNode(d); - else if (q == null) { - if (UNSAFE.compareAndSwapObject - (fst, COMPLETIONS, p.next = fst.completions, p)) - q = new CompletionNode(d); - } - else if (UNSAFE.compareAndSwapObject - (snd, COMPLETIONS, q.next = snd.completions, q)) - break; - } - if ((r != null || (r = fst.result) != null) && - (s != null || (s = snd.result) != null) && - (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - dst.internalComplete(null, ex); - } - fst.helpPostComplete(); - snd.helpPostComplete(); - return dst; + return andTree(cfs, 0, cfs.length - 1); } /** @@ -2782,92 +2233,7 @@ public class CompletableFuture implements Future, CompletionStage { * {@code null} */ public static CompletableFuture anyOf(CompletableFuture... cfs) { - int len = cfs.length; // Same idea as allOf - if (len > 1) - return anyTree(cfs, 0, len - 1); - else { - CompletableFuture dst = new CompletableFuture(); - CompletableFuture f; - if (len == 0) - ; // skip - else if ((f = cfs[0]) == null) - throw new NullPointerException(); - else { - ThenCopy d = null; - CompletionNode p = null; - Object r; - while ((r = f.result) == null) { - if (d == null) - d = new ThenCopy(f, dst); - else if (p == null) - p = new CompletionNode(d); - else if (UNSAFE.compareAndSwapObject - (f, COMPLETIONS, p.next = f.completions, p)) - break; - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; Object t; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - t = r; - } - dst.internalComplete(t, ex); - } - f.helpPostComplete(); - } - return dst; - } - } - - /** - * Recursively constructs an Or'ed tree of CompletableFutures. - */ - private static CompletableFuture anyTree(CompletableFuture[] cfs, - int lo, int hi) { - CompletableFuture fst, snd; - int mid = (lo + hi) >>> 1; - if ((fst = (lo == mid ? cfs[lo] : anyTree(cfs, lo, mid))) == null || - (snd = (hi == mid+1 ? cfs[hi] : anyTree(cfs, mid+1, hi))) == null) - throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - OrCompletion d = null; - CompletionNode p = null, q = null; - Object r; - while ((r = fst.result) == null && (r = snd.result) == null) { - if (d == null) - d = new OrCompletion(fst, snd, dst); - else if (p == null) - p = new CompletionNode(d); - else if (q == null) { - if (UNSAFE.compareAndSwapObject - (fst, COMPLETIONS, p.next = fst.completions, p)) - q = new CompletionNode(d); - } - else if (UNSAFE.compareAndSwapObject - (snd, COMPLETIONS, q.next = snd.completions, q)) - break; - } - if ((r != null || (r = fst.result) != null || - (r = snd.result) != null) && - (d == null || d.compareAndSet(0, 1))) { - Throwable ex; Object t; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - t = r; - } - dst.internalComplete(t, ex); - } - fst.helpPostComplete(); - snd.helpPostComplete(); - return dst; + return orTree(cfs, 0, cfs.length - 1); } /* ------------- Control and status methods -------------- */ @@ -2887,8 +2253,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public boolean cancel(boolean mayInterruptIfRunning) { boolean cancelled = (result == null) && - UNSAFE.compareAndSwapObject - (this, RESULT, null, new AltResult(new CancellationException())); + internalComplete(new AltResult(new CancellationException())); postComplete(); return cancelled || isCancelled(); } @@ -2940,11 +2305,12 @@ public class CompletableFuture implements Future, CompletionStage { * Forcibly causes subsequent invocations of method {@link #get()} * and related methods to throw the given exception, whether or * not already completed. This method is designed for use only in - * recovery actions, and even in such situations may result in - * ongoing dependent completions using established versus + * error recovery actions, and even in such situations may result + * in ongoing dependent completions using established versus * overwritten outcomes. * * @param ex the exception + * @throws NullPointerException if the exception is null */ public void obtrudeException(Throwable ex) { if (ex == null) throw new NullPointerException(); @@ -2962,7 +2328,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public int getNumberOfDependents() { int count = 0; - for (CompletionNode p = completions; p != null; p = p.next) + for (Completion p = stack; p != null; p = p.next) ++count; return count; } @@ -2993,20 +2359,19 @@ public class CompletableFuture implements Future, CompletionStage { // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long RESULT; - private static final long WAITERS; - private static final long COMPLETIONS; + private static final long STACK; + private static final long NEXT; static { try { - UNSAFE = sun.misc.Unsafe.getUnsafe(); + final sun.misc.Unsafe u; + UNSAFE = u = sun.misc.Unsafe.getUnsafe(); Class k = CompletableFuture.class; - RESULT = UNSAFE.objectFieldOffset - (k.getDeclaredField("result")); - WAITERS = UNSAFE.objectFieldOffset - (k.getDeclaredField("waiters")); - COMPLETIONS = UNSAFE.objectFieldOffset - (k.getDeclaredField("completions")); - } catch (Exception e) { - throw new Error(e); + RESULT = u.objectFieldOffset(k.getDeclaredField("result")); + STACK = u.objectFieldOffset(k.getDeclaredField("stack")); + NEXT = u.objectFieldOffset + (Completion.class.getDeclaredField("next")); + } catch (Exception x) { + throw new Error(x); } } } diff --git a/src/share/classes/java/util/concurrent/CompletionStage.java b/src/share/classes/java/util/concurrent/CompletionStage.java index 6de60980cffbd5a1ac7988aaf6151eb58cc38279..304ede5db506627bbf7f3917414a12521b9908c0 100644 --- a/src/share/classes/java/util/concurrent/CompletionStage.java +++ b/src/share/classes/java/util/concurrent/CompletionStage.java @@ -407,7 +407,7 @@ public interface CompletionStage { /** * Returns a new CompletionStage that, when this and the other * given stage complete normally, executes the given action using - * the supplied executor + * the supplied executor. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -569,7 +569,7 @@ public interface CompletionStage { /** * Returns a new CompletionStage that, when either this or the * other given stage complete normally, executes the given action - * using supplied executor. + * using the supplied executor. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -649,10 +649,15 @@ public interface CompletionStage { (Function fn); /** - * Returns a new CompletionStage with the same result or exception - * as this stage, and when this stage completes, executes the - * given action with the result (or {@code null} if none) and the - * exception (or {@code null} if none) of this stage. + * Returns a new CompletionStage with the same result or exception as + * this stage, that executes the given action when this stage completes. + * + *

    When this stage is complete, the given action is invoked with the + * result (or {@code null} if none) and the exception (or {@code null} + * if none) of this stage as arguments. The returned stage is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned stage exceptionally completes with this + * exception unless this stage also completed exceptionally. * * @param action the action to perform * @return the new CompletionStage @@ -661,12 +666,16 @@ public interface CompletionStage { (BiConsumer action); /** - * Returns a new CompletionStage with the same result or exception - * as this stage, and when this stage completes, executes the - * given action executes the given action using this stage's - * default asynchronous execution facility, with the result (or - * {@code null} if none) and the exception (or {@code null} if - * none) of this stage as arguments. + * Returns a new CompletionStage with the same result or exception as + * this stage, that executes the given action using this stage's + * default asynchronous execution facility when this stage completes. + * + *

    When this stage is complete, the given action is invoked with the + * result (or {@code null} if none) and the exception (or {@code null} + * if none) of this stage as arguments. The returned stage is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned stage exceptionally completes with this + * exception unless this stage also completed exceptionally. * * @param action the action to perform * @return the new CompletionStage @@ -675,11 +684,16 @@ public interface CompletionStage { (BiConsumer action); /** - * Returns a new CompletionStage with the same result or exception - * as this stage, and when this stage completes, executes using - * the supplied Executor, the given action with the result (or - * {@code null} if none) and the exception (or {@code null} if - * none) of this stage as arguments. + * Returns a new CompletionStage with the same result or exception as + * this stage, that executes the given action using the supplied + * Executor when this stage completes. + * + *

    When this stage is complete, the given action is invoked with the + * result (or {@code null} if none) and the exception (or {@code null} + * if none) of this stage as arguments. The returned stage is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned stage exceptionally completes with this + * exception unless this stage also completed exceptionally. * * @param action the action to perform * @param executor the executor to use for asynchronous execution @@ -693,9 +707,11 @@ public interface CompletionStage { * Returns a new CompletionStage that, when this stage completes * either normally or exceptionally, is executed with this stage's * result and exception as arguments to the supplied function. - * The given function is invoked with the result (or {@code null} - * if none) and the exception (or {@code null} if none) of this - * stage when complete as arguments. + * + *

    When this stage is complete, the given function is invoked + * with the result (or {@code null} if none) and the exception (or + * {@code null} if none) of this stage as arguments, and the + * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the * returned CompletionStage @@ -710,9 +726,11 @@ public interface CompletionStage { * either normally or exceptionally, is executed using this stage's * default asynchronous execution facility, with this stage's * result and exception as arguments to the supplied function. - * The given function is invoked with the result (or {@code null} - * if none) and the exception (or {@code null} if none) of this - * stage when complete as arguments. + * + *

    When this stage is complete, the given function is invoked + * with the result (or {@code null} if none) and the exception (or + * {@code null} if none) of this stage as arguments, and the + * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the * returned CompletionStage @@ -726,10 +744,12 @@ public interface CompletionStage { * Returns a new CompletionStage that, when this stage completes * either normally or exceptionally, is executed using the * supplied executor, with this stage's result and exception as - * arguments to the supplied function. The given function is - * invoked with the result (or {@code null} if none) and the - * exception (or {@code null} if none) of this stage when complete - * as arguments. + * arguments to the supplied function. + * + *

    When this stage is complete, the given function is invoked + * with the result (or {@code null} if none) and the exception (or + * {@code null} if none) of this stage as arguments, and the + * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the * returned CompletionStage diff --git a/src/share/classes/java/util/logging/FileHandler.java b/src/share/classes/java/util/logging/FileHandler.java index 4d63b775bbab1c8af62476f24034a8108e0064f6..9699b72b7096f0c4b36ff4ee438023d8db07d3f5 100644 --- a/src/share/classes/java/util/logging/FileHandler.java +++ b/src/share/classes/java/util/logging/FileHandler.java @@ -25,6 +25,7 @@ package java.util.logging; +import static java.nio.file.StandardOpenOption.APPEND; import static java.nio.file.StandardOpenOption.CREATE_NEW; import static java.nio.file.StandardOpenOption.WRITE; @@ -34,10 +35,17 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.channels.FileChannel; +import java.nio.channels.OverlappingFileLockException; import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.nio.file.Paths; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.HashSet; +import java.util.Set; /** * Simple file logging Handler. @@ -149,7 +157,7 @@ public class FileHandler extends StreamHandler { private FileChannel lockFileChannel; private File files[]; private static final int MAX_LOCKS = 100; - private static final java.util.HashMap locks = new java.util.HashMap<>(); + private static final Set locks = new HashSet<>(); /** * A metered stream is a subclass of OutputStream that @@ -428,34 +436,80 @@ public class FileHandler extends StreamHandler { // between processes (and not within a process), we first check // if we ourself already have the file locked. synchronized(locks) { - if (locks.get(lockFileName) != null) { + if (locks.contains(lockFileName)) { // We already own this lock, for a different FileHandler // object. Try again. continue; } - try { - lockFileChannel = FileChannel.open(Paths.get(lockFileName), - CREATE_NEW, WRITE); - } catch (FileAlreadyExistsException ix) { - // try the next lock file name in the sequence - continue; + final Path lockFilePath = Paths.get(lockFileName); + FileChannel channel = null; + int retries = -1; + boolean fileCreated = false; + while (channel == null && retries++ < 1) { + try { + channel = FileChannel.open(lockFilePath, + CREATE_NEW, WRITE); + fileCreated = true; + } catch (FileAlreadyExistsException ix) { + // This may be a zombie file left over by a previous + // execution. Reuse it - but only if we can actually + // write to its directory. + // Note that this is a situation that may happen, + // but not too frequently. + if (Files.isRegularFile(lockFilePath, LinkOption.NOFOLLOW_LINKS) + && Files.isWritable(lockFilePath.getParent())) { + try { + channel = FileChannel.open(lockFilePath, + WRITE, APPEND); + } catch (NoSuchFileException x) { + // Race condition - retry once, and if that + // fails again just try the next name in + // the sequence. + continue; + } catch(IOException x) { + // the file may not be writable for us. + // try the next name in the sequence + break; + } + } else { + // at this point channel should still be null. + // break and try the next name in the sequence. + break; + } + } } + if (channel == null) continue; // try the next name; + lockFileChannel = channel; + boolean available; try { available = lockFileChannel.tryLock() != null; // We got the lock OK. + // At this point we could call File.deleteOnExit(). + // However, this could have undesirable side effects + // as indicated by JDK-4872014. So we will instead + // rely on the fact that close() will remove the lock + // file and that whoever is creating FileHandlers should + // be responsible for closing them. } catch (IOException ix) { // We got an IOException while trying to get the lock. // This normally indicates that locking is not supported // on the target directory. We have to proceed without - // getting a lock. Drop through. - available = true; + // getting a lock. Drop through, but only if we did + // create the file... + available = fileCreated; + } catch (OverlappingFileLockException x) { + // someone already locked this file in this VM, through + // some other channel - that is - using something else + // than new FileHandler(...); + // continue searching for an available lock. + available = false; } if (available) { // We got the lock. Remember it. - locks.put(lockFileName, lockFileName); + locks.add(lockFileName); break; } diff --git a/src/share/classes/java/util/stream/ForEachOps.java b/src/share/classes/java/util/stream/ForEachOps.java index 2c343fbc3c121eb9a14c90288ef068963d36c56d..b527f054f4d85bc5f7cd9ddd24ff401171e988ae 100644 --- a/src/share/classes/java/util/stream/ForEachOps.java +++ b/src/share/classes/java/util/stream/ForEachOps.java @@ -32,6 +32,7 @@ import java.util.concurrent.ForkJoinTask; import java.util.function.Consumer; import java.util.function.DoubleConsumer; import java.util.function.IntConsumer; +import java.util.function.IntFunction; import java.util.function.LongConsumer; /** @@ -317,12 +318,55 @@ final class ForEachOps { */ @SuppressWarnings("serial") static final class ForEachOrderedTask extends CountedCompleter { + /* + * Our goal is to ensure that the elements associated with a task are + * processed according to an in-order traversal of the computation tree. + * We use completion counts for representing these dependencies, so that + * a task does not complete until all the tasks preceding it in this + * order complete. We use the "completion map" to associate the next + * task in this order for any left child. We increase the pending count + * of any node on the right side of such a mapping by one to indicate + * its dependency, and when a node on the left side of such a mapping + * completes, it decrements the pending count of its corresponding right + * side. As the computation tree is expanded by splitting, we must + * atomically update the mappings to maintain the invariant that the + * completion map maps left children to the next node in the in-order + * traversal. + * + * Take, for example, the following computation tree of tasks: + * + * a + * / \ + * b c + * / \ / \ + * d e f g + * + * The complete map will contain (not necessarily all at the same time) + * the following associations: + * + * d -> e + * b -> f + * f -> g + * + * Tasks e, f, g will have their pending counts increased by 1. + * + * The following relationships hold: + * + * - completion of d "happens-before" e; + * - completion of d and e "happens-before b; + * - completion of b "happens-before" f; and + * - completion of f "happens-before" g + * + * Thus overall the "happens-before" relationship holds for the + * reporting of elements, covered by tasks d, e, f and g, as specified + * by the forEachOrdered operation. + */ + private final PipelineHelper helper; private Spliterator spliterator; private final long targetSize; private final ConcurrentHashMap, ForEachOrderedTask> completionMap; private final Sink action; - private final Object lock; private final ForEachOrderedTask leftPredecessor; private Node node; @@ -333,9 +377,9 @@ final class ForEachOps { this.helper = helper; this.spliterator = spliterator; this.targetSize = AbstractTask.suggestTargetSize(spliterator.estimateSize()); - this.completionMap = new ConcurrentHashMap<>(); + // Size map to avoid concurrent re-sizes + this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.LEAF_TARGET << 1)); this.action = action; - this.lock = new Object(); this.leftPredecessor = null; } @@ -348,7 +392,6 @@ final class ForEachOps { this.targetSize = parent.targetSize; this.completionMap = parent.completionMap; this.action = parent.action; - this.lock = parent.lock; this.leftPredecessor = leftPredecessor; } @@ -367,16 +410,42 @@ final class ForEachOps { new ForEachOrderedTask<>(task, leftSplit, task.leftPredecessor); ForEachOrderedTask rightChild = new ForEachOrderedTask<>(task, rightSplit, leftChild); + + // Fork the parent task + // Completion of the left and right children "happens-before" + // completion of the parent + task.addToPendingCount(1); + // Completion of the left child "happens-before" completion of + // the right child + rightChild.addToPendingCount(1); task.completionMap.put(leftChild, rightChild); - task.addToPendingCount(1); // forking - rightChild.addToPendingCount(1); // right pending on left child + + // If task is not on the left spine if (task.leftPredecessor != null) { - leftChild.addToPendingCount(1); // left pending on previous subtree, except left spine - if (task.completionMap.replace(task.leftPredecessor, task, leftChild)) - task.addToPendingCount(-1); // transfer my "right child" count to my left child - else - leftChild.addToPendingCount(-1); // left child is ready to go when ready + /* + * Completion of left-predecessor, or left subtree, + * "happens-before" completion of left-most leaf node of + * right subtree. + * The left child's pending count needs to be updated before + * it is associated in the completion map, otherwise the + * left child can complete prematurely and violate the + * "happens-before" constraint. + */ + leftChild.addToPendingCount(1); + // Update association of left-predecessor to left-most + // leaf node of right subtree + if (task.completionMap.replace(task.leftPredecessor, task, leftChild)) { + // If replaced, adjust the pending count of the parent + // to complete when its children complete + task.addToPendingCount(-1); + } else { + // Left-predecessor has already completed, parent's + // pending count is adjusted by left-predecessor; + // left child is ready to complete + leftChild.addToPendingCount(-1); + } } + ForEachOrderedTask taskToFork; if (forkRight) { forkRight = false; @@ -391,31 +460,49 @@ final class ForEachOps { } taskToFork.fork(); } - if (task.getPendingCount() == 0) { - task.helper.wrapAndCopyInto(task.action, rightSplit); - } - else { + + /* + * Task's pending count is either 0 or 1. If 1 then the completion + * map will contain a value that is task, and two calls to + * tryComplete are required for completion, one below and one + * triggered by the completion of task's left-predecessor in + * onCompletion. Therefore there is no data race within the if + * block. + */ + if (task.getPendingCount() > 0) { + // Cannot complete just yet so buffer elements into a Node + // for use when completion occurs + @SuppressWarnings("unchecked") + IntFunction generator = size -> (T[]) new Object[size]; Node.Builder nb = task.helper.makeNodeBuilder( - task.helper.exactOutputSizeIfKnown(rightSplit), - size -> (T[]) new Object[size]); + task.helper.exactOutputSizeIfKnown(rightSplit), + generator); task.node = task.helper.wrapAndCopyInto(nb, rightSplit).build(); + task.spliterator = null; } task.tryComplete(); } @Override public void onCompletion(CountedCompleter caller) { - spliterator = null; if (node != null) { - // Dump any data from this leaf into the sink - synchronized (lock) { - node.forEach(action); - } + // Dump buffered elements from this leaf into the sink + node.forEach(action); node = null; } - ForEachOrderedTask victim = completionMap.remove(this); - if (victim != null) - victim.tryComplete(); + else if (spliterator != null) { + // Dump elements output from this leaf's pipeline into the sink + helper.wrapAndCopyInto(action, spliterator); + spliterator = null; + } + + // The completion of this task *and* the dumping of elements + // "happens-before" completion of the associated left-most leaf task + // of right subtree (if any, which can be this task's right sibling) + // + ForEachOrderedTask leftDescendant = completionMap.remove(this); + if (leftDescendant != null) + leftDescendant.tryComplete(); } } } diff --git a/src/share/classes/java/util/stream/Nodes.java b/src/share/classes/java/util/stream/Nodes.java index d69b9f61b1a50b6f5b0a37ae429880c059eb7cf7..c18540c4e6e5abf4c42b58f79e8024803fd8cdd3 100644 --- a/src/share/classes/java/util/stream/Nodes.java +++ b/src/share/classes/java/util/stream/Nodes.java @@ -63,7 +63,7 @@ final class Nodes { // IllegalArgumentException messages static final String BAD_SIZE = "Stream size exceeds max array size"; - @SuppressWarnings("raw") + @SuppressWarnings("rawtypes") private static final Node EMPTY_NODE = new EmptyNode.OfRef(); private static final Node.OfInt EMPTY_INT_NODE = new EmptyNode.OfInt(); private static final Node.OfLong EMPTY_LONG_NODE = new EmptyNode.OfLong(); @@ -956,6 +956,7 @@ final class Nodes { * Initiate a stack containing, in left-to-right order, the child nodes * covered by this spliterator */ + @SuppressWarnings("unchecked") protected final Deque initStack() { // Bias size to the case where leaf nodes are close to this node // 8 is the minimum initial capacity for the ArrayDeque implementation @@ -969,6 +970,7 @@ final class Nodes { * Depth first search, in left-to-right order, of the node tree, using * an explicit stack, to find the next non-empty leaf node. */ + @SuppressWarnings("unchecked") protected final N findNextLeafNode(Deque stack) { N n = null; while ((n = stack.pollFirst()) != null) { @@ -984,6 +986,7 @@ final class Nodes { return null; } + @SuppressWarnings("unchecked") protected final boolean initTryAdvance() { if (curNode == null) return false; @@ -1870,6 +1873,7 @@ final class Nodes { } assert task.offset + task.length < MAX_ARRAY_SIZE; + @SuppressWarnings("unchecked") T_SINK sink = (T_SINK) task; task.helper.wrapAndCopyInto(sink, rightSplit); task.propagateCompletion(); @@ -2173,6 +2177,7 @@ final class Nodes { } @Override + @SuppressWarnings("unchecked") protected T_NODE doLeaf() { T_BUILDER builder = builderFactory.apply(helper.exactOutputSizeIfKnown(spliterator)); return (T_NODE) helper.wrapAndCopyInto(builder, spliterator).build(); diff --git a/src/share/classes/java/util/stream/SortedOps.java b/src/share/classes/java/util/stream/SortedOps.java index 810de1ca20ed14c598d3543bdb1a43d0097a86b3..592b609cad57f60c582e64484ed90f2c10fc7371 100644 --- a/src/share/classes/java/util/stream/SortedOps.java +++ b/src/share/classes/java/util/stream/SortedOps.java @@ -29,7 +29,6 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Objects; import java.util.Spliterator; -import java.util.concurrent.ForkJoinTask; import java.util.function.IntFunction; @@ -113,7 +112,9 @@ final class SortedOps { StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED); this.isNaturalSort = true; // Will throw CCE when we try to sort if T is not Comparable - this.comparator = (Comparator) Comparator.naturalOrder(); + @SuppressWarnings("unchecked") + Comparator comp = (Comparator) Comparator.naturalOrder(); + this.comparator = comp; } /** @@ -170,7 +171,7 @@ final class SortedOps { } @Override - public Sink opWrapSink(int flags, Sink sink) { + public Sink opWrapSink(int flags, Sink sink) { Objects.requireNonNull(sink); if (StreamOpFlag.SORTED.isKnown(flags)) @@ -335,6 +336,7 @@ final class SortedOps { } @Override + @SuppressWarnings("unchecked") public void begin(long size) { if (size >= Nodes.MAX_ARRAY_SIZE) throw new IllegalArgumentException(Nodes.BAD_SIZE); diff --git a/src/share/classes/java/util/stream/SpinedBuffer.java b/src/share/classes/java/util/stream/SpinedBuffer.java index 878b2c2899ed9831ea06f5156852cdd11c7a7f3b..163692cf858384118fabdcd0162f54b852e9f8d2 100644 --- a/src/share/classes/java/util/stream/SpinedBuffer.java +++ b/src/share/classes/java/util/stream/SpinedBuffer.java @@ -92,6 +92,7 @@ class SpinedBuffer * @throws IllegalArgumentException if the specified initial capacity * is negative */ + @SuppressWarnings("unchecked") SpinedBuffer(int initialCapacity) { super(initialCapacity); curChunk = (E[]) new Object[1 << initialChunkPower]; @@ -100,6 +101,7 @@ class SpinedBuffer /** * Constructs an empty list with an initial capacity of sixteen. */ + @SuppressWarnings("unchecked") SpinedBuffer() { super(); curChunk = (E[]) new Object[1 << initialChunkPower]; @@ -114,6 +116,7 @@ class SpinedBuffer : priorElementCount[spineIndex] + spine[spineIndex].length; } + @SuppressWarnings("unchecked") private void inflateSpine() { if (spine == null) { spine = (E[][]) new Object[MIN_SPINE_SIZE][]; @@ -125,6 +128,7 @@ class SpinedBuffer /** * Ensure that the buffer has at least capacity to hold the target size */ + @SuppressWarnings("unchecked") protected final void ensureCapacity(long targetSize) { long capacity = capacity(); if (targetSize > capacity) { diff --git a/src/share/classes/java/util/stream/StreamSpliterators.java b/src/share/classes/java/util/stream/StreamSpliterators.java index 7322773fe87ee552742f13be7ba62e47082d500e..67683425bfccefb8f0ed9f1e95bc2d52899d4b4d 100644 --- a/src/share/classes/java/util/stream/StreamSpliterators.java +++ b/src/share/classes/java/util/stream/StreamSpliterators.java @@ -516,6 +516,7 @@ class StreamSpliterators { } @Override + @SuppressWarnings("unchecked") public T_SPLITR trySplit() { return (T_SPLITR) get().trySplit(); } @@ -643,6 +644,7 @@ class StreamSpliterators { // existing and additionally created F/J tasks that perform // redundant work on no elements. while (true) { + @SuppressWarnings("unchecked") T_SPLITR leftSplit = (T_SPLITR) s.trySplit(); if (leftSplit == null) return null; @@ -970,6 +972,7 @@ class StreamSpliterators { // Stop splitting when there are no more limit permits if (permits.get() == 0) return null; + @SuppressWarnings("unchecked") T_SPLITR split = (T_SPLITR) s.trySplit(); return split == null ? null : makeSpliterator(split); } @@ -1068,16 +1071,18 @@ class StreamSpliterators { super(s, skip, limit); } - OfPrimitive(T_SPLITR s, UnorderedSliceSpliterator.OfPrimitive parent) { + OfPrimitive(T_SPLITR s, UnorderedSliceSpliterator.OfPrimitive parent) { super(s, parent); } @Override public boolean tryAdvance(T_CONS action) { Objects.requireNonNull(action); + @SuppressWarnings("unchecked") + T_CONS consumer = (T_CONS) this; while (permitStatus() != PermitStatus.NO_MORE) { - if (!s.tryAdvance((T_CONS) this)) + if (!s.tryAdvance(consumer)) return false; else if (acquirePermits(1) == 1) { acceptConsumed(action); @@ -1316,7 +1321,7 @@ class StreamSpliterators { * estimate size is 0. * *

    The {@code forEachRemaining} method if invoked will never terminate. - * The {@coe tryAdvance} method always returns true. + * The {@code tryAdvance} method always returns true. * */ static abstract class InfiniteSupplyingSpliterator implements Spliterator { diff --git a/src/share/classes/java/util/stream/Streams.java b/src/share/classes/java/util/stream/Streams.java index 41f3adad592d302b11bff4fa45fbd97d2f2041b8..072691aeccba72ff006de94375d27705e65e5ded 100644 --- a/src/share/classes/java/util/stream/Streams.java +++ b/src/share/classes/java/util/stream/Streams.java @@ -715,6 +715,7 @@ final class Streams { @Override public T_SPLITR trySplit() { + @SuppressWarnings("unchecked") T_SPLITR ret = beforeSplit ? aSpliterator : (T_SPLITR) bSpliterator.trySplit(); beforeSplit = false; return ret; diff --git a/src/share/classes/sun/invoke/util/ValueConversions.java b/src/share/classes/sun/invoke/util/ValueConversions.java index e3095fce2d7128373b7ad2ba36595b44925eb21a..64b52f4569a92e08ff1e6afa946661569729b333 100644 --- a/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/src/share/classes/sun/invoke/util/ValueConversions.java @@ -29,38 +29,34 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.EnumMap; -import java.util.List; public class ValueConversions { private static final Class THIS_CLASS = ValueConversions.class; - // Do not adjust this except for special platforms: - private static final int MAX_ARITY; - static { - final Object[] values = { 255 }; - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); - return null; - } - }); - MAX_ARITY = (Integer) values[0]; - } - private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); - private static EnumMap[] newWrapperCaches(int n) { - @SuppressWarnings("unchecked") // generic array creation - EnumMap[] caches - = (EnumMap[]) new EnumMap[n]; + /** Thread-safe canonicalized mapping from Wrapper to MethodHandle + * with unsynchronized reads and synchronized writes. + * It's safe to publish MethodHandles by data race because they are immutable. */ + private static class WrapperCache { + /** EnumMap uses preconstructed array internally, which is constant during it's lifetime. */ + private final EnumMap map = new EnumMap<>(Wrapper.class); + + public MethodHandle get(Wrapper w) { + return map.get(w); + } + public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) { + // Simulate CAS to avoid racy duplication + MethodHandle prev = map.putIfAbsent(w, mh); + if (prev != null) return prev; + return mh; + } + } + + private static WrapperCache[] newWrapperCaches(int n) { + WrapperCache[] caches = new WrapperCache[n]; for (int i = 0; i < n; i++) - caches[i] = new EnumMap<>(Wrapper.class); + caches[i] = new WrapperCache(); return caches; } @@ -71,63 +67,92 @@ public class ValueConversions { // implicit conversions sanctioned by JLS 5.1.2, etc. // explicit conversions as allowed by explicitCastArguments + static int unboxInteger(Integer x) { + return x; + } static int unboxInteger(Object x, boolean cast) { if (x instanceof Integer) - return ((Integer) x).intValue(); + return (Integer) x; return primitiveConversion(Wrapper.INT, x, cast).intValue(); } + static byte unboxByte(Byte x) { + return x; + } static byte unboxByte(Object x, boolean cast) { if (x instanceof Byte) - return ((Byte) x).byteValue(); + return (Byte) x; return primitiveConversion(Wrapper.BYTE, x, cast).byteValue(); } + static short unboxShort(Short x) { + return x; + } static short unboxShort(Object x, boolean cast) { if (x instanceof Short) - return ((Short) x).shortValue(); + return (Short) x; return primitiveConversion(Wrapper.SHORT, x, cast).shortValue(); } + static boolean unboxBoolean(Boolean x) { + return x; + } static boolean unboxBoolean(Object x, boolean cast) { if (x instanceof Boolean) - return ((Boolean) x).booleanValue(); + return (Boolean) x; return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0; } + static char unboxCharacter(Character x) { + return x; + } static char unboxCharacter(Object x, boolean cast) { if (x instanceof Character) - return ((Character) x).charValue(); + return (Character) x; return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue(); } + static long unboxLong(Long x) { + return x; + } static long unboxLong(Object x, boolean cast) { if (x instanceof Long) - return ((Long) x).longValue(); + return (Long) x; return primitiveConversion(Wrapper.LONG, x, cast).longValue(); } + static float unboxFloat(Float x) { + return x; + } static float unboxFloat(Object x, boolean cast) { if (x instanceof Float) - return ((Float) x).floatValue(); + return (Float) x; return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue(); } + static double unboxDouble(Double x) { + return x; + } static double unboxDouble(Object x, boolean cast) { if (x instanceof Double) - return ((Double) x).doubleValue(); + return (Double) x; return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue(); } - private static MethodType unboxType(Wrapper wrap) { + private static MethodType unboxType(Wrapper wrap, int kind) { + if (kind == 0) + return MethodType.methodType(wrap.primitiveType(), wrap.wrapperType()); return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class); } - private static final EnumMap[] - UNBOX_CONVERSIONS = newWrapperCaches(2); + private static final WrapperCache[] UNBOX_CONVERSIONS = newWrapperCaches(4); - private static MethodHandle unbox(Wrapper wrap, boolean cast) { - EnumMap cache = UNBOX_CONVERSIONS[(cast?1:0)]; + private static MethodHandle unbox(Wrapper wrap, int kind) { + // kind 0 -> strongly typed with NPE + // kind 1 -> strongly typed but zero for null, + // kind 2 -> asType rules: accept multiple box types but only widening conversions with NPE + // kind 3 -> explicitCastArguments rules: allow narrowing conversions, zero for null + WrapperCache cache = UNBOX_CONVERSIONS[kind]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; @@ -135,41 +160,59 @@ public class ValueConversions { // slow path switch (wrap) { case OBJECT: - mh = IDENTITY; break; case VOID: - mh = IGNORE; break; - } - if (mh != null) { - cache.put(wrap, mh); - return mh; + throw new IllegalArgumentException("unbox "+wrap); } // look up the method String name = "unbox" + wrap.wrapperSimpleName(); - MethodType type = unboxType(wrap); + MethodType type = unboxType(wrap, kind); try { mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); } catch (ReflectiveOperationException ex) { mh = null; } if (mh != null) { - mh = MethodHandles.insertArguments(mh, 1, cast); - cache.put(wrap, mh); - return mh; + if (kind > 0) { + boolean cast = (kind != 2); + mh = MethodHandles.insertArguments(mh, 1, cast); + } + if (kind == 1) { // casting but exact (null -> zero) + mh = mh.asType(unboxType(wrap, 0)); + } + return cache.put(wrap, mh); } throw new IllegalArgumentException("cannot find unbox adapter for " + wrap - + (cast ? " (cast)" : "")); + + (kind <= 1 ? " (exact)" : kind == 3 ? " (cast)" : "")); } - public static MethodHandle unboxCast(Wrapper type) { - return unbox(type, true); + /** Return an exact unboxer for the given primitive type. */ + public static MethodHandle unboxExact(Wrapper type) { + return unbox(type, 0); + } + + /** Return an exact unboxer for the given primitive type, with optional null-to-zero conversion. + * The boolean says whether to throw an NPE on a null value (false means unbox a zero). + * The type of the unboxer is of a form like (Integer)int. + */ + public static MethodHandle unboxExact(Wrapper type, boolean throwNPE) { + return unbox(type, throwNPE ? 0 : 1); } - public static MethodHandle unbox(Class type) { - return unbox(Wrapper.forPrimitiveType(type), false); + /** Return a widening unboxer for the given primitive type. + * Widen narrower primitive boxes to the given type. + * Do not narrow any primitive values or convert null to zero. + * The type of the unboxer is of a form like (Object)int. + */ + public static MethodHandle unboxWiden(Wrapper type) { + return unbox(type, 2); } - public static MethodHandle unboxCast(Class type) { - return unbox(Wrapper.forPrimitiveType(type), true); + /** Return a casting unboxer for the given primitive type. + * Widen or narrow primitive values to the given type, or convert null to zero, as needed. + * The type of the unboxer is of a form like (Object)int. + */ + public static MethodHandle unboxCast(Wrapper type) { + return unbox(type, 3); } static private final Integer ZERO_INT = 0, ONE_INT = 1; @@ -266,57 +309,26 @@ public class ValueConversions { return MethodType.methodType(boxType, wrap.primitiveType()); } - private static final EnumMap[] - BOX_CONVERSIONS = newWrapperCaches(2); + private static final WrapperCache[] BOX_CONVERSIONS = newWrapperCaches(1); - private static MethodHandle box(Wrapper wrap, boolean exact) { - EnumMap cache = BOX_CONVERSIONS[(exact?1:0)]; + public static MethodHandle boxExact(Wrapper wrap) { + WrapperCache cache = BOX_CONVERSIONS[0]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; } - // slow path - switch (wrap) { - case OBJECT: - mh = IDENTITY; break; - case VOID: - mh = ZERO_OBJECT; - break; - } - if (mh != null) { - cache.put(wrap, mh); - return mh; - } // look up the method String name = "box" + wrap.wrapperSimpleName(); MethodType type = boxType(wrap); - if (exact) { - try { - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); - } catch (ReflectiveOperationException ex) { - mh = null; - } - } else { - mh = box(wrap, !exact).asType(type.erase()); + try { + mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); + } catch (ReflectiveOperationException ex) { + mh = null; } if (mh != null) { - cache.put(wrap, mh); - return mh; + return cache.put(wrap, mh); } - throw new IllegalArgumentException("cannot find box adapter for " - + wrap + (exact ? " (exact)" : "")); - } - - public static MethodHandle box(Class type) { - boolean exact = false; - // e.g., boxShort(short)Short if exact, - // e.g., boxShort(short)Object if !exact - return box(Wrapper.forPrimitiveType(type), exact); - } - - public static MethodHandle box(Wrapper type) { - boolean exact = false; - return box(type, exact); + throw new IllegalArgumentException("cannot find box adapter for " + wrap); } /// Constant functions @@ -348,11 +360,10 @@ public class ValueConversions { return 0; } - private static final EnumMap[] - CONSTANT_FUNCTIONS = newWrapperCaches(2); + private static final WrapperCache[] CONSTANT_FUNCTIONS = newWrapperCaches(2); public static MethodHandle zeroConstantFunction(Wrapper wrap) { - EnumMap cache = CONSTANT_FUNCTIONS[0]; + WrapperCache cache = CONSTANT_FUNCTIONS[0]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; @@ -373,184 +384,37 @@ public class ValueConversions { break; } if (mh != null) { - cache.put(wrap, mh); - return mh; + return cache.put(wrap, mh); } // use zeroInt and cast the result if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) { mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type); - cache.put(wrap, mh); - return mh; + return cache.put(wrap, mh); } throw new IllegalArgumentException("cannot find zero constant for " + wrap); } - /// Converting references to references. - - /** - * Identity function. - * @param x an arbitrary reference value - * @return the same value x - */ - static T identity(T x) { - return x; - } - - static T[] identity(T[] x) { - return x; - } - - /** - * Identity function on ints. - * @param x an arbitrary int value - * @return the same value x - */ - static int identity(int x) { - return x; - } - - static byte identity(byte x) { - return x; - } - - static short identity(short x) { - return x; - } - - static boolean identity(boolean x) { - return x; - } - - static char identity(char x) { - return x; - } - - /** - * Identity function on longs. - * @param x an arbitrary long value - * @return the same value x - */ - static long identity(long x) { - return x; - } - - static float identity(float x) { - return x; - } - - static double identity(double x) { - return x; - } - - private static ClassCastException newClassCastException(Class t, Object obj) { - return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); - } - - private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY, - ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY; + private static final MethodHandle CAST_REFERENCE, IGNORE, EMPTY; static { try { MethodType idType = MethodType.genericMethodType(1); MethodType ignoreType = idType.changeReturnType(void.class); - MethodType zeroObjectType = MethodType.genericMethodType(0); - IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); - ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); - ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class)); - FILL_NEW_ARRAY = IMPL_LOOKUP - .findStatic(THIS_CLASS, "fillNewArray", - MethodType.methodType(Object[].class, Integer.class, Object[].class)); - FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP - .findStatic(THIS_CLASS, "fillNewTypedArray", - MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); } catch (NoSuchMethodException | IllegalAccessException ex) { throw newInternalError("uncaught exception", ex); } } - // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems. - static class LazyStatics { - private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST; - static { - try { - //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class)); - COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class)); - COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class)); - MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError("uncaught exception", ex); - } - } + public static MethodHandle ignore() { + return IGNORE; } - private static final EnumMap[] WRAPPER_CASTS - = newWrapperCaches(1); - - /** Return a method that casts its sole argument (an Object) to the given type - * and returns it as the given type. - */ - public static MethodHandle cast(Class type) { - return cast(type, CAST_REFERENCE); - } - public static MethodHandle cast(Class type, MethodHandle castReference) { - if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); - MethodHandle mh; - Wrapper wrap = null; - EnumMap cache = null; - if (Wrapper.isWrapperType(type)) { - wrap = Wrapper.forWrapperType(type); - cache = WRAPPER_CASTS[0]; - mh = cache.get(wrap); - if (mh != null) return mh; - } - mh = MethodHandles.insertArguments(castReference, 0, type); - if (cache != null) - cache.put(wrap, mh); - return mh; - } - - public static MethodHandle identity() { - return IDENTITY; - } - - public static MethodHandle identity(Class type) { - if (!type.isPrimitive()) - // Reference identity has been moved into MethodHandles: - return MethodHandles.identity(type); - return identity(Wrapper.findPrimitiveType(type)); - } - - public static MethodHandle identity(Wrapper wrap) { - EnumMap cache = CONSTANT_FUNCTIONS[1]; - MethodHandle mh = cache.get(wrap); - if (mh != null) { - return mh; - } - // slow path - MethodType type = MethodType.methodType(wrap.primitiveType()); - if (wrap != Wrapper.VOID) - type = type.appendParameterTypes(wrap.primitiveType()); - try { - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type); - } catch (ReflectiveOperationException ex) { - mh = null; - } - if (mh == null && wrap == Wrapper.VOID) { - mh = EMPTY; // #(){} : #()void - } - if (mh != null) { - cache.put(wrap, mh); - return mh; - } - - if (mh != null) { - cache.put(wrap, mh); - return mh; - } - throw new IllegalArgumentException("cannot find identity for " + wrap); + /** Return a method that casts its second argument (an Object) to the given type (a Class). */ + public static MethodHandle cast() { + return CAST_REFERENCE; } /// Primitive conversions. @@ -759,11 +623,10 @@ public class ValueConversions { return (x ? (byte)1 : (byte)0); } - private static final EnumMap[] - CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length); + private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length); public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) { - EnumMap cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()]; + WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()]; MethodHandle mh = cache.get(wdst); if (mh != null) { return mh; @@ -771,17 +634,9 @@ public class ValueConversions { // slow path Class src = wsrc.primitiveType(); Class dst = wdst.primitiveType(); - MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src); + MethodType type = MethodType.methodType(dst, src); if (wsrc == wdst) { - mh = identity(src); - } else if (wsrc == Wrapper.VOID) { - mh = zeroConstantFunction(wdst); - } else if (wdst == Wrapper.VOID) { - mh = MethodHandles.dropArguments(EMPTY, 0, src); // Defer back to MethodHandles. - } else if (wsrc == Wrapper.OBJECT) { - mh = unboxCast(dst); - } else if (wdst == Wrapper.OBJECT) { - mh = box(src); + mh = MethodHandles.identity(src); } else { assert(src.isPrimitive() && dst.isPrimitive()); try { @@ -792,8 +647,7 @@ public class ValueConversions { } if (mh != null) { assert(mh.type() == type) : mh; - cache.put(wdst, mh); - return mh; + return cache.put(wdst, mh); } throw new IllegalArgumentException("cannot find primitive conversion function for " + @@ -808,363 +662,6 @@ public class ValueConversions { return Character.toUpperCase(x.charAt(0))+x.substring(1); } - /// Collection of multiple arguments. - - public static Object convertArrayElements(Class arrayType, Object array) { - Class src = array.getClass().getComponentType(); - Class dst = arrayType.getComponentType(); - if (src == null || dst == null) throw new IllegalArgumentException("not array type"); - Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null); - Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null); - int length; - if (sw == null) { - Object[] a = (Object[]) array; - length = a.length; - if (dw == null) - return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class)); - Object res = dw.makeArray(length); - dw.copyArrayUnboxing(a, 0, res, 0, length); - return res; - } - length = java.lang.reflect.Array.getLength(array); - Object[] res; - if (dw == null) { - res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class)); - } else { - res = new Object[length]; - } - sw.copyArrayBoxing(array, 0, res, 0, length); - if (dw == null) return res; - Object a = dw.makeArray(length); - dw.copyArrayUnboxing(res, 0, a, 0, length); - return a; - } - - private static MethodHandle findCollector(String name, int nargs, Class rtype, Class... ptypes) { - MethodType type = MethodType.genericMethodType(nargs) - .changeReturnType(rtype) - .insertParameterTypes(0, ptypes); - try { - return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); - } catch (ReflectiveOperationException ex) { - return null; - } - } - - private static final Object[] NO_ARGS_ARRAY = {}; - private static Object[] makeArray(Object... args) { return args; } - private static Object[] array() { return NO_ARGS_ARRAY; } - private static Object[] array(Object a0) - { return makeArray(a0); } - private static Object[] array(Object a0, Object a1) - { return makeArray(a0, a1); } - private static Object[] array(Object a0, Object a1, Object a2) - { return makeArray(a0, a1, a2); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3) - { return makeArray(a0, a1, a2, a3); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4) - { return makeArray(a0, a1, a2, a3, a4); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5) - { return makeArray(a0, a1, a2, a3, a4, a5); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6) - { return makeArray(a0, a1, a2, a3, a4, a5, a6); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7) - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8) - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8, Object a9) - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - private static MethodHandle[] makeArrays() { - ArrayList mhs = new ArrayList<>(); - for (;;) { - MethodHandle mh = findCollector("array", mhs.size(), Object[].class); - if (mh == null) break; - mhs.add(mh); - } - assert(mhs.size() == 11); // current number of methods - return mhs.toArray(new MethodHandle[MAX_ARITY+1]); - } - private static final MethodHandle[] ARRAYS = makeArrays(); - - // filling versions of the above: - // using Integer len instead of int len and no varargs to avoid bootstrapping problems - private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { - Object[] a = new Object[len]; - fillWithArguments(a, 0, args); - return a; - } - private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { - Object[] a = Arrays.copyOf(example, len); - fillWithArguments(a, 0, args); - return a; - } - private static void fillWithArguments(Object[] a, int pos, Object... args) { - System.arraycopy(args, 0, a, pos, args.length); - } - // using Integer pos instead of int pos to avoid bootstrapping problems - private static Object[] fillArray(Integer pos, Object[] a, Object a0) - { fillWithArguments(a, pos, a0); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) - { fillWithArguments(a, pos, a0, a1); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) - { fillWithArguments(a, pos, a0, a1, a2); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) - { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8, Object a9) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } - private static MethodHandle[] makeFillArrays() { - ArrayList mhs = new ArrayList<>(); - mhs.add(null); // there is no empty fill; at least a0 is required - for (;;) { - MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class); - if (mh == null) break; - mhs.add(mh); - } - assert(mhs.size() == 11); // current number of methods - return mhs.toArray(new MethodHandle[0]); - } - private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); - - private static Object[] copyAsReferenceArray(Class arrayType, Object... a) { - return Arrays.copyOf(a, a.length, arrayType); - } - private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { - Object a = w.makeArray(boxes.length); - w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); - return a; - } - - /** Return a method handle that takes the indicated number of Object - * arguments and returns an Object array of them, as if for varargs. - */ - public static MethodHandle varargsArray(int nargs) { - MethodHandle mh = ARRAYS[nargs]; - if (mh != null) return mh; - mh = findCollector("array", nargs, Object[].class); - if (mh != null) return ARRAYS[nargs] = mh; - mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs); - assert(assertCorrectArity(mh, nargs)); - return ARRAYS[nargs] = mh; - } - - private static boolean assertCorrectArity(MethodHandle mh, int arity) { - assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; - return true; - } - - private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) { - // Build up the result mh as a sequence of fills like this: - // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23)) - // The various fill(_,10*I,___*[J]) are reusable. - int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately - int rightLen = nargs - leftLen; - MethodHandle leftCollector = newArray.bindTo(nargs); - leftCollector = leftCollector.asCollector(Object[].class, leftLen); - MethodHandle mh = finisher; - if (rightLen > 0) { - MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); - if (mh == ARRAY_IDENTITY) - mh = rightFiller; - else - mh = MethodHandles.collectArguments(mh, 0, rightFiller); - } - if (mh == ARRAY_IDENTITY) - mh = leftCollector; - else - mh = MethodHandles.collectArguments(mh, 0, leftCollector); - return mh; - } - - private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); - private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; - /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) - * fills a[L]..a[N-1] with corresponding arguments, - * and then returns a. The value L is a global constant (LEFT_ARGS). - */ - private static MethodHandle fillToRight(int nargs) { - MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; - if (filler != null) return filler; - filler = buildFiller(nargs); - assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); - return FILL_ARRAY_TO_RIGHT[nargs] = filler; - } - private static MethodHandle buildFiller(int nargs) { - if (nargs <= LEFT_ARGS) - return ARRAY_IDENTITY; // no args to fill; return the array unchanged - // we need room for both mh and a in mh.invoke(a, arg*[nargs]) - final int CHUNK = LEFT_ARGS; - int rightLen = nargs % CHUNK; - int midLen = nargs - rightLen; - if (rightLen == 0) { - midLen = nargs - (rightLen = CHUNK); - if (FILL_ARRAY_TO_RIGHT[midLen] == null) { - // build some precursors from left to right - for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) - if (j > LEFT_ARGS) fillToRight(j); - } - } - if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); - assert(rightLen > 0); - MethodHandle midFill = fillToRight(midLen); // recursive fill - MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] - assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); - assert(rightFill.type().parameterCount() == 1 + rightLen); - - // Combine the two fills: - // right(mid(a, x10..x19), x20..x23) - // The final product will look like this: - // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) - if (midLen == LEFT_ARGS) - return rightFill; - else - return MethodHandles.collectArguments(rightFill, 0, midFill); - } - - // Type-polymorphic version of varargs maker. - private static final ClassValue TYPED_COLLECTORS - = new ClassValue() { - @Override - protected MethodHandle[] computeValue(Class type) { - return new MethodHandle[256]; - } - }; - - static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM - - /** Return a method handle that takes the indicated number of - * typed arguments and returns an array of them. - * The type argument is the array type. - */ - public static MethodHandle varargsArray(Class arrayType, int nargs) { - Class elemType = arrayType.getComponentType(); - if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); - // FIXME: Need more special casing and caching here. - if (nargs >= MAX_JVM_ARITY/2 - 1) { - int slots = nargs; - final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH - if (arrayType == double[].class || arrayType == long[].class) - slots *= 2; - if (slots > MAX_ARRAY_SLOTS) - throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); - } - if (elemType == Object.class) - return varargsArray(nargs); - // other cases: primitive arrays, subtypes of Object[] - MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); - MethodHandle mh = nargs < cache.length ? cache[nargs] : null; - if (mh != null) return mh; - if (elemType.isPrimitive()) { - MethodHandle builder = FILL_NEW_ARRAY; - MethodHandle producer = buildArrayProducer(arrayType); - mh = buildVarargsArray(builder, producer, nargs); - } else { - @SuppressWarnings("unchecked") - Class objArrayType = (Class) arrayType; - Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); - MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example); - MethodHandle producer = ARRAY_IDENTITY; - mh = buildVarargsArray(builder, producer, nargs); - } - mh = mh.asType(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType))); - assert(assertCorrectArity(mh, nargs)); - if (nargs < cache.length) - cache[nargs] = mh; - return mh; - } - - private static MethodHandle buildArrayProducer(Class arrayType) { - Class elemType = arrayType.getComponentType(); - if (elemType.isPrimitive()) - return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType)); - else - return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType); - } - - // List version of varargs maker. - - private static final List NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); - private static List makeList(Object... args) { return Arrays.asList(args); } - private static List list() { return NO_ARGS_LIST; } - private static List list(Object a0) - { return makeList(a0); } - private static List list(Object a0, Object a1) - { return makeList(a0, a1); } - private static List list(Object a0, Object a1, Object a2) - { return makeList(a0, a1, a2); } - private static List list(Object a0, Object a1, Object a2, Object a3) - { return makeList(a0, a1, a2, a3); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4) - { return makeList(a0, a1, a2, a3, a4); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5) - { return makeList(a0, a1, a2, a3, a4, a5); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6) - { return makeList(a0, a1, a2, a3, a4, a5, a6); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7) - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8) - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8, Object a9) - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - private static MethodHandle[] makeLists() { - ArrayList mhs = new ArrayList<>(); - for (;;) { - MethodHandle mh = findCollector("list", mhs.size(), List.class); - if (mh == null) break; - mhs.add(mh); - } - assert(mhs.size() == 11); // current number of methods - return mhs.toArray(new MethodHandle[MAX_ARITY+1]); - } - private static final MethodHandle[] LISTS = makeLists(); - - /** Return a method handle that takes the indicated number of Object - * arguments and returns a List. - */ - public static MethodHandle varargsList(int nargs) { - MethodHandle mh = LISTS[nargs]; - if (mh != null) return mh; - mh = findCollector("list", nargs, List.class); - if (mh != null) return LISTS[nargs] = mh; - return LISTS[nargs] = buildVarargsList(nargs); - } - private static MethodHandle buildVarargsList(int nargs) { - return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST); - } - // handy shared exception makers (they simplify the common case code) private static InternalError newInternalError(String message, Throwable cause) { return new InternalError(message, cause); diff --git a/src/share/classes/sun/invoke/util/VerifyType.java b/src/share/classes/sun/invoke/util/VerifyType.java index 52b32c40e890631eaa927b3d3c95cdc140b35d20..ce37b88c76db26c20d0004ce660d2881c8846a3b 100644 --- a/src/share/classes/sun/invoke/util/VerifyType.java +++ b/src/share/classes/sun/invoke/util/VerifyType.java @@ -40,18 +40,38 @@ public class VerifyType { /** * True if a value can be stacked as the source type and unstacked as the * destination type, without violating the JVM's type consistency. + *

    + * If both types are references, we apply the verifier's subclass check + * (or subtyping, if keepInterfaces). + * If the src type is a type guaranteed to be null (Void) it can be converted + * to any other reference type. + *

    + * If both types are primitives, we apply the verifier's primitive conversions. + * These do not include Java conversions such as long to double, since those + * require computation and (in general) stack depth changes. + * But very simple 32-bit viewing changes, such as byte to int, + * are null conversions, because they do not require any computation. + * These conversions are from any type to a wider type up to 32 bits, + * as long as the conversion is not signed to unsigned (byte to char). + *

    + * The primitive type 'void' does not interconvert with any other type, + * even though it is legal to drop any type from the stack and "return void". + * The stack effects, though are different between void and any other type, + * so it is safer to report a non-trivial conversion. * * @param src the type of a stacked value * @param dst the type by which we'd like to treat it + * @param keepInterfaces if false, we treat any interface as if it were Object * @return whether the retyping can be done without motion or reformatting */ - public static boolean isNullConversion(Class src, Class dst) { + public static boolean isNullConversion(Class src, Class dst, boolean keepInterfaces) { if (src == dst) return true; // Verifier allows any interface to be treated as Object: - if (dst.isInterface()) dst = Object.class; - if (src.isInterface()) src = Object.class; - if (src == dst) return true; // check again - if (dst == void.class) return true; // drop any return value + if (!keepInterfaces) { + if (dst.isInterface()) dst = Object.class; + if (src.isInterface()) src = Object.class; + if (src == dst) return true; // check again + } if (isNullType(src)) return !dst.isPrimitive(); if (!src.isPrimitive()) return dst.isAssignableFrom(src); if (!dst.isPrimitive()) return false; @@ -82,25 +102,13 @@ public class VerifyType { * Is the given type java.lang.Null or an equivalent null-only type? */ public static boolean isNullType(Class type) { - if (type == null) return false; - return type == NULL_CLASS - // This one may also be used as a null type. - // TO DO: Decide if we really want to legitimize it here. - // Probably we do, unless java.lang.Null really makes it into Java 7 - //|| type == Void.class - // Locally known null-only class: - || type == Empty.class - ; - } - private static final Class NULL_CLASS; - static { - Class nullClass = null; - try { - nullClass = Class.forName("java.lang.Null"); - } catch (ClassNotFoundException ex) { - // OK, we'll cope - } - NULL_CLASS = nullClass; + // Any reference statically typed as Void is guaranteed to be null. + // Therefore, it can be safely treated as a value of any + // other type that admits null, i.e., a reference type. + if (type == Void.class) return true; + // Locally known null-only class: + if (type == Empty.class) return true; + return false; } /** @@ -111,14 +119,14 @@ public class VerifyType { * @param recv the type of the method handle receiving the call * @return whether the retyping can be done without motion or reformatting */ - public static boolean isNullConversion(MethodType call, MethodType recv) { + public static boolean isNullConversion(MethodType call, MethodType recv, boolean keepInterfaces) { if (call == recv) return true; int len = call.parameterCount(); if (len != recv.parameterCount()) return false; for (int i = 0; i < len; i++) - if (!isNullConversion(call.parameterType(i), recv.parameterType(i))) + if (!isNullConversion(call.parameterType(i), recv.parameterType(i), keepInterfaces)) return false; - return isNullConversion(recv.returnType(), call.returnType()); + return isNullConversion(recv.returnType(), call.returnType(), keepInterfaces); } /** diff --git a/src/share/classes/sun/invoke/util/Wrapper.java b/src/share/classes/sun/invoke/util/Wrapper.java index 6c4be456aee3c6f00cd9839e61a1372623ecf763..2732e28c8ed6ee351e9ec310cca5d54efc511c9f 100644 --- a/src/share/classes/sun/invoke/util/Wrapper.java +++ b/src/share/classes/sun/invoke/util/Wrapper.java @@ -230,14 +230,6 @@ public enum Wrapper { */ public T zero(Class type) { return convert(zero, type); } -// /** Produce a wrapper for the given wrapper or primitive type. */ -// public static Wrapper valueOf(Class type) { -// if (isPrimitiveType(type)) -// return forPrimitiveType(type); -// else -// return forWrapperType(type); -// } - /** Return the wrapper that wraps values of the given type. * The type may be {@code Object}, meaning the {@code OBJECT} wrapper. * Otherwise, the type must be a primitive. diff --git a/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java index 4b858bbb82cc36dccce1f5e2231e20a37f04df2f..bf2e9516525aa16bf78361fe7dd6925bae73f68c 100644 --- a/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java +++ b/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import com.sun.tools.attach.spi.AttachProvider; import java.io.InputStream; import java.io.IOException; import java.util.Properties; -import java.util.Map; +import java.util.stream.Collectors; /* * The HotSpot implementation of com.sun.tools.attach.VirtualMachine. @@ -161,6 +161,50 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine { return props; } + private static final String MANAGMENT_PREFIX = "com.sun.management."; + + private static boolean checkedKeyName(Object key) { + if (!(key instanceof String)) { + throw new IllegalArgumentException("Invalid option (not a String): "+key); + } + if (!((String)key).startsWith(MANAGMENT_PREFIX)) { + throw new IllegalArgumentException("Invalid option: "+key); + } + return true; + } + + private static String stripKeyName(Object key) { + return ((String)key).substring(MANAGMENT_PREFIX.length()); + } + + @Override + public void startManagementAgent(Properties agentProperties) throws IOException { + if (agentProperties == null) { + throw new NullPointerException("agentProperties cannot be null"); + } + // Convert the arguments into arguments suitable for the Diagnostic Command: + // "ManagementAgent.start jmxremote.port=5555 jmxremote.authenticate=false" + String args = agentProperties.entrySet().stream() + .filter(entry -> checkedKeyName(entry.getKey())) + .map(entry -> stripKeyName(entry.getKey()) + "=" + escape(entry.getValue())) + .collect(Collectors.joining(" ")); + executeJCmd("ManagementAgent.start " + args); + } + + private String escape(Object arg) { + String value = arg.toString(); + if (value.contains(" ")) { + return "'" + value + "'"; + } + return value; + } + + @Override + public String startLocalManagementAgent() throws IOException { + executeJCmd("ManagementAgent.start_local"); + return getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); + } + // --- HotSpot specific methods --- // same as SIGQUIT @@ -257,6 +301,20 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine { return value; } + /* + * Utility method to read data into a String. + */ + String readErrorMessage(InputStream sis) throws IOException { + byte b[] = new byte[1024]; + int n; + StringBuffer message = new StringBuffer(); + while ((n = sis.read(b)) != -1) { + message.append(new String(b, 0, n, "UTF-8")); + } + return message.toString(); + } + + // -- attach timeout support private static long defaultAttachTimeout = 5000; diff --git a/src/share/classes/sun/tools/jcmd/JCmd.java b/src/share/classes/sun/tools/jcmd/JCmd.java index 8c5a2c50274c798a421a3cdffc9aba8420497b4f..0ff46323ec6ff828e9488c2a5c2db553ac822fc1 100644 --- a/src/share/classes/sun/tools/jcmd/JCmd.java +++ b/src/share/classes/sun/tools/jcmd/JCmd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,12 @@ import java.util.ArrayList; import java.util.Comparator; import java.net.URISyntaxException; +import com.sun.tools.attach.AttachOperationFailedException; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; + import sun.tools.attach.HotSpotVirtualMachine; import sun.tools.jstat.JStatLogger; import sun.jvmstat.monitor.Monitor; @@ -119,6 +121,7 @@ public class JCmd { pids.add(arg.getPid() + ""); } + boolean success = true; for (String pid : pids) { System.out.println(pid + ":"); if (arg.isListCounters()) { @@ -126,11 +129,16 @@ public class JCmd { } else { try { executeCommandForPid(pid, arg.getCommand()); + } catch(AttachOperationFailedException ex) { + System.err.println(ex.getMessage()); + success = false; } catch(Exception ex) { ex.printStackTrace(); + success = false; } } } + System.exit(success ? 0 : 1); } private static void executeCommandForPid(String pid, String command) @@ -150,13 +158,18 @@ public class JCmd { // read to EOF and just print output byte b[] = new byte[256]; int n; + boolean messagePrinted = false; do { n = in.read(b); if (n > 0) { String s = new String(b, 0, n, "UTF-8"); System.out.print(s); + messagePrinted = true; } } while (n > 0); + if (!messagePrinted) { + System.out.println("Command executed successfully"); + } } } vm.detach(); diff --git a/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java b/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java index 65b03e0fac0ccb9d0ebedfda3b6fb5fe6c229064..e6c827b70ce4202543fce1e9c2196038f25bfaae 100644 --- a/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java +++ b/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import java.io.File; // Sun specific import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; -import com.sun.tools.attach.AgentInitializationException; -import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; // Sun private @@ -238,35 +236,7 @@ public class LocalVirtualMachine { throw ioe; } - String home = vm.getSystemProperties().getProperty("java.home"); - - // Normally in ${java.home}/jre/lib/management-agent.jar but might - // be in ${java.home}/lib in build environments. - - String agent = home + File.separator + "jre" + File.separator + - "lib" + File.separator + "management-agent.jar"; - File f = new File(agent); - if (!f.exists()) { - agent = home + File.separator + "lib" + File.separator + - "management-agent.jar"; - f = new File(agent); - if (!f.exists()) { - throw new IOException("Management agent not found"); - } - } - - agent = f.getCanonicalPath(); - try { - vm.loadAgent(agent, "com.sun.management.jmxremote"); - } catch (AgentLoadException x) { - IOException ioe = new IOException(x.getMessage()); - ioe.initCause(x); - throw ioe; - } catch (AgentInitializationException x) { - IOException ioe = new IOException(x.getMessage()); - ioe.initCause(x); - throw ioe; - } + vm.startLocalManagementAgent(); // get the connector address Properties agentProps = vm.getAgentProperties(); diff --git a/src/share/classes/sun/util/calendar/ZoneInfoFile.java b/src/share/classes/sun/util/calendar/ZoneInfoFile.java index 4c423b703a721d818aa10c554926a86b76ea1d50..78d9f3ed6cba96f729a95278d34d24558e7bf435 100644 --- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -615,7 +615,9 @@ public final class ZoneInfoFile { // startTime=86400000 <= 24 hours // This: startDayOfWeek=6 // startTime=0 - // Below is the workaround, it probably slows down everyone a little + // Similar workaround needs to be applied to Africa/Cairo and + // its endDayOfWeek and endTime + // Below is the workarounds, it probably slows down everyone a little if (params[2] == 6 && params[3] == 0 && (zoneId.equals("Asia/Amman") || zoneId.equals("Asia/Gaza") || @@ -623,6 +625,13 @@ public final class ZoneInfoFile { params[2] = 5; params[3] = 86400000; } + //endDayOfWeek and endTime workaround + if (params[7] == 6 && params[8] == 0 && + (zoneId.equals("Africa/Cairo"))) { + params[7] = 5; + params[8] = 86400000; + } + } else if (nTrans > 0) { // only do this if there is something in table already if (lastyear < LASTYEAR) { // ZoneInfo has an ending entry for 2037 diff --git a/src/share/classes/sun/util/resources/TimeZoneNames.java b/src/share/classes/sun/util/resources/TimeZoneNames.java index 298a233d8509562d8fddb850ba9c441a92242e58..9ab92c93620f7f48c146bde62a4167da2aee6f23 100644 --- a/src/share/classes/sun/util/resources/TimeZoneNames.java +++ b/src/share/classes/sun/util/resources/TimeZoneNames.java @@ -47,9 +47,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String ACT[] = new String[] {"Acre Time", "ACT", "Acre Summer Time", "ACST", "Acre Time", "ACT"}; - String ADELAIDE[] = new String[] {"Central Standard Time (South Australia)", "CST", - "Central Summer Time (South Australia)", "CST", - "Central Time (South Australia)", "CT"}; + String ADELAIDE[] = new String[] {"Australian Central Standard Time (South Australia)", "ACST", + "Australian Central Daylight Time (South Australia)", "ACDT", + "Australian Central Time (South Australia)", "ACT"}; String AGT[] = new String[] {"Argentine Time", "ART", "Argentine Summer Time", "ARST", "Argentine Time", "ART"}; @@ -71,12 +71,12 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String BDT[] = new String[] {"Bangladesh Time", "BDT", "Bangladesh Summer Time", "BDST", "Bangladesh Time", "BDT"}; - String BRISBANE[] = new String[] {"Eastern Standard Time (Queensland)", "EST", - "Eastern Summer Time (Queensland)", "EST", - "Eastern Time (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Central Standard Time (South Australia/New South Wales)", "CST", - "Central Summer Time (South Australia/New South Wales)", "CST", - "Central Time (South Australia/New South Wales)", "CT"}; + String BRISBANE[] = new String[] {"Australian Eastern Standard Time (Queensland)", "AEST", + "Australian Eastern Daylight Time (Queensland)", "AEDT", + "Australian Eastern Time (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Australian Central Standard Time (South Australia/New South Wales)", "ACST", + "Australian Central Daylight Time (South Australia/New South Wales)", "ACDT", + "Australian Central Time (South Australia/New South Wales)", "ACT"}; String BRT[] = new String[] {"Brasilia Time", "BRT", "Brasilia Summer Time", "BRST", "Brasilia Time", "BRT"}; @@ -110,9 +110,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Cuba Standard Time", "CST", "Cuba Daylight Time", "CDT", "Cuba Time", "CT"}; - String DARWIN[] = new String[] {"Central Standard Time (Northern Territory)", "CST", - "Central Summer Time (Northern Territory)", "CST", - "Central Time (Northern Territory)", "CT"}; + String DARWIN[] = new String[] {"Australian Central Standard Time (Northern Territory)", "ACST", + "Australian Central Daylight Time (Northern Territory)", "ACDT", + "Australian Central Time (Northern Territory)", "ACT"}; String DUBLIN[] = new String[] {"Greenwich Mean Time", "GMT", "Irish Summer Time", "IST", "Irish Time", "IT"}; @@ -131,9 +131,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String EST[] = new String[] {"Eastern Standard Time", "EST", "Eastern Daylight Time", "EDT", "Eastern Time", "ET"}; - String EST_NSW[] = new String[] {"Eastern Standard Time (New South Wales)", "EST", - "Eastern Summer Time (New South Wales)", "EST", - "Eastern Time (New South Wales)", "ET"}; + String EST_NSW[] = new String[] {"Australian Eastern Standard Time (New South Wales)", "AEST", + "Australian Eastern Daylight Time (New South Wales)", "AEDT", + "Australian Eastern Time (New South Wales)", "AET"}; String FET[] = new String[] {"Further-eastern European Time", "FET", "Further-eastern European Summer Time", "FEST", "Further-eastern European Time", "FET"}; @@ -167,6 +167,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String IRT[] = new String[] {"Iran Standard Time", "IRST", "Iran Daylight Time", "IRDT", "Iran Time", "IRT"}; + String IRKT[] = new String[] {"Irkutsk Time", "IRKT", + "Irkutsk Summer Time", "IRKST", + "Irkutsk Time", "IRKT"}; String ISRAEL[] = new String[] {"Israel Standard Time", "IST", "Israel Daylight Time", "IDT", "Israel Time", "IT"}; @@ -176,11 +179,14 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String JST[] = new String[] {"Japan Standard Time", "JST", "Japan Daylight Time", "JDT", "Japan Time", "JT"}; + String KRAT[] = new String[] {"Krasnoyarsk Time", "KRAT", + "Krasnoyarsk Summer Time", "KRAST", + "Krasnoyarsk Time", "KRAT"}; String KST[] = new String[] {"Korea Standard Time", "KST", "Korea Daylight Time", "KDT", "Korea Time", "KT"}; String LORD_HOWE[] = new String[] {"Lord Howe Standard Time", "LHST", - "Lord Howe Summer Time", "LHST", + "Lord Howe Daylight Time", "LHDT", "Lord Howe Time", "LHT"}; String MHT[] = new String[] {"Marshall Islands Time", "MHT", "Marshall Islands Summer Time", "MHST", @@ -230,21 +236,15 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String SGT[] = new String[] {"Singapore Time", "SGT", "Singapore Summer Time", "SGST", "Singapore Time", "SGT"}; - String SLST[] = new String[] {"Greenwich Mean Time", "GMT", - "Sierra Leone Summer Time", "SLST", - "Sierra Leone Time", "SLT"}; - String TASMANIA[] = new String[] {"Eastern Standard Time (Tasmania)", "EST", - "Eastern Summer Time (Tasmania)", "EST", - "Eastern Time (Tasmania)", "ET"}; + String TASMANIA[] = new String[] {"Australian Eastern Standard Time (Tasmania)", "AEST", + "Australian Eastern Daylight Time (Tasmania)", "AEDT", + "Australian Eastern Time (Tasmania)", "AET"}; String TMT[] = new String[] {"Turkmenistan Time", "TMT", "Turkmenistan Summer Time", "TMST", "Turkmenistan Time", "TMT"}; String ULAT[]= new String[] {"Ulaanbaatar Time", "ULAT", "Ulaanbaatar Summer Time", "ULAST", "Ulaanbaatar Time", "ULAT"}; - String WART[] = new String[] {"Western Argentine Time", "WART", - "Western Argentine Summer Time", "WARST", - "Western Argentine Time", "WART"}; String WAT[] = new String[] {"Western African Time", "WAT", "Western African Summer Time", "WAST", "Western African Time", "WAT"}; @@ -254,27 +254,30 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String WIT[] = new String[] {"West Indonesia Time", "WIB", "West Indonesia Summer Time", "WIST", "West Indonesia Time", "WIB"}; - String WST_AUS[] = new String[] {"Western Standard Time (Australia)", "WST", - "Western Summer Time (Australia)", "WST", - "Western Time (Australia)", "WT"}; + String WST_AUS[] = new String[] {"Australian Western Standard Time", "AWST", + "Australian Western Daylight Time", "AWDT", + "Australian Western Time", "AWT"}; String SAMOA[] = new String[] {"Samoa Standard Time", "SST", "Samoa Daylight Time", "SDT", "Samoa Time", "ST"}; - String WST_SAMOA[] = new String[] {"West Samoa Time", "WST", + String WST_SAMOA[] = new String[] {"West Samoa Standard Time", "WSST", "West Samoa Daylight Time", "WSDT", "West Samoa Time", "WST"}; String ChST[] = new String[] {"Chamorro Standard Time", "ChST", "Chamorro Daylight Time", "ChDT", "Chamorro Time", "ChT"}; - String VICTORIA[] = new String[] {"Eastern Standard Time (Victoria)", "EST", - "Eastern Summer Time (Victoria)", "EST", - "Eastern Time (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"Australian Eastern Standard Time (Victoria)", "AEST", + "Australian Eastern Daylight Time (Victoria)", "AEDT", + "Australian Eastern Time (Victoria)", "AET"}; String UTC[] = new String[] {"Coordinated Universal Time", "UTC", "Coordinated Universal Time", "UTC", "Coordinated Universal Time", "UTC"}; String UZT[] = new String[] {"Uzbekistan Time", "UZT", "Uzbekistan Summer Time", "UZST", "Uzbekistan Time", "UZT"}; + String XJT[] = new String[] {"Xinjiang Standard Time", "XJT", + "Xinjiang Daylight Time", "XJDT", + "Xinjiang Time", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +339,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +440,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Western Greenland Summer Time", "WGST", "Western Greenland Time", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +487,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST", - "Metlakatla Daylight Time", "MeDT", - "Metlakatla Time", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Pierre & Miquelon Standard Time", "PMST", "Pierre & Miquelon Daylight Time", "PMDT", @@ -555,8 +556,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Time", "DDUT", "Dumont-d'Urville Summer Time", "DDUST", "Dumont-d'Urville Time", "DDUT"}}, - {"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST", - "Macquarie Island Summer Time", "MIST", + {"Antarctica/Macquarie", new String[] {"Macquarie Island Standard Time", "MIST", + "Macquarie Island Daylight Time", "MIDT", "Macquarie Island Time", "MIST"}}, {"Antarctica/Mawson", new String[] {"Mawson Time", "MAWT", "Mawson Summer Time", "MAWST", @@ -607,6 +608,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Brunei Summer Time", "BNST", "Brunei Time", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Choibalsan Time", "CHOT", "Choibalsan Summer Time", "CHOST", "Choibalsan Time", "CHOT"}}, @@ -631,9 +633,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Hovd Time", "HOVT", "Hovd Summer Time", "HOVST", "Hovd Time", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Irkutsk Time", "IRKT", - "Irkutsk Summer Time", "IRKST", - "Irkutsk Time", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"East Indonesia Time", "WIT", @@ -646,7 +646,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Petropavlovsk-Kamchatski Summer Time", "PETST", "Petropavlovsk-Kamchatski Time", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT", @@ -654,9 +654,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Khandyga Time", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Krasnoyarsk Time", "KRAT", - "Krasnoyarsk Summer Time", "KRAST", - "Krasnoyarsk Time", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -671,7 +669,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Philippines Time", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral Time", "ORAT", "Oral Summer Time", "ORAST", @@ -697,6 +695,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -709,7 +710,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT", "Ust-Nera Summer Time", "VLAST", "Ust-Nera Time", "VLAT"}}, @@ -751,9 +752,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST", - "Central Western Time (Australia)", "CWT"}}, + {"Australia/Eucla", new String[] {"Australian Central Western Standard Time", "ACWST", + "Australian Central Western Daylight Time", "ACWDT", + "Australian Central Western Time", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -819,7 +820,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -854,9 +855,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Volgograd Time", "VOLT", - "Volgograd Summer Time", "VOLST", - "Volgograd Time", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java b/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java index ea7ab573a715bd7b418ededa81eb38213c8ab35c..9b4e6503d84e144860691399f91bbba1e635c4f9 100644 --- a/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java +++ b/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String ACT[] = new String[] {"Acre Normalzeit", "ACT", "Acre Sommerzeit", "ACST", "Acre Normalzeit", "ACT"}; - String ADELAIDE[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien)", "CST", - "Zentrale Sommerzeit (S\u00FCdaustralien)", "CST", - "Zentrale Zeitzone (S\u00FCdaustralien)", "CT"}; + String ADELAIDE[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien)", "ACST", + "Zentrale Sommerzeit (S\u00FCdaustralien)", "ACDT", + "Zentrale Zeitzone (S\u00FCdaustralien)", "ACT"}; String AGT[] = new String[] {"Argentinische Zeit", "ART", "Argentinische Sommerzeit", "ARST", "Argentinische Zeit", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String BDT[] = new String[] {"Bangladesch Zeit", "BDT", "Bangladesch Sommerzeit", "BDST", "Bangladesch Zeit", "BDT"}; - String BRISBANE[] = new String[] {"\u00D6stliche Normalzeit (Queensland)", "EST", - "\u00D6stliche Sommerzeit (Queensland)", "EST", - "\u00D6stliche Zeitzone (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien/New South Wales)", "CST", - "Zentrale Sommerzeit (S\u00FCdaustralien/New South Wales)", "CST", - "Zentrale Zeitzone (S\u00FCdaustralien/New South Wales)", "CT"}; + String BRISBANE[] = new String[] {"\u00D6stliche Normalzeit (Queensland)", "AEST", + "\u00D6stliche Sommerzeit (Queensland)", "AEDT", + "\u00D6stliche Zeitzone (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Zentrale Normalzeit (S\u00FCdaustralien/New South Wales)", "ACST", + "Zentrale Sommerzeit (S\u00FCdaustralien/New South Wales)", "ACDT", + "Zentrale Zeitzone (S\u00FCdaustralien/New South Wales)", "ACT"}; String BRT[] = new String[] {"Brasilianische Zeit", "BRT", "Brasilianische Sommerzeit", "BRST", "Brasilianische Zeit", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Kubanische Normalzeit", "CST", "Kubanische Sommerzeit", "CDT", "Kubanische Normalzeit", "CT"}; - String DARWIN[] = new String[] {"Zentrale Normalzeit (Northern Territory)", "CST", - "Zentrale Sommerzeit (Northern Territory)", "CST", - "Zentrale Zeitzone (Northern Territory)", "CT"}; + String DARWIN[] = new String[] {"Zentrale Normalzeit (Northern Territory)", "ACST", + "Zentrale Sommerzeit (Northern Territory)", "ACDT", + "Zentrale Zeitzone (Northern Territory)", "ACT"}; String DUBLIN[] = new String[] {"Greenwich Zeit", "GMT", "Irische Sommerzeit", "IST", "Irische Zeit", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String EST[] = new String[] {"\u00d6stliche Normalzeit", "EST", "\u00d6stliche Sommerzeit", "EDT", "\u00D6stliche Zeitzone", "ET"}; - String EST_NSW[] = new String[] {"\u00D6stliche Normalzeit (New South Wales)", "EST", - "\u00D6stliche Sommerzeit (New South Wales)", "EST", - "\u00D6stliche Zeitzone (New South Wales)", "ET"}; + String EST_NSW[] = new String[] {"\u00D6stliche Normalzeit (New South Wales)", "AEST", + "\u00D6stliche Sommerzeit (New South Wales)", "AEDT", + "\u00D6stliche Zeitzone (New South Wales)", "AET"}; String FET[] = new String[] {"Kaliningrader Zeit", "FET", "Kaliningrader Sommerzeit", "FEST", "Kaliningrader Zeit", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String ICT[] = new String[] {"Indochina Zeit", "ICT", "Indochina Sommerzeit", "ICST", "Indochina Zeit", "ICT"}; + String IRKT[] = new String[] {"Irkutsk Zeit", "IRKT", + "Irkutsk Sommerzeit", "IRKST", + "Irkutsk Zeit", "IRKT"}; String IRT[] = new String[] {"Iranische Normalzeit", "IRST", "Iranische Sommerzeit", "IRDT", "Iranische Zeit", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String JST[] = new String[] {"Japanische Normalzeit", "JST", "Japanische Sommerzeit", "JDT", "Zeitzone f\u00FCr Japan", "JT"}; + String KRAT[] = new String[] {"Krasnojarsker Zeit", "KRAT", + "Krasnojarsker Sommerzeit", "KRAST", + "Krasnojarsker Zeit", "KRAT"}; String KST[] = new String[] {"Koreanische Normalzeit", "KST", "Koreanische Sommerzeit", "KDT", "Zeitzone f\u00FCr Korea", "KT"}; String LORD_HOWE[] = new String[] {"Lord Howe Normalzeit", "LHST", - "Lord Howe Sommerzeit", "LHST", + "Lord Howe Sommerzeit", "LHDT", "Lord-Howe Normalzeit", "LHT"}; String MHT[] = new String[] {"Marshallinseln Zeit", "MHT", "Marshallinseln Sommerzeit", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String SGT[] = new String[] {"Singapur Zeit", "SGT", "Singapur Sommerzeit", "SGST", "Singapur Zeit", "SGT"}; - String SLST[] = new String[] {"Greenwich Normalzeit", "GMT", - "Sierra Leone Sommerzeit", "SLST", - "Sierra Leone Zeit", "SLT"}; - String TASMANIA[] = new String[] {"\u00D6stliche Normalzeit (Tasmanien)", "EST", - "\u00D6stliche Sommerzeit (Tasmanien)", "EST", - "\u00D6stliche Zeitzone (Tasmanien)", "ET"}; + String TASMANIA[] = new String[] {"\u00D6stliche Normalzeit (Tasmanien)", "AEST", + "\u00D6stliche Sommerzeit (Tasmanien)", "AEDT", + "\u00D6stliche Zeitzone (Tasmanien)", "AET"}; String TMT[] = new String[] {"Turkmenische Zeit", "TMT", "Turkmenische Sommerzeit", "TMST", "Turkmenische Zeit", "TMT"}; String ULAT[]= new String[] {"Ulaanbaatar Zeit", "ULAT", "Ulaanbaatar Sommerzeit", "ULAST", "Ulaanbaatar Zeit", "ULAT"}; - String WART[] = new String[] {"Westargentinische Zeit", "WART", - "Westargentinische Sommerzeit", "WARST"}; String WAT[] = new String[] {"Westafrikanische Zeit", "WAT", "Westafrikanische Sommerzeit", "WAST", "Westafrikanische Zeit", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String WIT[] = new String[] {"Westindonesische Zeit", "WIB", "Westindonesische Sommerzeit", "WIST", "Westindonesische Zeit", "WIB"}; - String WST_AUS[] = new String[] {"Westliche Normalzeit (Australien)", "WST", - "Westliche Sommerzeit (Australien)", "WST", - "Westliche Zeitzone (Australien)", "WT"}; + String WST_AUS[] = new String[] {"Westliche Normalzeit (Australien)", "AWST", + "Westliche Sommerzeit (Australien)", "AWDT", + "Westliche Zeitzone (Australien)", "AWT"}; String SAMOA[] = new String[] {"Samoa Normalzeit", "SST", "Samoa Sommerzeit", "SDT", "Zeitzone f\u00FCr Samoa", "ST"}; - String WST_SAMOA[] = new String[] {"West Samoa Zeit", "WST", + String WST_SAMOA[] = new String[] {"West Samoa Zeit", "WSST", "West Samoa Sommerzeit", "WSDT", "West Samoa Zeit", "WST"}; String ChST[] = new String[] {"Chamorro Normalzeit", "ChST", "Chamorro Sommerzeit", "ChDT", "Zeitzone f\u00FCr die Marianen", "ChT"}; - String VICTORIA[] = new String[] {"\u00D6stliche Normalzeit (Victoria)", "EST", - "\u00D6stliche Sommerzeit (Victoria)", "EST", - "\u00D6stliche Zeitzone (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"\u00D6stliche Normalzeit (Victoria)", "AEST", + "\u00D6stliche Sommerzeit (Victoria)", "AEDT", + "\u00D6stliche Zeitzone (Victoria)", "AET"}; String UTC[] = new String[] {"Koordinierte Universalzeit", "UTC", "Koordinierte Universalzeit", "UTC", "Koordinierte Universalzeit", "UTC"}; String UZT[] = new String[] {"Usbekistan Zeit", "UZT", "Usbekistan Sommerzeit", "UZST", "Usbekistan Zeit", "UZT"}; + String XJT[] = new String[] {"Chinesische Normalzeit", "XJT", + "Chinesische Sommerzeit", "XJDT", + "Zeitzone f\u00FCr China", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Westgr\u00f6nl\u00e4ndische Sommerzeit", "WGST", "Westgr\u00F6nl\u00E4ndische Zeit", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Metlakatla Normalzeit", "MeST", - "Metlakatla Sommerzeit", "MeDT", - "Metlakatla Normalzeit", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Pierre & Miquelon Normalzeit", "PMST", "Pierre & Miquelon Sommerzeit", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Brunei Sommerzeit", "BNST", "Brunei Zeit", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Choibalsan Zeit", "CHOT", "Choibalsan Sommerzeit", "CHOST", "Choibalsan Zeit", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Hovd Zeit", "HOVT", "Hovd Sommerzeit", "HOVST", "Hovd Zeit", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Irkutsk Zeit", "IRKT", - "Irkutsk Sommerzeit", "IRKST", - "Irkutsk Zeit", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"Ostindonesische Zeit", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Petropawlowsk-Kamtschatkische Sommerzeit", "PETST", "Petropawlowsk-Kamtschatkische Zeit", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Chandyga Zeit", "YAKT", "Chandyga Sommerzeit", "YAKST", "Chandyga Zeit", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Krasnojarsker Zeit", "KRAT", - "Krasnojarsker Sommerzeit", "KRAST", - "Krasnojarsker Zeit", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Philippinische Zeit", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral Zeit", "ORAT", "Oral Sommerzeit", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Ust-Nera Zeit", "VLAT", "Ust-Nera Sommerzeit", "VLAST", "Ust-Nera Zeit", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Zentral-Westliche Normalzeit (Australien)", "CWST", - "Zentral-Westliche Sommerzeit (Australien)", "CWST", - "Zentral-Westliche Normalzeit (Australien)", "CWT"}}, + {"Australia/Eucla", new String[] {"Zentral-Westliche Normalzeit (Australien)", "ACWST", + "Zentral-Westliche Sommerzeit (Australien)", "ACWDT", + "Zentral-Westliche Normalzeit (Australien)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Wolgograder Zeit", "VOLT", - "Wolgograder Sommerzeit", "VOLST", - "Wolgograder Zeit", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java b/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java index c35c80963bea7c8fb26afcf464013b3270c79ba2..0235158296ca42c286c6cff618602478332003f1 100644 --- a/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java +++ b/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String ACT[] = new String[] {"Hora de Acre", "ACT", "Hora de verano de Acre", "ACST", "Hora de Acre", "ACT"}; - String ADELAIDE[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia)", "CST", - "Hora de verano Central (Sur de Australia)", "CST", - "Hora Central (Australia del Sur)", "CT"}; + String ADELAIDE[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia)", "ACST", + "Hora de verano Central (Sur de Australia)", "ACDT", + "Hora Central (Australia del Sur)", "ACT"}; String AGT[] = new String[] {"Hora de Argentina", "ART", "Hora de verano de Argentina", "ARST", "Hora de Argentina", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String BDT[] = new String[] {"Hora de Bangladesh", "BDT", "Hora de verano de Bangladesh", "BDST", "Hora de Bangladesh", "BDT"}; - String BRISBANE[] = new String[] {"Hora est\u00E1ndar del Este (Queensland)", "EST", - "Hora est\u00E1ndar de verano del Este (Queensland)", "EST", - "Hora Oriental (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia/Nueva Gales del Sur)", "CST", - "Hora de verano Central (Sur de Australia/Nueva Gales del Sur)", "CST", - "Hora Central (Australia del Sur/Nueva Gales del Sur)", "CT"}; + String BRISBANE[] = new String[] {"Hora est\u00E1ndar del Este (Queensland)", "AEST", + "Hora est\u00E1ndar de verano del Este (Queensland)", "AEDT", + "Hora Oriental (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Hora est\u00E1ndar Central (Sur de Australia/Nueva Gales del Sur)", "ACST", + "Hora de verano Central (Sur de Australia/Nueva Gales del Sur)", "ACDT", + "Hora Central (Australia del Sur/Nueva Gales del Sur)", "ACT"}; String BRT[] = new String[] {"Hora de Brasil", "BRT", "Hora de verano de Brasil", "BRST", "Hora de Brasil", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Hora est\u00e1ndar de Cuba", "CST", "Hora de verano de Cuba", "CDT", "Hora de Cuba", "CT"}; - String DARWIN[] = new String[] {"Hora est\u00E1ndar Central (territorio del Norte)", "CST", - "Hora de verano Central (territorio del Norte)", "CST", - "Hora Central (Territorio Septentrional)", "CT"}; + String DARWIN[] = new String[] {"Hora est\u00E1ndar Central (territorio del Norte)", "ACST", + "Hora de verano Central (territorio del Norte)", "ACDT", + "Hora Central (Territorio Septentrional)", "ACT"}; String DUBLIN[] = new String[] {"Hora del Meridiano de Greenwich", "GMT", "Hora de verano de Irlanda", "IST", "Hora de Irlanda", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String EST[] = new String[] {"Hora est\u00e1ndar Oriental", "EST", "Hora de verano Oriental", "EDT", "Hora Oriental", "ET"}; - String EST_NSW[] = new String[] {"Hora est\u00E1ndar Oriental (Nueva Gales del Sur)", "EST", - "Hora de verano Oriental (Nueva Gales del Sur)", "EST", - "Hora Oriental (Nueva Gales del Sur)", "ET"}; + String EST_NSW[] = new String[] {"Hora est\u00E1ndar Oriental (Nueva Gales del Sur)", "AEST", + "Hora de verano Oriental (Nueva Gales del Sur)", "AEDT", + "Hora Oriental (Nueva Gales del Sur)", "AET"}; String FET[] = new String[] {"Hora de Europa m\u00E1s Oriental", "FET", "Hora de verano de Europa m\u00E1s Oriental", "FEST", "Hora de Europa m\u00E1s Oriental", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String ICT[] = new String[] {"Hora de Indochina", "ICT", "Hora de verano de Indochina", "ICST", "Hora de Indochina", "ICT"}; + String IRKT[] = new String[] {"Hora de Irkutsk", "IRKT", + "Hora de verano de Irkutsk", "IRKST", + "Hora de Irkutsk", "IRKT"}; String IRT[] = new String[] {"Hora est\u00e1ndar de Ir\u00e1n", "IRST", "Hora de verano de Ir\u00e1n", "IRDT", "Hora de Ir\u00E1n", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String JST[] = new String[] {"Hora est\u00e1ndar de Jap\u00f3n", "JST", "Hora de verano de Jap\u00f3n", "JDT", "Hora de Jap\u00F3n", "JT"}; + String KRAT[] = new String[] {"Hora de Krasnoyarsk", "KRAT", + "Hora de verano de Krasnoyarsk", "KRAST", + "Hora de Krasnoyarsk", "KRAT"}; String KST[] = new String[] {"Hora est\u00e1ndar de Corea", "KST", "Hora de verano de Corea", "KDT", "Hora de Corea", "KT"}; String LORD_HOWE[] = new String[] {"Hora est\u00e1ndar de Lord Howe", "LHST", - "Hora de verano de Lord Howe", "LHST", + "Hora de verano de Lord Howe", "LHDT", "Hora de Lord Howe", "LHT"}; String MHT[] = new String[] {"Hora de las Islas Marshall", "MHT", "Hora de verano de las Islas Marshall", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String SGT[] = new String[] {"Hora de Singapur", "SGT", "Hora de verano de Singapur", "SGST", "Hora de Singapur", "SGT"}; - String SLST[] = new String[] {"Hora del Meridiano de Greenwich", "GMT", - "Hora de verano de Sierra Leona", "SLST", - "Horario de Sierra Leona", "SLT"}; - String TASMANIA[] = new String[] {"Hora est\u00E1ndar del Este (Tasmania)", "EST", - "Hora de verano del Este (Tasmania)", "EST", - "Hora Oriental (Tasmania)", "ET"}; + String TASMANIA[] = new String[] {"Hora est\u00E1ndar del Este (Tasmania)", "AEST", + "Hora de verano del Este (Tasmania)", "AEDT", + "Hora Oriental (Tasmania)", "AET"}; String TMT[] = new String[] {"Hora de Turkmenist\u00e1n", "TMT", "Hora de verano de Turkmenist\u00e1n", "TMST", "Hora de Turkmenist\u00E1n", "TMT"}; String ULAT[]= new String[] {"Hora de Ulan Bator", "ULAT", "Hora de verano de Ulan Bator", "ULAST", "Hora de Ulan Bator", "ULAT"}; - String WART[] = new String[] {"Hora de Argentina Occidental", "WART", - "Hora de verano de Argentina Occidental", "WARST"}; String WAT[] = new String[] {"Hora de \u00c1frica Occidental", "WAT", "Hora de verano de \u00c1frica Occidental", "WAST", "Hora de \u00C1frica Occidental", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String WIT[] = new String[] {"Hora de Indonesia Occidental", "WIB", "Indonesia Hora de verano de Indonesia Occidental", "WIST", "Hora de Indonesia Occidental", "WIB"}; - String WST_AUS[] = new String[] {"Hora est\u00E1ndar Occidental (Australia)", "WST", - "Hora de verano Occidental (Australia)", "WST", - "Hora Occidental (Australia)", "WT"}; + String WST_AUS[] = new String[] {"Hora est\u00E1ndar Occidental (Australia)", "AWST", + "Hora de verano Occidental (Australia)", "AWDT", + "Hora Occidental (Australia)", "AWT"}; String SAMOA[] = new String[] {"Hora est\u00e1ndar de Samoa", "SST", "Hora de verano de Samoa", "SDT", "Hora de Samoa", "ST"}; - String WST_SAMOA[] = new String[] {"Hora de Samoa Occidental", "WST", + String WST_SAMOA[] = new String[] {"Hora de Samoa Occidental", "WSST", "Hora de verano de Samoa Occidental", "WSDT", "Hora de Samoa Occidental", "WST"}; String ChST[] = new String[] {"Hora est\u00e1ndar de Chamorro", "ChST", "Hora de verano de Chamorro", "ChDT", "Hora de Chamorro", "ChT"}; - String VICTORIA[] = new String[] {"Hora est\u00E1ndar del Este (Victoria)", "EST", - "Hora de verano del Este (Victoria)", "EST", - "Hora Oriental (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"Hora est\u00E1ndar del Este (Victoria)", "AEST", + "Hora de verano del Este (Victoria)", "AEDT", + "Hora Oriental (Victoria)", "AET"}; String UTC[] = new String[] {"Hora Universal Coordinada", "UTC", "Hora Universal Coordinada", "UTC", "Hora Universal Coordinada", "UTC"}; String UZT[] = new String[] {"Hora de Uzbekist\u00e1n", "UZT", "Hora de verano de Uzbekist\u00e1n", "UZST", "Hora de Uzbekist\u00E1n", "UZT"}; + String XJT[] = new String[] {"Hora est\u00e1ndar de China", "XJT", + "Hora de verano de China", "XJDT", + "Hora de China", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Groenlandia Occidental", "WGST", "Hora de Groenlandia Occidental", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Hora de Metlakatla", "MeST", - "Hora de verano de Metlakatla", "MeDT", - "Metlakatla Time", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Hora est\u00e1ndar de Pierre & Miquelon", "PMST", "Hora de verano de Pierre & Miquelon", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Brunei", "BNST", "Hora de Brunei", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Hora de Choibalsan", "CHOT", "Hora de verano de Choibalsan", "CHOST", "Hora de Choibalsan", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Hora de Hovd", "HOVT", "Hora de verano de Hovd", "HOVST", "Hora de Hovd", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Hora de Irkutsk", "IRKT", - "Hora de verano de Irkutsk", "IRKST", - "Hora de Irkutsk", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"Hora de Indonesia Oriental", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Petropavlovsk-Kamchatski", "PETST", "Hora de Petropavlovsk-Kamchatski", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Hora de Khandyga", "YAKT", "Hora de verano de Khandyga", "YAKST", "Hora de Khandyga", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Hora de Krasnoyarsk", "KRAT", - "Hora de verano de Krasnoyarsk", "KRAST", - "Hora de Krasnoyarsk", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de Filipinas", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Hora de Uralsk", "ORAT", "Hora de verano de Uralsk", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Hora de Ust-Nera", "VLAT", "Hora de verano de Ust-Nera", "VLAST", "Hora de Ust-Nera", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Hora est\u00E1ndar de Australia Central y Occidental", "CWST", - "Hora est\u00E1ndar de verano de Australia Central y Occidental", "CWST", - "Hora de Australia Central y Occidental", "CWT"}}, + {"Australia/Eucla", new String[] {"Hora est\u00E1ndar de Australia Central y Occidental", "ACWST", + "Hora est\u00E1ndar de verano de Australia Central y Occidental", "ACWDT", + "Hora de Australia Central y Occidental", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Hora de Volgogrado", "VOLT", - "Hora de verano de Volgogrado", "VOLST", - "Hora de Volgogrado", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java b/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java index 393e45d45495e76f77981fd23206bfe64204329e..1d8b8561299c154c1ceba06ba5f10edd85312515 100644 --- a/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java +++ b/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String ACT[] = new String[] {"Heure de l'Acre", "ACT", "Heure d'\u00e9t\u00e9 de l'Acre", "ACST", "Heure de l'Acre", "ACT"}; - String ADELAIDE[] = new String[] {"Heure standard d'Australie centrale (Australie du sud)", "CST", - "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud)", "CST", - "Centre (Australie-M\u00E9ridionale)", "CT"}; + String ADELAIDE[] = new String[] {"Heure standard d'Australie centrale (Australie du sud)", "ACST", + "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud)", "ACDT", + "Centre (Australie-M\u00E9ridionale)", "ACT"}; String AGT[] = new String[] {"Heure D'Argentine", "ART", "Heure d'\u00e9t\u00e9 D'Argentine", "ARST", "Heure d'Argentine", "ART"} ; @@ -72,12 +72,12 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String BDT[] = new String[] {"Heure du Bangladesh", "BDT", "Heure d'\u00e9t\u00e9 du Bangladesh", "BDST", "Heure du Bangladesh", "BDT"} ; - String BRISBANE[] = new String[] {"Heure standard d'Australie orientale (Queensland)", "EST", - "Heure d'\u00E9t\u00E9 d'Australie orientale (Queensland)", "EST", - "C\u00F4te Est (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Heure standard d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "CST", - "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "CST", - "Centre (Australie-M\u00E9ridionale/Nouvelle-Galles du Sud)", "CT"}; + String BRISBANE[] = new String[] {"Heure standard d'Australie orientale (Queensland)", "AEST", + "Heure d'\u00E9t\u00E9 d'Australie orientale (Queensland)", "AEDT", + "C\u00F4te Est (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Heure standard d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "ACST", + "Heure d'\u00E9t\u00E9 d'Australie centrale (Australie du sud/Nouvelle-Galles du sud)", "ACDT", + "Centre (Australie-M\u00E9ridionale/Nouvelle-Galles du Sud)", "ACT"}; String BRT[] = new String[] {"Heure du Br\u00e9sil", "BRT", "Heure d'\u00e9t\u00e9 du Br\u00e9sil", "BRST", "Heure du Br\u00E9sil", "BRT"} ; @@ -111,9 +111,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Heure standard de Cuba", "CST", "Heure d'\u00e9t\u00e9 de Cuba", "CDT", "Heure de Cuba", "CT"}; - String DARWIN[] = new String[] {"Heure standard d'Australie centrale (Territoire du Nord)", "CST", - "Heure d'\u00E9t\u00E9 d'Australie centrale (Territoire du Nord)", "CST", - "Centre (Territoire du Nord)", "CT"}; + String DARWIN[] = new String[] {"Heure standard d'Australie centrale (Territoire du Nord)", "ACST", + "Heure d'\u00E9t\u00E9 d'Australie centrale (Territoire du Nord)", "ACDT", + "Centre (Territoire du Nord)", "ACT"}; String DUBLIN[] = new String[] {"Heure du m\u00e9ridien de Greenwich", "GMT", "Heure d'\u00e9t\u00e9 irlandaise", "IST", "Heure irlandaise", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String EST[] = new String[] {"Heure normale de l'Est", "EST", "Heure avanc\u00e9e de l'Est", "EDT", "C\u00F4te Est", "ET"} ; - String EST_NSW[] = new String[] {"Heure normale de l'Est (Nouvelle-Galles du Sud)", "EST", - "Heure d'\u00E9t\u00E9 de l'Est (Nouvelle-Galles du Sud)", "EST", - "C\u00F4te Est (Nouvelle-Galles du Sud)", "ET"} ; + String EST_NSW[] = new String[] {"Heure normale de l'Est (Nouvelle-Galles du Sud)", "AEST", + "Heure d'\u00E9t\u00E9 de l'Est (Nouvelle-Galles du Sud)", "AEDT", + "C\u00F4te Est (Nouvelle-Galles du Sud)", "AET"} ; String FET[] = new String[] {"Heure d'Europe de l'Est UTC+3", "FET", "Heure d'\u00E9t\u00E9 d'Europe de l'Est UTC+3", "FEST", "Heure d'Europe de l'Est UTC+3", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String ICT[] = new String[] {"Heure d'Indochine", "ICT", "Heure d'\u00e9t\u00e9 d'Indochine", "ICST", "Heure d'Indochine", "ICT"} ; + String IRKT[] = new String[] {"Heure d'Irkutsk", "IRKT", + "Heure d'\u00e9t\u00e9 d'Irkutsk", "IRKST", + "Heure d'Irkutsk", "IRKT"}; String IRT[] = new String[] {"Heure normale d'Iran", "IRST", "Heure avanc\u00e9e d'Iran", "IRDT", "Heure d'Iran", "IRT"} ; @@ -177,11 +180,14 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String JST[] = new String[] {"Heure normale du Japon", "JST", "Heure avanc\u00e9e du Japon", "JDT", "Japon", "JT"} ; + String KRAT[] = new String[] {"Heure de Krasno\u00efarsk", "KRAT", + "Heure d'\u00e9t\u00e9 de Krasno\u00efarsk", "KRAST", + "Heure de Krasno\u00EFarsk", "KRAT"}; String KST[] = new String[] {"Heure normale de Cor\u00e9e", "KST", "Heure avanc\u00e9e de Cor\u00e9e", "KDT", "Cor\u00E9e", "KT"} ; String LORD_HOWE[] = new String[] {"Heure standard de Lord Howe", "LHST", - "Heure d'\u00e9t\u00e9 de Lord Howe", "LHST", + "Heure d'\u00e9t\u00e9 de Lord Howe", "LHDT", "Heure de Lord Howe", "LHT"}; String MHT[] = new String[] {"Heure des Iles Marshall", "MHT", "Heure d'\u00e9t\u00e9 des Iles Marshall", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String SGT[] = new String[] {"Heure de Singapour", "SGT", "Heure d'\u00e9t\u00e9 de Singapour", "SGST", "Heure de Singapour", "SGT"}; - String SLST[] = new String[] {"Heure du m\u00e9ridien de Greenwich", "GMT", - "Heure d'\u00e9t\u00e9 de Sierra Leone", "SLST", - "Heure de Sierra Leone", "SLT"}; - String TASMANIA[] = new String[] {"Heure standard d'Australie orientale (Tasmanie)", "EST", - "Heure d'\u00E9t\u00E9 d'Australie orientale (Tasmanie)", "EST", - "C\u00F4te Est (Tasmanie)", "ET"}; + String TASMANIA[] = new String[] {"Heure standard d'Australie orientale (Tasmanie)", "AEST", + "Heure d'\u00E9t\u00E9 d'Australie orientale (Tasmanie)", "AEDT", + "C\u00F4te Est (Tasmanie)", "AET"}; String TMT[] = new String[] {"Heure du Turkm\u00e9nistan", "TMT", "Heure d'\u00e9t\u00e9 du Turkm\u00e9nistan", "TMST", "Heure du Turkm\u00E9nistan", "TMT"} ; String ULAT[]= new String[] {"Heure de l'Ulaanbaatar", "ULAT", "Heure d'\u00e9t\u00e9 de l'Ulaanbaatar", "ULAST", "Heure de l'Ulaanbaatar", "ULAT"} ; - String WART[] = new String[] {"Heure D'Argentine de l'Ouest", "WART", - "Heure d'\u00e9t\u00e9 D'Argentine de l'Ouest", "WARST"} ; String WAT[] = new String[] {"Heure d'Afrique de l'Ouest", "WAT", "Heure d'\u00e9t\u00e9 d'Afrique de l'Ouest", "WAST", "Heure d'Afrique de l'Ouest", "WAT"} ; @@ -254,27 +255,30 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String WIT[] = new String[] {"Heure de l'Indon\u00e9sie occidentale", "WIB", "Heure d'\u00e9t\u00e9 de l'Indon\u00e9sie occidentale", "WIST", "Heure de l'Indon\u00E9sie occidentale", "WIB"}; - String WST_AUS[] = new String[] {"Heure normale de l'Ouest (Australie)", "WST", - "Heure d'\u00E9t\u00E9 de l'Ouest (Australie)", "WST", - "Ouest (Australie)", "WT"} ; + String WST_AUS[] = new String[] {"Heure normale de l'Ouest (Australie)", "AWST", + "Heure d'\u00E9t\u00E9 de l'Ouest (Australie)", "AWDT", + "Ouest (Australie)", "AWT"} ; String SAMOA[] = new String[] {"Heure standard de Samoa", "SST", "Heure avanc\u00e9e de Samoa", "SDT", "Samoa", "ST"}; - String WST_SAMOA[] = new String[] {"Heure des Samoas occidentales", "WST", + String WST_SAMOA[] = new String[] {"Heure des Samoas occidentales", "WSST", "Heure d'\u00e9t\u00e9 des Samoas occidentales", "WSDT", "Heure des Samoas occidentales", "WST"} ; String ChST[] = new String[] {"Heure normale des \u00eeles Mariannes", "ChST", "Heure d'\u00e9t\u00e9 des \u00eeles Mariannes", "ChDT", "Chamorro", "ChT"}; - String VICTORIA[] = new String[] {"Heure standard d'Australie orientale (Victoria)", "EST", - "Heure d'\u00E9t\u00E9 d'Australie orientale (Victoria)", "EST", - "C\u00F4te Est (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"Heure standard d'Australie orientale (Victoria)", "AEST", + "Heure d'\u00E9t\u00E9 d'Australie orientale (Victoria)", "AEDT", + "C\u00F4te Est (Victoria)", "AET"}; String UTC[] = new String[] {"Temps universel coordonn\u00e9", "UTC", "Temps universel coordonn\u00e9", "UTC", "Temps universel coordonn\u00E9", "UTC"}; String UZT[] = new String[] {"Heure de l'Ouzb\u00e9kistan", "UZT", "Heure d'\u00e9t\u00e9 de l'Ouzb\u00e9kistan", "UZST", "Heure de l'Ouzb\u00E9kistan", "UZT"}; + String XJT[] = new String[] {"Heure normale de Chine", "XJT", + "Heure avanc\u00e9e de Chine", "XJDT", + "Chine", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 du Groenland de l'Ouest", "WGST", "Heure du Groenland de l'Ouest", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Heure normale de Metlakatla", "MeST", - "Heure avanc\u00E9e de Metlakatla", "MeDT", - "Heure de Metlakatla", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Heure normale de Saint-Pierre et Miquelon", "PMST", "Heure avanc\u00e9e de Saint-Pierre et Miquelon", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 du Brunei", "BNST", "Heure du Brunei", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Heure de Choibalsan", "CHOT", "Heure d'\u00e9t\u00e9 de Choibalsan", "CHOST", "Heure de Choibalsan", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Heure de Hovd", "HOVT", "Heure d'\u00e9t\u00e9 de Hovd", "HOVST", "Heure de Hovd", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Heure d'Irkutsk", "IRKT", - "Heure d'\u00e9t\u00e9 d'Irkutsk", "IRKST", - "Heure d'Irkutsk", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"Heure d'Indon\u00e9sie orientale", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 de Petropavlovsk-Kamchatski", "PETST", "Heure de Petropavlovsk-Kamchatski", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Heure de Khandyga", "YAKT", "Heure d'\u00E9t\u00E9 de Khandyga", "YAKST", "Heure de Khandyga", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Heure de Krasno\u00efarsk", "KRAT", - "Heure d'\u00e9t\u00e9 de Krasno\u00efarsk", "KRAST", - "Heure de Krasno\u00EFarsk", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure des Philippines", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Heure d'Oral", "ORAT", "Heure d'\u00e9t\u00e9 d'Oral", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Heure d'Ust-Nera", "VLAT", "Heure d'\u00E9t\u00E9 d'Ust-Nera", "VLAST", "Heure d'Ust-Nera", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Heure standard de l'Australie occidentale (centre)", "CWST", - "Heure d'\u00E9t\u00E9 de l'Australie occidentale (centre)", "CWST", - "Heure de l'Australie occidentale (centre)", "CWT"}}, + {"Australia/Eucla", new String[] {"Heure standard de l'Australie occidentale (centre)", "ACWST", + "Heure d'\u00E9t\u00E9 de l'Australie occidentale (centre)", "ACWDT", + "Heure de l'Australie occidentale (centre)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Heure de Volgograd", "VOLT", - "Heure d'\u00e9t\u00e9 de Volgograd", "VOLST", - "Heure de Volgograd", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java b/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java index 309a7715c7d5fdcb2070a7d76fd036bd5180be36..43035b66ea40eb396e012437220da8982a3f7064 100644 --- a/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java +++ b/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String ACT[] = new String[] {"Ora di Acre", "ACT", "Ora estiva di Acre", "ACST", "Ora di Acre", "ACT"}; - String ADELAIDE[] = new String[] {"Ora standard centrale (Australia del Sud)", "CST", - "Ora estiva centrale (Australia del Sud)", "CST", - "Ora fuso centrale (Australia del Sud)", "CT"}; + String ADELAIDE[] = new String[] {"Ora standard centrale (Australia del Sud)", "ACST", + "Ora estiva centrale (Australia del Sud)", "ACDT", + "Ora fuso centrale (Australia del Sud)", "ACT"}; String AGT[] = new String[] {"Ora dell'Argentina", "ART", "Ora estiva dell'Argentina", "ARST", "Ora dell'Argentina", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String BDT[] = new String[] {"Ora del Bangladesh", "BDT", "Ora estiva del Bangladesh", "BDST", "Ora del Bangladesh", "BDT"}; - String BRISBANE[] = new String[] {"Ora standard orientale (Queensland)", "EST", - "Ora estiva orientale (Queensland)", "EST", - "Ora fuso orientale (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Ora standard centrale (Australia del Sud/Nuovo Galles del Sud)", "CST", - "Ora estiva centrale (Australia del Sud/Nuovo Galles del Sud)", "CST", - "Ora fuso centrale (Australia del Sud/Nuovo Galles del Sud)", "CT"}; + String BRISBANE[] = new String[] {"Ora standard orientale (Queensland)", "AEST", + "Ora estiva orientale (Queensland)", "AEDT", + "Ora fuso orientale (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Ora standard centrale (Australia del Sud/Nuovo Galles del Sud)", "ACST", + "Ora estiva centrale (Australia del Sud/Nuovo Galles del Sud)", "ACDT", + "Ora fuso centrale (Australia del Sud/Nuovo Galles del Sud)", "ACT"}; String BRT[] = new String[] {"Ora del Brasile", "BRT", "Ora estiva del Brasile", "BRST", "Ora di Brasilia", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Ora solare Cuba", "CST", "Ora legale Cuba", "CDT", "Ora di Cuba", "CT"}; - String DARWIN[] = new String[] {"Ora standard centrale (Territori del Nord)", "CST", - "Ora estiva centrale (Territori del Nord)", "CST", - "Ora fuso centrale (Territori del Nord)", "CT"}; + String DARWIN[] = new String[] {"Ora standard centrale (Territori del Nord)", "ACST", + "Ora estiva centrale (Territori del Nord)", "ACDT", + "Ora fuso centrale (Territori del Nord)", "ACT"}; String DUBLIN[] = new String[] {"Ora media di Greenwich", "GMT", "Ora estiva irlandese", "IST", "Ora irlandese", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String EST[] = new String[] {"Ora solare USA orientale", "EST", "Ora legale USA orientale", "EDT", "Fuso orientale", "ET"}; - String EST_NSW[] = new String[] {"Ora standard dell'Australia orientale (Nuovo Galles del Sud)", "EST", - "Ora estiva dell'Australia orientale (Nuovo Galles del Sud)", "EST", - "Ora fuso orientale (Nuovo Galles del Sud)", "ET"}; + String EST_NSW[] = new String[] {"Ora standard dell'Australia orientale (Nuovo Galles del Sud)", "AEST", + "Ora estiva dell'Australia orientale (Nuovo Galles del Sud)", "AEDT", + "Ora fuso orientale (Nuovo Galles del Sud)", "AET"}; String FET[] = new String[] {"Ora dei paesi europei pi\u00F9 orientali", "FET", "Ora estiva dei paesi europei pi\u00F9 orientali", "FEST", "Ora dei paesi europei pi\u00F9 orientali", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String ICT[] = new String[] {"Ora dell'Indocina", "ICT", "Ora estiva dell'Indocina", "ICST", "Ora dell'Indocina", "ICT"}; + String IRKT[] = new String[] {"Ora di Irkutsk", "IRKT", + "Ora estiva di Irkutsk", "IRKST", + "Ora di Irkutsk", "IRKT"}; String IRT[] = new String[] {"Ora solare Iran", "IRST", "Ora legale Iran", "IRDT", "Ora Iran", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String JST[] = new String[] {"Ora solare del Giappone", "JST", "Ora legale del Giappone", "JDT", "Ora Giappone", "JT"}; + String KRAT[] = new String[] {"Ora di Krasnojarsk", "KRAT", + "Ora estiva di Krasnojarsk", "KRAST", + "Ora di Krasnojarsk", "KRAT"}; String KST[] = new String[] {"Ora solare della Corea", "KST", "Ora legale della Corea", "KDT", "Ora Corea", "KT"}; String LORD_HOWE[] = new String[] {"Ora standard di Lord Howe", "LHST", - "Ora estiva di Lord Howe", "LHST", + "Ora estiva di Lord Howe", "LHDT", "Ora di Lord Howe", "LHT"}; String MHT[] = new String[] {"Ora delle Isole Marshall", "MHT", "Ora estiva delle Isole Marshall", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String SGT[] = new String[] {"Ora di Singapore", "SGT", "Ora estiva di Singapore", "SGST", "Ora di Singapore", "SGT"}; - String SLST[] = new String[] {"Ora media di Greenwich", "GMT", - "Ora legale della Sierra Leone", "SLST", - "Ora della Sierra Leone", "SLT"}; - String TASMANIA[] = new String[] {"Ora standard orientale (Tasmania)", "EST", - "Ora estiva orientale (Tasmania)", "EST", - "Ora fuso orientale (Tasmania)", "ET"}; + String TASMANIA[] = new String[] {"Ora standard orientale (Tasmania)", "AEST", + "Ora estiva orientale (Tasmania)", "AEDT", + "Ora fuso orientale (Tasmania)", "AET"}; String TMT[] = new String[] {"Ora del Turkmenistan", "TMT", "Ora estiva del Turkmenistan", "TMST", "Ora del Turkmenistan", "TMT"}; String ULAT[]= new String[] {"Ora di Ulaanbaatar", "ULAT", "Ora estiva di Ulaanbaatar", "ULAST", "Ora di Ulaanbaatar", "ULAT"}; - String WART[] = new String[] {"Ora dell'Argentina occidentale", "WART", - "Ora estiva dell'Argentina occidentale", "WARST"}; String WAT[] = new String[] {"Ora dell'Africa occidentale", "WAT", "Ora estiva dell'Africa occidentale", "WAST", "Ora dell'Africa occidentale", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String WIT[] = new String[] {"Ora dell'Indonesia occidentale", "WIB", "Ora estiva dell'Indonesia occidentale", "WIST", "Ora dell'Indonesia occidentale", "WIB"}; - String WST_AUS[] = new String[] {"Ora standard dell'Australia occidentale", "WST", - "Ora estiva dell'Australia occidentale", "WST", - "Ora Australia occidentale", "WT"}; + String WST_AUS[] = new String[] {"Ora standard dell'Australia occidentale", "AWST", + "Ora estiva dell'Australia occidentale", "AWDT", + "Ora Australia occidentale", "AWT"}; String SAMOA[] = new String[] {"Ora standard di Samoa", "SST", "Ora legale di Samoa", "SDT", "Ora Samoa", "ST"}; - String WST_SAMOA[] = new String[] {"Ora di Samoa", "WST", + String WST_SAMOA[] = new String[] {"Ora di Samoa", "WSST", "Ora estiva di Samoa", "WSDT", "Ora di Samoa occidentale", "WST"}; String ChST[] = new String[] {"Ora standard di Chamorro", "ChST", "Ora legale di Chamorro", "ChDT", "Ora Chamorro", "ChT"}; - String VICTORIA[] = new String[] {"Ora standard orientale (Victoria)", "EST", - "Ora estiva orientale (Victoria)", "EST", - "Ora fuso orientale (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"Ora standard orientale (Victoria)", "AEST", + "Ora estiva orientale (Victoria)", "AEDT", + "Ora fuso orientale (Victoria)", "AET"}; String UTC[] = new String[] {"Tempo universale coordinato", "UTC", "Tempo universale coordinato", "UTC", "Tempo universale coordinato", "UTC"}; String UZT[] = new String[] {"Ora dell'Uzbekistan", "UZT", "Ora estiva dell'Uzbekistan", "UZST", "Ora dell'Uzbekistan", "UZT"}; + String XJT[] = new String[] {"Ora solare della Cina", "XJT", + "Ora legale della Cina", "XJDT", + "Ora Cina", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva della Groenlandia occidentale", "WGST", "Ora della Groenlandia occidentale", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Ora standard di Metlakatla", "MeST", - "Ora legale di Metlakatla", "MeDT", - "Ora di Metlakatla", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Ora solare di Saint-Pierre e Miquelon", "PMST", "Ora legale di Saint-Pierre e Miquelon", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva del Brunei", "BNST", "Ora del Brunei", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Ora di Choibalsan", "CHOT", "Ora estiva di Choibalsan", "CHOST", "Ora di Choibalsan", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Ora di Hovd", "HOVT", "Ora estiva di Hovd", "HOVST", "Ora di Hovd", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Ora di Irkutsk", "IRKT", - "Ora estiva di Irkutsk", "IRKST", - "Ora di Irkutsk", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"Ora dell'Indonesia orientale", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva di Petropavlovsk-Kamchatski", "PETST", "Ora di Petropavlovsk-Kamchatski", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Khandyga", new String[] {"Ora di Khandyga", "YAKT", "Ora estiva di Khandyga", "YAKST", "Ora di Khandyga", "YAKT"}}, - {"Asia/Krasnoyarsk", new String[] {"Ora di Krasnojarsk", "KRAT", - "Ora estiva di Krasnojarsk", "KRAST", - "Ora di Krasnojarsk", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora delle Filippine", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Ora di Oral", "ORAT", "Ora estiva di Oral", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Ora di Ust-Nera", "VLAT", "Ora estiva di Ust-Nera", "VLAST", "Ora di Ust-Nera", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Ora standard Australia centro-occidentale", "CWST", - "Ora estiva Australia centro-occidentale", "CWST", - "Ora Australia centro-occidentale", "CWT"}}, + {"Australia/Eucla", new String[] {"Ora standard Australia centro-occidentale", "ACWST", + "Ora estiva Australia centro-occidentale", "ACWDT", + "Ora Australia centro-occidentale", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Ora di Volgograd", "VOLT", - "Ora estiva di Volgograd", "VOLST", - "Ora di Volgograd", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java b/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java index 23bbcd6c8e0ff961ae47b3de4380bb88ed36f2d2..68bd6c30871be93078a30a3afb1ea110740cf63e 100644 --- a/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java +++ b/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String ACT[] = new String[] {"\u30a2\u30af\u30ec\u6642\u9593", "ACT", "\u30a2\u30af\u30ec\u590f\u6642\u9593", "ACST", "\u30a2\u30af\u30ec\u6642\u9593", "ACT"}; - String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CST", - "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CST", - "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CT"}; + String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACST", + "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACDT", + "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACT"}; String AGT[] = new String[] {"\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "ART", "\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u590f\u6642\u9593", "ARST", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6642\u9593", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String BDT[] = new String[] {"\u30d0\u30f3\u30b0\u30e9\u30c7\u30b7\u30e5\u6642\u9593", "BDT", "\u30d0\u30f3\u30b0\u30e9\u30c7\u30b7\u30e5\u590f\u6642\u9593", "BDST", "\u30D0\u30F3\u30B0\u30E9\u30C7\u30B7\u30E5\u6642\u9593", "BDT"}; - String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "EST", - "\u6771\u90E8\u590F\u6642\u9593(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "EST", - "\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "ET"}; - String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "CST", - "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "CST", - "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "CT"}; + String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "AEST", + "\u6771\u90E8\u590F\u6642\u9593(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "AEDT", + "\u6771\u90E8\u6A19\u6E96\u6642(\u30AF\u30A4\u30FC\u30F3\u30BA\u30E9\u30F3\u30C9)", "AET"}; + String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ACST", + "\u4E2D\u90E8\u590F\u6642\u9593(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ACDT", + "\u4E2D\u90E8\u6A19\u6E96\u6642(\u5357\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2/\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ACT"}; String BRT[] = new String[] {"\u30d6\u30e9\u30b8\u30eb\u6642\u9593", "BRT", "\u30d6\u30e9\u30b8\u30eb\u590f\u6642\u9593", "BRST", "\u30D6\u30E9\u30B8\u30EA\u30A2\u6642\u9593", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String CUBA[] = new String[] {"\u30ad\u30e5\u30fc\u30d0\u6a19\u6e96\u6642", "CST", "\u30ad\u30e5\u30fc\u30d0\u590f\u6642\u9593", "CDT", "\u30AD\u30E5\u30FC\u30D0\u6642\u9593", "CT"}; - String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "CST", - "\u4E2D\u90E8\u590F\u6642\u9593(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "CST", - "\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "CT"}; + String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "ACST", + "\u4E2D\u90E8\u590F\u6642\u9593(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "ACDT", + "\u4E2D\u90E8\u6A19\u6E96\u6642(\u30CE\u30FC\u30B6\u30F3\u30C6\u30EA\u30C8\u30EA\u30FC)", "ACT"}; String DUBLIN[] = new String[] {"\u30b0\u30ea\u30cb\u30c3\u30b8\u6a19\u6e96\u6642", "GMT", "\u30a2\u30a4\u30eb\u30e9\u30f3\u30c9\u590f\u6642\u9593", "IST", "\u30A2\u30A4\u30EB\u30E9\u30F3\u30C9\u6642\u9593", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String EST[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642", "EST", "\u6771\u90e8\u590f\u6642\u9593", "EDT", "\u6771\u90E8\u6A19\u6E96\u6642", "ET"}; - String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "EST", - "\u6771\u90E8\u590F\u6642\u9593(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "EST", - "\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "ET"}; + String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "AEST", + "\u6771\u90E8\u590F\u6642\u9593(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "AEDT", + "\u6771\u90E8\u6A19\u6E96\u6642(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)", "AET"}; String FET[] = new String[] {"\u6975\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u6642\u9593", "FET", "\u6975\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u590F\u6642\u9593", "FEST", "\u6975\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u6642\u9593", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String ICT[] = new String[] {"\u30a4\u30f3\u30c9\u30b7\u30ca\u6642\u9593", "ICT", "\u30a4\u30f3\u30c9\u30b7\u30ca\u590f\u6642\u9593", "ICST", "\u30A4\u30F3\u30C9\u30B7\u30CA\u6642\u9593", "ICT"}; + String IRKT[] = new String[] {"\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u6642\u9593", "IRKT", + "\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u590f\u6642\u9593", "IRKST", + "\u30A4\u30EB\u30AF\u30FC\u30C4\u30AF\u6642\u9593", "IRKT"}; String IRT[] = new String[] {"\u30a4\u30e9\u30f3\u6a19\u6e96\u6642", "IRST", "\u30a4\u30e9\u30f3\u590f\u6642\u9593", "IRDT", "\u30A4\u30E9\u30F3\u6642\u9593", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String JST[] = new String[] {"\u65e5\u672c\u6a19\u6e96\u6642", "JST", "\u65e5\u672c\u590f\u6642\u9593", "JDT", "\u65E5\u672C\u6642\u9593", "JT"}; + String KRAT[] = new String[] {"\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u6642\u9593", "KRAT", + "\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u590f\u6642\u9593", "KRAST", + "\u30AF\u30E9\u30B9\u30CE\u30E4\u30EB\u30B9\u30AF\u6642\u9593", "KRAT"}; String KST[] = new String[] {"\u97d3\u56fd\u6a19\u6e96\u6642", "KST", "\u97d3\u56fd\u590f\u6642\u9593", "KDT", "\u97D3\u56FD\u6642\u9593", "KT"}; String LORD_HOWE[] = new String[] {"\u30ed\u30fc\u30c9\u30cf\u30a6\u5cf6\u6a19\u6e96\u6642", "LHST", - "\u30ed\u30fc\u30c9\u30cf\u30a6\u5cf6\u590f\u6642\u9593", "LHST", + "\u30ed\u30fc\u30c9\u30cf\u30a6\u5cf6\u590f\u6642\u9593", "LHDT", "\u30ED\u30FC\u30C9\u30CF\u30A6\u6642\u9593", "LHT"}; String MHT[] = new String[] {"\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u6642\u9593", "MHT", "\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u590f\u6642\u9593", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String SGT[] = new String[] {"\u30b7\u30f3\u30ac\u30dd\u30fc\u30eb\u6642\u9593", "SGT", "\u30b7\u30f3\u30ac\u30dd\u30fc\u30eb\u590f\u6642\u9593", "SGST", "\u30B7\u30F3\u30AC\u30DD\u30FC\u30EB\u6642\u9593", "SGT"}; - String SLST[] = new String[] {"\u30b0\u30ea\u30cb\u30c3\u30b8\u6a19\u6e96\u6642", "GMT", - "\u30b7\u30a8\u30e9\u30ec\u30aa\u30cd\u590f\u6642\u9593", "SLST", - "\u30B7\u30A8\u30E9\u30EC\u30AA\u30CD\u6642\u9593", "SLT"}; - String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "EST", - "\u6771\u90E8\u590F\u6642\u9593(\u30BF\u30B9\u30DE\u30CB\u30A2)", "EST", - "\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "ET"}; + String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "AEST", + "\u6771\u90E8\u590F\u6642\u9593(\u30BF\u30B9\u30DE\u30CB\u30A2)", "AEDT", + "\u6771\u90E8\u6A19\u6E96\u6642(\u30BF\u30B9\u30DE\u30CB\u30A2)", "AET"}; String TMT[] = new String[] {"\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3\u6642\u9593", "TMT", "\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3\u590f\u6642\u9593", "TMST", "\u30C8\u30EB\u30AF\u30E1\u30CB\u30B9\u30BF\u30F3\u6642\u9593", "TMT"}; String ULAT[]= new String[] {"\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u6642\u9593", "ULAT", "\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u590f\u6642\u9593", "ULAST", "\u30A6\u30E9\u30F3\u30D0\u30FC\u30C8\u30EB\u6642\u9593", "ULAT"}; - String WART[] = new String[] {"\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "WART", - "\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u590f\u6642\u9593", "WARST"}; String WAT[] = new String[] {"\u897f\u30a2\u30d5\u30ea\u30ab\u6642\u9593", "WAT", "\u897f\u30a2\u30d5\u30ea\u30ab\u590f\u6642\u9593", "WAST", "\u897F\u90E8\u30A2\u30D5\u30EA\u30AB\u6642\u9593", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String WIT[] = new String[] {"\u897f\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u6642\u9593", "WIB", "\u897f\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u590f\u6642\u9593", "WIST", "\u897F\u90E8\u30A4\u30F3\u30C9\u30CD\u30B7\u30A2\u6642\u9593", "WIB"}; - String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "WST", - "\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "WST", - "\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "WT"}; + String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "AWST", + "\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "AWDT", + "\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "AWT"}; String SAMOA[] = new String[] {"\u30b5\u30e2\u30a2\u6a19\u6e96\u6642", "SST", "\u30b5\u30e2\u30a2\u590f\u6642\u9593", "SDT", "\u30B5\u30E2\u30A2\u6642\u9593", "ST"}; - String WST_SAMOA[] = new String[] {"\u897f\u30b5\u30e2\u30a2\u6642\u9593", "WST", + String WST_SAMOA[] = new String[] {"\u897f\u30b5\u30e2\u30a2\u6642\u9593", "WSST", "\u897f\u30b5\u30e2\u30a2\u590f\u6642\u9593", "WSDT", "\u897F\u30B5\u30E2\u30A2\u6642\u9593", "WST"}; String ChST[] = new String[] {"\u30b0\u30a2\u30e0\u6a19\u6e96\u6642", "ChST", "\u30b0\u30a2\u30e0\u590f\u6642\u9593", "ChDT", "\u30C1\u30E3\u30E2\u30ED\u6642\u9593", "ChT"}; - String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "EST", - "\u6771\u90E8\u590F\u6642\u9593(\u30D3\u30AF\u30C8\u30EA\u30A2)", "EST", - "\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "ET"}; + String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "AEST", + "\u6771\u90E8\u590F\u6642\u9593(\u30D3\u30AF\u30C8\u30EA\u30A2)", "AEDT", + "\u6771\u90E8\u6A19\u6E96\u6642(\u30D3\u30AF\u30C8\u30EA\u30A2)", "AET"}; String UTC[] = new String[] {"\u5354\u5b9a\u4e16\u754c\u6642", "UTC", "\u5354\u5b9a\u4e16\u754c\u6642", "UTC", "\u5354\u5B9A\u4E16\u754C\u6642", "UTC"}; String UZT[] = new String[] {"\u30a6\u30ba\u30d9\u30ad\u30b9\u30bf\u30f3\u6642\u9593", "UZT", "\u30a6\u30ba\u30d9\u30ad\u30b9\u30bf\u30f3\u590f\u6642\u9593", "UZST", "\u30A6\u30BA\u30D9\u30AD\u30B9\u30BF\u30F3\u6642\u9593", "UZT"}; + String XJT[] = new String[] {"\u4e2d\u56fd\u6a19\u6e96\u6642", "XJT", + "\u4e2d\u56fd\u590f\u6642\u9593", "XJDT", + "\u4E2D\u56FD\u6642\u9593", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u897f\u30b0\u30ea\u30fc\u30f3\u30e9\u30f3\u30c9\u590f\u6642\u9593", "WGST", "\u897F\u90E8\u30B0\u30EA\u30FC\u30F3\u30E9\u30F3\u30C9\u6642\u9593", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"\u30E1\u30C8\u30E9\u30AB\u30C8\u30E9\u6A19\u6E96\u6642\u9593", "MeST", - "\u30E1\u30C8\u30E9\u30AB\u30C8\u30E9\u590F\u6642\u9593", "MeDT", - "\u30E1\u30C8\u30E9\u30AB\u30C8\u30E9\u6642\u9593", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u30fb\u30df\u30af\u30ed\u30f3\u8af8\u5cf6\u6a19\u6e96\u6642", "PMST", "\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u30fb\u30df\u30af\u30ed\u30f3\u8af8\u5cf6\u590f\u6642\u9593", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30d6\u30eb\u30cd\u30a4\u590f\u6642\u9593", "BNST", "\u30D6\u30EB\u30CD\u30A4\u6642\u9593", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"\u30c1\u30e7\u30a4\u30d0\u30eb\u30b5\u30f3\u6642\u9593", "CHOT", "\u30c1\u30e7\u30a4\u30d0\u30eb\u30b5\u30f3\u590f\u6642\u9593", "CHOST", "\u30C1\u30E7\u30A4\u30D0\u30EB\u30B5\u30F3\u6642\u9593", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"\u30db\u30d6\u30c9\u6642\u9593", "HOVT", "\u30db\u30d6\u30c9\u590f\u6642\u9593", "HOVST", "\u30DB\u30D6\u30C9\u6642\u9593", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u6642\u9593", "IRKT", - "\u30a4\u30eb\u30af\u30fc\u30c4\u30af\u590f\u6642\u9593", "IRKST", - "\u30A4\u30EB\u30AF\u30FC\u30C4\u30AF\u6642\u9593", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"\u6771\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u6642\u9593", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30da\u30c8\u30ed\u30d1\u30d6\u30ed\u30d5\u30b9\u30af\u30ab\u30e0\u30c1\u30e3\u30c4\u30ad\u30fc\u590f\u6642\u9593", "PETST", "\u30DA\u30C8\u30ED\u30D1\u30D6\u30ED\u30D5\u30B9\u30AF\u30FB\u30AB\u30E0\u30C1\u30E3\u30C4\u30AD\u30FC\u6642\u9593", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"\u30CF\u30F3\u30C9\u30A5\u30A4\u30AC\u6642\u9593", "YAKT", "\u30CF\u30F3\u30C9\u30A5\u30A4\u30AC\u590F\u6642\u9593", "YAKST", "\u30CF\u30F3\u30C9\u30A5\u30A4\u30AC\u6642\u9593", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u6642\u9593", "KRAT", - "\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u590f\u6642\u9593", "KRAST", - "\u30AF\u30E9\u30B9\u30CE\u30E4\u30EB\u30B9\u30AF\u6642\u9593", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30D5\u30A3\u30EA\u30D4\u30F3\u6642\u9593", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"\u30aa\u30e9\u30eb\u6642\u9593", "ORAT", "\u30aa\u30e9\u30eb\u590f\u6642\u9593", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"\u30A6\u30B9\u30C1\u30CD\u30E9\u6642\u9593", "VLAT", "\u30A6\u30B9\u30C1\u30CD\u30E9\u590F\u6642\u9593", "VLAST", "\u30A6\u30B9\u30C1\u30CD\u30E9\u6642\u9593", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CWST", - "\u4E2D\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CWST", - "\u4E2D\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "CWT"}}, + {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACWST", + "\u4E2D\u897F\u90E8\u590F\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACWDT", + "\u4E2D\u897F\u90E8\u6642\u9593(\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"\u30dc\u30eb\u30b4\u30b0\u30e9\u30fc\u30c9\u6642\u9593", "VOLT", - "\u30dc\u30eb\u30b4\u30b0\u30e9\u30fc\u30c9\u590f\u6642\u9593", "VOLST", - "\u30DC\u30EB\u30B4\u30B0\u30E9\u30FC\u30C9\u6642\u9593", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java b/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java index d1e106e2cd82f9d50c9794c134deb0bc9cee3411..fcfd748153eeb6c19aed7237155df61132a060a7 100644 --- a/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java +++ b/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String ACT[] = new String[] {"\uc5d0\uc774\ucee4 \uc2dc\uac04", "ACT", "\uc5d0\uc774\ucee4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ACST", "\uc5d0\uc774\ucee4 \uc2dc\uac04", "ACT"}; - String ADELAIDE[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CST", - "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CST", - "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CT"}; + String ADELAIDE[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACST", + "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACDT", + "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACT"}; String AGT[] = new String[] {"\uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "ART", "\uc544\ub974\ud5e8\ud2f0\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ARST", "\uC544\uB974\uD5E8\uD2F0\uB098 \uD45C\uC900\uC2DC", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String BDT[] = new String[] {"\ubc29\uae00\ub77c\ub370\uc2dc \uc2dc\uac04", "BDT", "\ubc29\uae00\ub77c\ub370\uc2dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BDST", "\uBC29\uAE00\uB77C\uB370\uC2DC \uD45C\uC900\uC2DC", "BDT"}; - String BRISBANE[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "EST", - "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD038\uC990\uB79C\uB4DC)", "EST", - "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "ET"}; - String BROKEN_HILL[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "CST", - "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "CST", - "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "CT"}; + String BRISBANE[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "AEST", + "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD038\uC990\uB79C\uB4DC)", "AEDT", + "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD038\uC990\uB79C\uB4DC)", "AET"}; + String BROKEN_HILL[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ACST", + "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ACDT", + "\uC911\uBD80 \uD45C\uC900\uC2DC(\uB0A8\uBD80 \uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544/\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ACT"}; String BRT[] = new String[] {"\ube0c\ub77c\uc9c8\ub9ac\uc544 \uc2dc\uac04", "BRT", "\ube0c\ub77c\uc9c8\ub9ac\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BRST", "\uBE0C\uB77C\uC9C8\uB9AC\uC544 \uD45C\uC900\uC2DC", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String CUBA[] = new String[] {"\ucfe0\ubc14 \ud45c\uc900\uc2dc", "CST", "\ucfe0\ubc14 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT", "\uCFE0\uBC14 \uD45C\uC900\uC2DC", "CT"}; - String DARWIN[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "CST", - "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBD81\uBD80 \uC9C0\uC5ED)", "CST", - "\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "CT"}; + String DARWIN[] = new String[] {"\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "ACST", + "\uC911\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBD81\uBD80 \uC9C0\uC5ED)", "ACDT", + "\uC911\uBD80 \uD45C\uC900\uC2DC(\uBD81\uBD80 \uC9C0\uC5ED)", "ACT"}; String DUBLIN[] = new String[] {"\uadf8\ub9ac\ub2c8\uce58 \ud45c\uc900\uc2dc", "GMT", "\uc544\uc77c\ub79c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IST", "\uC544\uC77C\uB79C\uB4DC \uD45C\uC900\uC2DC", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String EST[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc", "EST", "\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "EDT", "\uB3D9\uBD80 \uD45C\uC900\uC2DC", "ET"}; - String EST_NSW[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "EST", - "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "EST", - "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "ET"}; + String EST_NSW[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "AEST", + "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "AEDT", + "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)", "AET"}; String FET[] = new String[] {"\uADF9\uB3D9 \uC720\uB7FD \uD45C\uC900\uC2DC", "FET", "\uADF9\uB3D9 \uC720\uB7FD \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "FEST", "\uADF9\uB3D9 \uC720\uB7FD \uD45C\uC900\uC2DC", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String ICT[] = new String[] {"\uc778\ub3c4\ucc28\uc774\ub098 \ubc18\ub3c4 \uc2dc\uac04", "ICT", "\uc778\ub3c4\ucc28\uc774\ub098 \ubc18\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ICST", "\uC778\uB3C4\uCC28\uC774\uB098 \uBC18\uB3C4 \uD45C\uC900\uC2DC", "ICT"}; + String IRKT[] = new String[] {"\uc774\ub974\ucfe0\uce20\ud06c \uc2dc\uac04", "IRKT", + "\uc774\ub974\ucfe0\uce20\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IRKST", + "\uC774\uB974\uCFE0\uCE20\uD06C \uD45C\uC900\uC2DC", "IRKT"}; String IRT[] = new String[] {"\uc774\ub780 \ud45c\uc900\uc2dc", "IRST", "\uc774\ub780 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IRDT", "\uC774\uB780 \uD45C\uC900\uC2DC", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String JST[] = new String[] {"\uc77c\ubcf8 \ud45c\uc900\uc2dc", "JST", "\uc77c\ubcf8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "JDT", "\uC77C\uBCF8 \uD45C\uC900\uC2DC", "JT"}; + String KRAT[] = new String[] {"\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc2dc\uac04", "KRAT", + "\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KRAST", + "\uD06C\uB77C\uC2A4\uB178\uC57C\uB974\uC2A4\uD06C \uD45C\uC900\uC2DC", "KRAT"}; String KST[] = new String[] {"\ud55c\uad6d \ud45c\uc900\uc2dc", "KST", "\ud55c\uad6d \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KDT", "\uB300\uD55C\uBBFC\uAD6D \uD45C\uC900\uC2DC", "KT"}; String LORD_HOWE[] = new String[] {"\ub85c\ub4dc \ud558\uc6b0 \ud45c\uc900\uc2dc", "LHST", - "\ub85c\ub4dc \ud558\uc6b0 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "LHST", + "\ub85c\ub4dc \ud558\uc6b0 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "LHDT", "\uB85C\uB4DC\uD558\uC6B0 \uD45C\uC900\uC2DC", "LHT"}; String MHT[] = new String[] {"\ub9c8\uc15c\uc81c\ub3c4 \uc2dc\uac04", "MHT", "\ub9c8\uc15c\uc81c\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String SGT[] = new String[] {"\uc2f1\uac00\ud3ec\ub974 \uc2dc\uac04", "SGT", "\uc2f1\uac00\ud3ec\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SGST", "\uC2F1\uAC00\uD3EC\uB974 \uD45C\uC900\uC2DC", "SGT"}; - String SLST[] = new String[] {"\uadf8\ub9ac\ub2c8\uce58 \ud45c\uc900\uc2dc", "GMT", - "\uc2dc\uc5d0\ub77c\ub9ac\uc628 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SLST", - "\uC2DC\uC5D0\uB77C\uB9AC\uC628 \uD45C\uC900\uC2DC", "SLT"}; - String TASMANIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "EST", - "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "EST", - "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "ET"}; + String TASMANIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "AEST", + "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "AEDT", + "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uD0DC\uC988\uBA54\uC774\uB2C8\uC544)", "AET"}; String TMT[] = new String[] {"\ud22c\ub974\ud06c\uba54\ub2c8\uc2a4\ud0c4 \uc2dc\uac04", "TMT", "\ud22c\ub974\ud06c\uba54\ub2c8\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TMST", "\uD22C\uB974\uD06C\uBA54\uB2C8\uC2A4\uD0C4 \uD45C\uC900\uC2DC", "TMT"}; String ULAT[]= new String[] {"\uc6b8\ub780\ubc14\ud0c0\ub974 \uc2dc\uac04", "ULAT", "\uc6b8\ub780\ubc14\ud0c0\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ULAST", "\uC6B8\uB780\uBC14\uD1A0\uB974 \uD45C\uC900\uC2DC", "ULAT"}; - String WART[] = new String[] {"\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "WART", - "\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WARST"}; String WAT[] = new String[] {"\uc11c\ubd80 \uc544\ud504\ub9ac\uce74 \uc2dc\uac04", "WAT", "\uc11c\ubd80 \uc544\ud504\ub9ac\uce74 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WAST", "\uC11C\uBD80 \uC544\uD504\uB9AC\uCE74 \uD45C\uC900\uC2DC", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String WIT[] = new String[] {"\uc11c\uc778\ub3c4\ub124\uc2dc\uc544 \uc2dc\uac04", "WIB", "\uc11c\uc778\ub3c4\ub124\uc2dc\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WIST", "\uC11C\uBD80 \uC778\uB3C4\uB124\uC2DC\uC544 \uD45C\uC900\uC2DC", "WIB"}; - String WST_AUS[] = new String[] {"\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "WST", - "\uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "WST", - "\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "WT"}; + String WST_AUS[] = new String[] {"\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "AWST", + "\uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "AWDT", + "\uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "AWT"}; String SAMOA[] = new String[] {"\uc0ac\ubaa8\uc544 \ud45c\uc900\uc2dc", "SST", "\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SDT", "\uC0AC\uBAA8\uC544 \uD45C\uC900\uC2DC", "ST"}; - String WST_SAMOA[] = new String[] {"\uc11c\uc0ac\ubaa8\uc544 \uc2dc\uac04", "WST", + String WST_SAMOA[] = new String[] {"\uc11c\uc0ac\ubaa8\uc544 \uc2dc\uac04", "WSST", "\uc11c\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WSDT", "\uC11C\uC0AC\uBAA8\uC544 \uD45C\uC900\uC2DC", "WST"}; String ChST[] = new String[] {"\ucc28\ubaa8\ub85c \ud45c\uc900\uc2dc", "ChST", "\ucc28\ubaa8\ub85c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ChDT", "\uCC28\uBAA8\uB974 \uD45C\uC900\uC2DC", "ChT"}; - String VICTORIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "EST", - "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBE45\uD1A0\uB9AC\uC544)", "EST", - "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "ET"}; + String VICTORIA[] = new String[] {"\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "AEST", + "\uB3D9\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uBE45\uD1A0\uB9AC\uC544)", "AEDT", + "\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uBE45\uD1A0\uB9AC\uC544)", "AET"}; String UTC[] = new String[] {"\uc138\uacc4 \ud45c\uc900\uc2dc", "UTC", "\uc138\uacc4 \ud45c\uc900\uc2dc", "UTC", "\uC9C0\uC5ED \uD45C\uC900\uC2DC", "UTC"}; String UZT[] = new String[] {"\uc6b0\uc988\ubca0\ud0a4\uc2a4\ud0c4 \uc2dc\uac04", "UZT", "\uc6b0\uc988\ubca0\ud0a4\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "UZST", "\uC6B0\uC988\uBCA0\uD0A4\uC2A4\uD0C4 \uD45C\uC900\uC2DC", "UZT"}; + String XJT[] = new String[] {"\uc911\uad6d \ud45c\uc900\uc2dc", "XJT", + "\uc911\uad6d \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "XJDT", + "\uC911\uAD6D \uD45C\uC900\uC2DC", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\uc11c\ubd80 \uadf8\ub9b0\ub79c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WGST", "\uC11C\uBD80 \uADF8\uB9B0\uB780\uB4DC \uD45C\uC900\uC2DC", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"\uBA54\uD2B8\uB77C\uCE74\uD2B8\uB77C \uD45C\uC900\uC2DC", "MeST", - "\uBA54\uD2B8\uB77C\uCE74\uD2B8\uB77C \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "MeDT", - "\uBA54\uD2B8\uB77C\uCE74\uD2B8\uB77C \uD45C\uC900\uC2DC", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"\ud53c\uc5d0\ub974 \ubbf8\ud06c\ub860 \ud45c\uc900\uc2dc", "PMST", "\ud53c\uc5d0\ub974 \ubbf8\ud06c\ub860 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ube0c\ub8e8\ub098\uc774 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BNST", "\uBE0C\uB8E8\uB098\uC774 \uD45C\uC900\uC2DC", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Choibalsan \uc2dc\uac04", "CHOT", "Choibalsan \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CHOST", "\uCD08\uC774\uBC1C\uC0B0 \uD45C\uC900\uC2DC", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Hovd \uc2dc\uac04", "HOVT", "Hovd \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "HOVST", "\uD638\uBE0C\uB4DC \uD45C\uC900\uC2DC", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"\uc774\ub974\ucfe0\uce20\ud06c \uc2dc\uac04", "IRKT", - "\uc774\ub974\ucfe0\uce20\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "IRKST", - "\uC774\uB974\uCFE0\uCE20\uD06C \uD45C\uC900\uC2DC", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"\ub3d9\ubd80 \uc778\ub3c4\ub124\uc2dc\uc544 \uc2dc\uac04", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ud398\ud2b8\ub85c\ud30c\ube14\ub85c\ud504\uc2a4\ud06c-\uce84\ucc28\uce20\ud0a4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PETST", "\uD398\uD2B8\uB85C\uD30C\uBE0C\uB85C\uD504\uC2A4\uD06C-\uCE84\uCC28\uCE20\uD0A4 \uD45C\uC900\uC2DC", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"\uD55C\uB514\uAC00 \uD45C\uC900\uC2DC", "YAKT", "\uD55C\uB514\uAC00 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "YAKST", "\uD55C\uB514\uAC00 \uD45C\uC900\uC2DC", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc2dc\uac04", "KRAT", - "\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KRAST", - "\uD06C\uB77C\uC2A4\uB178\uC57C\uB974\uC2A4\uD06C \uD45C\uC900\uC2DC", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\uD544\uB9AC\uD540 \uD45C\uC900\uC2DC", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral \ud45c\uc900\uc2dc", "ORAT", "Oral \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"\uC6B0\uC2A4\uD2F0\uB124\uB77C \uD45C\uC900\uC2DC", "VLAT", "\uC6B0\uC2A4\uD2F0\uB124\uB77C \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04", "VLAST" , "\uC6B0\uC2A4\uD2F0\uB124\uB77C \uD45C\uC900\uC2DC", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CWST", - "\uC911\uC559 \uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CWST", - "\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "CWT"}}, + {"Australia/Eucla", new String[] {"\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACWST", + "\uC911\uC559 \uC11C\uBD80 \uC77C\uAD11 \uC808\uC57D \uC2DC\uAC04(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACWDT", + "\uC911\uC559 \uC11C\uBD80 \uD45C\uC900\uC2DC(\uC624\uC2A4\uD2B8\uB808\uC77C\uB9AC\uC544)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"\ubcfc\uace0\uadf8\ub77c\ub4dc \uc2dc\uac04", "VOLT", - "\ubcfc\uace0\uadf8\ub77c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VOLST", - "\uBCFC\uACE0\uADF8\uB77C\uB4DC \uD45C\uC900\uC2DC", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/lt/CurrencyNames_lt_LT.properties b/src/share/classes/sun/util/resources/lt/CurrencyNames_lt_LT.properties index f7275219e28def5a54f7ab4ce364169354d4d37b..a0884fafef501a09ada62b4a64ce5a634f123dd1 100644 --- a/src/share/classes/sun/util/resources/lt/CurrencyNames_lt_LT.properties +++ b/src/share/classes/sun/util/resources/lt/CurrencyNames_lt_LT.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,4 +35,5 @@ # This notice and attribution to Taligent may not be removed. # Taligent is a registered trademark of Taligent, Inc. +EUR=\u20AC LTL=Lt diff --git a/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java b/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java index 21852adbb674bf98dcd450afa1468c24696fd711..60664c5b1f1fb1dd444838137a0007df3d0836e4 100644 --- a/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java +++ b/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String ACT[] = new String[] {"Fuso hor\u00e1rio do Acre", "ACT", "Fuso hor\u00e1rio de ver\u00e3o do Acre", "ACST", "Fuso hor\u00e1rio do Acre", "ACT"}; - String ADELAIDE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul)", "CST", - "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul)", "CST", - "Hor\u00E1rio Central (Austr\u00E1lia do Sul)", "CT"}; + String ADELAIDE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul)", "ACST", + "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul)", "ACDT", + "Hor\u00E1rio Central (Austr\u00E1lia do Sul)", "ACT"}; String AGT[] = new String[] {"Fuso hor\u00e1rio da Argentina", "ART", "Fuso hor\u00e1rio de ver\u00e3o da Argentina", "ARST", "Hor\u00E1rio da Argentina", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String BDT[] = new String[] {"Fuso hor\u00e1rio de Bangladesh", "BDT", "Fuso hor\u00e1rio de ver\u00e3o de Bangladesh", "BDST", "Hor\u00E1rio de Bangladesh", "BDT"}; - String BRISBANE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Queensland)", "EST", - "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Queensland)", "EST", - "Hor\u00E1rio do Leste (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "CST", - "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "CST", - "Hor\u00E1rio Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "CT"}; + String BRISBANE[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Queensland)", "AEST", + "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Queensland)", "AEDT", + "Hor\u00E1rio do Leste (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "ACST", + "Fuso Hor\u00E1rio de Ver\u00E3o Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "ACDT", + "Hor\u00E1rio Central (Austr\u00E1lia do Sul/Nova Gales do Sul)", "ACT"}; String BRT[] = new String[] {"Fuso hor\u00e1rio de Bras\u00edlia", "BRT", "Fuso hor\u00e1rio de ver\u00e3o de Bras\u00edlia", "BRST", "Hor\u00E1rio de Bras\u00EDlia", "BRT"}; @@ -108,9 +108,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Cuba", "CST", "Hor\u00e1rio de luz natural de Cuba", "CDT", "Hor\u00E1rio de Cuba", "CT"}; - String DARWIN[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Territ\u00F3rio do Norte)", "CST", - "Fuso Hor\u00E1rio de Ver\u00E3o Central (Territ\u00F3rio do Norte)", "CST", - "Hor\u00E1rio Central (Territ\u00F3rio do Norte)", "CT"}; + String DARWIN[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Central (Territ\u00F3rio do Norte)", "ACST", + "Fuso Hor\u00E1rio de Ver\u00E3o Central (Territ\u00F3rio do Norte)", "ACDT", + "Hor\u00E1rio Central (Territ\u00F3rio do Norte)", "ACT"}; String DUBLIN[] = new String[] {"Fuso hor\u00e1rio do meridiano de Greenwich", "GMT", "Fuso hor\u00e1rio de ver\u00e3o da Irlanda", "IST", "Hor\u00E1rio da Rep\u00FAblica da Irlanda", "IT"}; @@ -129,9 +129,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String EST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental", "EST", "Hor\u00e1rio de luz natural oriental", "EDT", "Hor\u00E1rio do Leste", "ET"}; - String EST_NSW[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Oriental (Nova Gales do Sul)", "EST", - "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Nova Gales do Sul)", "EST", - "Hor\u00E1rio Oriental (Nova Gales do Sul)", "ET"}; + String EST_NSW[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Oriental (Nova Gales do Sul)", "AEST", + "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Nova Gales do Sul)", "AEDT", + "Hor\u00E1rio Oriental (Nova Gales do Sul)", "AET"}; String FET[] = new String[] {"Hor\u00E1rio do Extremo Leste Europeu (FET)", "FET", "Fuso Hor\u00E1rio de Ver\u00E3o do Extremo Leste Europeu", "FEST", "Hor\u00E1rio do Extremo Leste Europeu (FET)", "FET"}; @@ -162,6 +162,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String ICT[] = new String[] {"Fuso hor\u00e1rio da Indochina", "ICT", "Fuso hor\u00e1rio de ver\u00e3o da Indochina", "ICST", "Hor\u00E1rio da Indochina", "ICT"}; + String IRKT[] = new String[] {"Fuso hor\u00e1rio de Irkutsk", "IRKT", + "Fuso hor\u00e1rio de ver\u00e3o de Irkutsk", "IRKST", + "Hor\u00E1rio de Irkutsk", "IRKT"}; String IRT[] = new String[] {"Fuso hor\u00e1rio do Ir\u00e3", "IRST", "Hor\u00e1rio de luz natural do Ir\u00e3", "IRDT", "Hor\u00E1rio do Ir\u00E3", "IRT"}; @@ -174,11 +177,14 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String JST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o do Jap\u00e3o", "JST", "Hor\u00e1rio de luz natural do Jap\u00e3o", "JDT", "Hor\u00E1rio do Jap\u00E3o", "JT"}; + String KRAT[] = new String[] {"Fuso hor\u00e1rio de Krasnoyarsk", "KRAT", + "Fuso hor\u00e1rio de ver\u00e3o de Krasnoyarsk", "KRAST", + "Hor\u00E1rio de Krasnoyarsk", "KRAT"}; String KST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o da Coreia", "KST", "Hor\u00e1rio de luz natural da Coreia", "KDT", "Hor\u00E1rio da Coreia", "KT"}; String LORD_HOWE[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Lord Howe", "LHST", - "Fuso hor\u00e1rio de ver\u00e3o de Lord Howe", "LHST", + "Fuso hor\u00e1rio de ver\u00e3o de Lord Howe", "LHDT", "Hor\u00E1rio de Lord Howe", "LHT"}; String MHT[] = new String[] {"Fuso hor\u00e1rio das Ilhas Marshall", "MHT", "Fuso hor\u00e1rio de ver\u00e3o das Ilhas Marshall", "MHST", @@ -228,12 +234,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String SGT[] = new String[] {"Fuso hor\u00e1rio de Cingapura", "SGT", "Fuso hor\u00e1rio de ver\u00e1 de Cingapura", "SGST", "Hor\u00E1rio de Cingapura", "SGT"}; - String SLST[] = new String[] {"Fuso hor\u00e1rio do meridiano de Greenwich", "GMT", - "Fuso hor\u00e1rio de ver\u00e3o de Serra Leoa", "SLST", - "Hor\u00E1rio de Serra Leoa", "SLT"}; - String TASMANIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Tasm\u00E2nia)", "EST", - "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Tasm\u00E2nia)", "EST", - "Hor\u00E1rio do Leste (Tasm\u00E2nia)", "ET"}; + String TASMANIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Tasm\u00E2nia)", "AEST", + "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Tasm\u00E2nia)", "AEDT", + "Hor\u00E1rio do Leste (Tasm\u00E2nia)", "AET"}; String TMT[] = new String[] {"Fuso hor\u00e1rio do Turcomenist\u00e3o", "TMT", "Fuso hor\u00e1rio de ver\u00e3o do Turcomenist\u00e3o", "TMST", "Hor\u00E1rio do Turcomenist\u00E3o", "TMT"}; @@ -252,29 +255,30 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String WIT[] = new String[] {"Fuso hor\u00e1rio da Indon\u00e9sia Ocidental", "WIB", "Fuso hor\u00e1rio de ver\u00e3o da Indon\u00e9sia Ocidental", "WIST", "Hor\u00E1rio da Indon\u00E9sia Ocidental", "WIB"}; - String WST_AUS[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Ocidental (Austr\u00E1lia)", "WST", - "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental (Austr\u00E1lia)", "WST", - "Hor\u00E1rio Ocidental (Austr\u00E1lia)", "WT"}; + String WST_AUS[] = new String[] {"Hor\u00E1rio-Padr\u00E3o Ocidental (Austr\u00E1lia)", "AWST", + "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental (Austr\u00E1lia)", "AWDT", + "Hor\u00E1rio Ocidental (Austr\u00E1lia)", "AWT"}; String SAMOA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Samoa", "SST", "Hor\u00e1rio de luz natural de Samoa", "SDT", "Hor\u00E1rio da Samoa", "ST"}; - String WST_SAMOA[] = new String[] {"Fuso hor\u00e1rio de Samoa Ocidental", "WST", + String WST_SAMOA[] = new String[] {"Fuso hor\u00e1rio de Samoa Ocidental", "WSST", "Fuso hor\u00e1rio de ver\u00e3o de Samoa Ocidental", "WSDT", "Fuso Hor\u00E1rio de Samoa Ocidental", "WST"}; String ChST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Chamorro", "ChST", "Hor\u00e1rio de luz natural de Chamorro", "ChDT", "Hor\u00E1rio de Chamorro", "ChT"}; - String VICTORIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Victoria)", "EST", - "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Victoria)", "EST", - "Hor\u00E1rio do Leste (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"Hor\u00E1rio-Padr\u00E3o do Leste (Victoria)", "AEST", + "Fuso Hor\u00E1rio de Ver\u00E3o Oriental (Victoria)", "AEDT", + "Hor\u00E1rio do Leste (Victoria)", "AET"}; String UTC[] = new String[] {"Tempo universal coordenado", "UTC", "Tempo universal coordenado", "UTC", "Hor\u00E1rio Universal Coordenado", "UTC"}; String UZT[] = new String[] {"Fuso hor\u00e1rio do Uzbequist\u00e3o", "UZT", "Fuso hor\u00e1rio de ver\u00e3o do Uzbequist\u00e3o", "UZST", "Hor\u00E1rio do Uzbequist\u00E3o", "UZT"}; - String WART[] = new String[] {"Fuso hor\u00e1rio da Argentina Ocidental", "WART", - "Fuso hor\u00e1rio de ver\u00e3o da Argentina Ocidental", "WARST"}; + String XJT[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o da China", "XJT", + "Hor\u00e1rio de luz natural da China", "XJDT", + "Hor\u00E1rio da China", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o da Groenl\u00e2ndia Ocidental", "WGST", "Hor\u00E1rio da Groenl\u00E2ndia Ocidental", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Hor\u00E1rio Padr\u00E3o de Metlakatla", "MeST", - "Hor\u00E1rio de Luz Natural de Metlakatla", "MeDT", - "Hor\u00E1rio de Metlakatla", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Fuso hor\u00e1rio padr\u00e3o de S\u00e3o Pedro e Miquelon", "PMST", "Hor\u00e1rio de luz natural de S\u00e3o Pedro e Miquelon", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o de Brunei", "BNST", "Hor\u00E1rio de Brunei", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Fuso hor\u00e1rio de Choibalsan", "CHOT", "Fuso hor\u00e1rio de ver\u00e3o de Choibalsan", "CHOST", "Hor\u00E1rio de Choibalsan", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Fuso hor\u00e1rio de Hovd", "HOVT", "Fuso hor\u00e1rio de ver\u00e3o de Hovd", "HOVST", "Hor\u00E1rio de Hovd", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Fuso hor\u00e1rio de Irkutsk", "IRKT", - "Fuso hor\u00e1rio de ver\u00e3o de Irkutsk", "IRKST", - "Hor\u00E1rio de Irkutsk", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"Fuso hor\u00e1rio da Indon\u00e9sia Oriental", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o de Petropavlovsk-Kamchatski", "PETST", "Hor\u00E1rio de Petropavlovsk-Kamchatski", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Hor\u00E1rio de Khandyga", "YAKT", "Hor\u00E1rio de Ver\u00E3o de Khandyga", "YAKST", "Hor\u00E1rio de Khandyga", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Fuso hor\u00e1rio de Krasnoyarsk", "KRAT", - "Fuso hor\u00e1rio de ver\u00e3o de Krasnoyarsk", "KRAST", - "Hor\u00E1rio de Krasnoyarsk", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Hor\u00E1rio das Filipinas", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Fuso hor\u00e1rio de Uralsk", "ORAT", "Fuso hor\u00e1rio de ver\u00e3o de Uralsk", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Hor\u00E1rio de Ust-Nera", "VLAT", "Hor\u00E1rio de Ver\u00E3o de Ust-Nera", "VLAST", "Hor\u00E1rio de Ust-Nera", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Fuso Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "CWST", - "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental Central (Austr\u00E1lia)", "CWST", - "Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "CWT"}}, + {"Australia/Eucla", new String[] {"Fuso Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "ACWST", + "Fuso Hor\u00E1rio de Ver\u00E3o Ocidental Central (Austr\u00E1lia)", "ACWDT", + "Hor\u00E1rio Ocidental Central (Austr\u00E1lia)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Fuso hor\u00e1rio de Volgogrado", "VOLT", - "Fuso hor\u00e1rio de ver\u00e3o de Volgogrado", "VOLST", - "Hor\u00E1rio de Volgogrado", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java b/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java index dd509e15142410245aadfd16f0eefe33c1f93077..ab28e0054a05b6e75fcc4db9129fd23f056657d6 100644 --- a/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java +++ b/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String ACT[] = new String[] {"Acre, normaltid", "ACT", "Acre, sommartid", "ACST", "Acre, normaltid", "ACT"}; - String ADELAIDE[] = new String[] {"Central standardtid (Sydaustralien)", "CST", - "Central sommartid (South Australia)", "CST", - "Central tid (Sydaustralien)", "CT"}; + String ADELAIDE[] = new String[] {"Central standardtid (Sydaustralien)", "ACST", + "Central sommartid (South Australia)", "ACDT", + "Central tid (Sydaustralien)", "ACT"}; String AGT[] = new String[] {"Argentina, normaltid", "ART", "Argentina, sommartid", "ARST", "Argentinsk tid", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String BDT[] = new String[] {"Bangladesh, normaltid", "BDT", "Bangladesh, sommartid", "BDST", "Bangladeshisk tid", "BDT"}; - String BRISBANE[] = new String[] {"\u00D6stlig standardtid (Queensland)", "EST", - "\u00D6stlig sommartid (Queensland)", "EST", - "\u00D6stlig tid (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Central standardtid (Sydaustralien/New South Wales)", "CST", - "Central sommartid (South Australia/New South Wales)", "CST", - "Central tid (Sydaustralien/New South Wales)", "CT"}; + String BRISBANE[] = new String[] {"\u00D6stlig standardtid (Queensland)", "AEST", + "\u00D6stlig sommartid (Queensland)", "AEDT", + "\u00D6stlig tid (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Central standardtid (Sydaustralien/New South Wales)", "ACST", + "Central sommartid (South Australia/New South Wales)", "ACDT", + "Central tid (Sydaustralien/New South Wales)", "ACT"}; String BRT[] = new String[] {"Brasilien, normaltid", "BRT", "Brasilien, sommartid", "BRST", "Brasiliansk tid", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Kuba, normaltid", "CST", "Kuba, sommartid", "CDT", "Kubansk tid", "CT"}; - String DARWIN[] = new String[] {"Central standardtid (Nordterritoriet)", "CST", - "Central sommartid (Nordterritoriet)", "CST", - "Central tid (Nordterritoriet)", "CT"}; + String DARWIN[] = new String[] {"Central standardtid (Nordterritoriet)", "ACST", + "Central sommartid (Nordterritoriet)", "ACDT", + "Central tid (Nordterritoriet)", "ACT"}; String DUBLIN[] = new String[] {"Greenwichtid", "GMT", "Irland, sommartid", "IST", "Irl\u00E4ndsk tid", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String EST[] = new String[] {"Eastern, normaltid", "EST", "Eastern, sommartid", "EDT", "\u00D6stlig tid", "ET"}; - String EST_NSW[] = new String[] {"\u00D6stlig standardtid (New South Wales)", "EST", - "\u00D6stlig sommartid (New South Wales)", "EST", - "\u00D6stlig tid (New South Wales)", "ET"}; + String EST_NSW[] = new String[] {"\u00D6stlig standardtid (New South Wales)", "AEST", + "\u00D6stlig sommartid (New South Wales)", "AEDT", + "\u00D6stlig tid (New South Wales)", "AET"}; String FET[] = new String[] {"Kaliningradtid", "FET", "\u00D6steuropeisk sommartid", "FEST", "Kaliningradtid", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String ICT[] = new String[] {"Indokinesisk tid", "ICT", "Indokinesisk sommartid", "ICST", "Indokinesisk tid", "ICT"}; + String IRKT[] = new String[] {"Irkutsk, normaltid", "IRKT", + "Irkutsk, sommartid", "IRKST", + "Irkutsk-tid", "IRKT"}; String IRT[] = new String[] {"Iran, normaltid", "IRST", "Iran, sommartid", "IRDT", "Iransk tid", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String JST[] = new String[] {"Japan, normaltid", "JST", "Japan, sommartid", "JDT", "Japansk tid", "JT"}; + String KRAT[] = new String[] {"Krasnojarsk, normaltid", "KRAT", + "Krasnojarsk, sommartid", "KRAST", + "Krasnojarsk-tid", "KRAT"}; String KST[] = new String[] {"Korea, normaltid", "KST", "Korea, sommartid", "KDT", "Koreansk tid", "KT"}; String LORD_HOWE[] = new String[] {"Lord Howe, normaltid", "LHST", - "Lord Howe, sommartid", "LHST", + "Lord Howe, sommartid", "LHDT", "Lord Howe-tid", "LHT"}; String MHT[] = new String[] {"Marshall\u00f6arna, normaltid", "MHT", "Marshall\u00f6arna, sommartid", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String SGT[] = new String[] {"Singapore, normaltid", "SGT", "Singapore, sommartid", "SGST", "Singapore-tid", "SGT"}; - String SLST[] = new String[] {"Greenwichtid", "GMT", - "Sierra Leone, sommartid", "SLST", - "Sierra Leone-tid", "SLT"}; - String TASMANIA[] = new String[] {"\u00D6stlig standardtid (Tasmania)", "EST", - "\u00D6stlig sommartid (Tasmanien)", "EST", - "\u00D6stlig tid (Tasmania)", "ET"}; + String TASMANIA[] = new String[] {"\u00D6stlig standardtid (Tasmania)", "AEST", + "\u00D6stlig sommartid (Tasmanien)", "AEDT", + "\u00D6stlig tid (Tasmania)", "AET"}; String TMT[] = new String[] {"Turkmenistan, normaltid", "TMT", "Turkmenistan, sommartid", "TMST", "Turkmensk tid", "TMT"}; String ULAT[]= new String[] {"Ulaanbaatar, normaltid", "ULAT", "Ulaanbaatar, sommartid", "ULAST", "Ulaanbaatar-tid", "ULAT"}; - String WART[] = new String[] {"V\u00e4stargentina, normaltid", "WART", - "V\u00e4stargentina, sommartid", "WARST"}; String WAT[] = new String[] {"V\u00e4stafrikansk tid", "WAT", "V\u00e4stafrikansk sommartid", "WAST", "V\u00E4stafrikansk tid", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String WIT[] = new String[] {"V\u00e4stindonesisk tid", "WIB", "V\u00e4stindonesisk sommartid", "WIST", "V\u00E4stindonesisk tid", "WIB"}; - String WST_AUS[] = new String[] {"Western Standard Time (Australien)", "WST", - "V\u00E4stlig sommartid (Australien)", "WST", - "V\u00E4stlig tid (Australien)", "WT"}; + String WST_AUS[] = new String[] {"Western Standard Time (Australien)", "AWST", + "V\u00E4stlig sommartid (Australien)", "AWDT", + "V\u00E4stlig tid (Australien)", "AWT"}; String SAMOA[] = new String[] {"Samoa, normaltid", "SST", "Samoa, sommartid", "SDT", "Samoansk tid", "ST"}; - String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WST", + String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WSST", "V\u00e4stsamoansk sommartid", "WSDT", "V\u00E4stsamoansk tid", "WST"}; String ChST[] = new String[] {"Chamorro, normaltid", "ChST", "Chamorro, sommartid", "ChDT", "Chamorros tid", "ChT"}; - String VICTORIA[] = new String[] {"\u00D6stlig standardtid (Victoria)", "EST", - "\u00D6stlig sommartid (Victoria)", "EST", - "\u00D6stlig tid (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"\u00D6stlig standardtid (Victoria)", "AEST", + "\u00D6stlig sommartid (Victoria)", "AEDT", + "\u00D6stlig tid (Victoria)", "AET"}; String UTC[] = new String[] {"Koordinerad universell tid", "UTC", "Koordinerad universell tid", "UTC", "UTC (koordinerad v\u00E4rldstid)", "UTC"}; String UZT[] = new String[] {"Uzbekistan, normaltid", "UZT", "Uzbekistan, sommartid", "UZST", "Uzbekisk tid", "UZT"}; + String XJT[] = new String[] {"Kina, normaltid", "XJT", + "Kina, sommartid", "XJDT", + "Kinesisk tid", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "V\u00e4stra Gr\u00f6nland, sommartid", "WGST", "V\u00E4stgr\u00F6nl\u00E4ndsk tid", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Metlakatla, normaltid", "MeST", - "Metlakatla, sommartid", "MeDT", - "Metlakatla-tid", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Saint-Pierre-et-Miquelon, normaltid", "PMST", "Saint-Pierre-et-Miquelon, sommartid", "PMDT", @@ -612,6 +614,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Choibalsan-tid", "CHOT"}}, {"Asia/Chongqing", CTT}, {"Asia/Chungking", CTT}, + {"Asia/Chita", IRKT}, {"Asia/Colombo", IST}, {"Asia/Dacca", BDT}, {"Asia/Dhaka", BDT}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Hovd, normaltid", "HOVT", "Hovd, sommartid", "HOVST", "Hovd-tid", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Irkutsk, normaltid", "IRKT", - "Irkutsk, sommartid", "IRKST", - "Irkutsk-tid", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"\u00d6stindonesisk tid", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Petropavlovsk-Kamtjatka, sommartid", "PETST", "Petropavlovsk-Kamtjatskij-tid", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Khandyga, normaltid", "YAKT", "Khandyga, sommartid", "YAKST", "Khandyga, normaltid", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Krasnojarsk, normaltid", "KRAT", - "Krasnojarsk, sommartid", "KRAST", - "Krasnojarsk-tid", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Filippinsk tid", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral, normaltid", "ORAT", "Oral, sommartid", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Ust-Nera, normaltid", "VLAT", "Ust-Nera, sommartid", "VLAST", "Ust-Nera, normaltid", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central v\u00E4stlig normaltid (Australien)", "CWST", - "Central v\u00E4stlig sommartid (Australien)", "CWST", - "Central v\u00E4stlig tid (Australien)", "CWT"}}, + {"Australia/Eucla", new String[] {"Central v\u00E4stlig normaltid (Australien)", "ACWST", + "Central v\u00E4stlig sommartid (Australien)", "ACWDT", + "Central v\u00E4stlig tid (Australien)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Volgograd-tid", "VOLT", - "Volgograd, sommartid", "VOLST", - "Volgograd, normaltid", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java index e4fca385baa95346f77f54f553d43a11d1bccab9..c8f109aec645d22e2ca191eaff4f91f17957bf22 100644 --- a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java +++ b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String ACT[] = new String[] {"Acre \u65f6\u95f4", "ACT", "Acre \u590f\u4ee4\u65f6", "ACST", "Acre \u65f6\u95f4", "ACT"}; - String ADELAIDE[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "CST", - "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A)", "CST", - "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "CT"}; + String ADELAIDE[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "ACST", + "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A)", "ACDT", + "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A)", "ACT"}; String AGT[] = new String[] {"\u963f\u6839\u5ef7\u65f6\u95f4", "ART", "\u963f\u6839\u5ef7\u590f\u4ee4\u65f6", "ARST", "\u963F\u6839\u5EF7\u65F6\u95F4", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String BDT[] = new String[] {"\u5b5f\u52a0\u62c9\u65f6\u95f4", "BDT", "\u5b5f\u52a0\u62c9\u590f\u4ee4\u65f6", "BDST", "\u5B5F\u52A0\u62C9\u65F6\u95F4", "BDT"}; - String BRISBANE[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u6606\u58EB\u5170)", "EST", - "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u6606\u58EB\u5170)", "EST", - "\u4E1C\u90E8\u65F6\u95F4 (\u6606\u58EB\u5170)", "ET"}; - String BROKEN_HILL[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "CST", - "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "CST", - "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "CT"}; + String BRISBANE[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u6606\u58EB\u5170)", "AEST", + "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u6606\u58EB\u5170)", "AEDT", + "\u4E1C\u90E8\u65F6\u95F4 (\u6606\u58EB\u5170)", "AET"}; + String BROKEN_HILL[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "ACST", + "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "ACDT", + "\u4E2D\u90E8\u65F6\u95F4 (\u5357\u6FB3\u5927\u5229\u4E9A/\u65B0\u5357\u5A01\u5C14\u65AF)", "ACT"}; String BRT[] = new String[] {"\u5df4\u897f\u5229\u4e9a\u65f6\u95f4", "BRT", "\u5df4\u897f\u5229\u4e9a\u590f\u4ee4\u65f6", "BRST", "\u5DF4\u897F\u5229\u4E9A\u65F6\u95F4", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String CUBA[] = new String[] {"\u53e4\u5df4\u6807\u51c6\u65f6\u95f4", "CST", "\u53e4\u5df4\u590f\u4ee4\u65f6", "CDT", "\u53E4\u5DF4\u65F6\u95F4", "CT"}; - String DARWIN[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5317\u9886\u5730)", "CST", - "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5317\u9886\u5730)", "CST", - "\u4E2D\u90E8\u65F6\u95F4 (\u5317\u90E8\u5730\u533A)", "CT"}; + String DARWIN[] = new String[] {"\u4E2D\u592E\u6807\u51C6\u65F6\u95F4 (\u5317\u9886\u5730)", "ACST", + "\u4E2D\u592E\u590F\u4EE4\u65F6 (\u5317\u9886\u5730)", "ACDT", + "\u4E2D\u90E8\u65F6\u95F4 (\u5317\u90E8\u5730\u533A)", "ACT"}; String DUBLIN[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u65f6\u95f4", "GMT", "\u7231\u5c14\u5170\u590f\u4ee4\u65f6", "IST", "\u7231\u5C14\u5170\u65F6\u95F4", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String EST[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "EST", "\u4e1c\u90e8\u590f\u4ee4\u65f6", "EDT", "\u4E1C\u90E8\u65F6\u95F4", "ET"}; - String EST_NSW[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "EST", - "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u65B0\u5357\u5A01\u5C14\u65AF)", "EST", - "\u4E1C\u90E8\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "ET"}; + String EST_NSW[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "AEST", + "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u65B0\u5357\u5A01\u5C14\u65AF)", "AEDT", + "\u4E1C\u90E8\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)", "AET"}; String FET[] = new String[] {"\u8FDC\u4E1C\u6B27\u65F6\u95F4", "FET", "\u8FDC\u4E1C\u6B27\u590F\u4EE4\u65F6", "FEST", "\u8FDC\u4E1C\u6B27\u65F6\u95F4", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String ICT[] = new String[] {"\u5370\u5ea6\u652f\u90a3\u65f6\u95f4", "ICT", "\u5370\u5ea6\u652f\u90a3\u590f\u4ee4\u65f6", "ICST", "\u5370\u5EA6\u652F\u90A3\u65F6\u95F4", "ICT"}; + String IRKT[] = new String[] {"\u4f0a\u5c14\u5e93\u6b21\u514b\u65f6\u95f4", "IRKT", + "\u4f0a\u5c14\u5e93\u6b21\u514b\u590f\u4ee4\u65f6", "IRKST", + "\u4F0A\u5C14\u5E93\u6B21\u514B\u65F6\u95F4", "IRKT"}; String IRT[] = new String[] {"\u4f0a\u6717\u6807\u51c6\u65f6\u95f4", "IRST", "\u4f0a\u6717\u590f\u4ee4\u65f6", "IRDT", "\u4F0A\u6717\u65F6\u95F4", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String JST[] = new String[] {"\u65e5\u672c\u6807\u51c6\u65f6\u95f4", "JST", "\u65e5\u672c\u590f\u4ee4\u65f6", "JDT", "\u65E5\u672C\u65F6\u95F4", "JT"}; + String KRAT[] = new String[] {"\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u65f6\u95f4", "KRAT", + "\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u590f\u4ee4\u65f6", "KRAST", + "\u514B\u62C9\u65AF\u8BFA\u4E9A\u5C14\u65AF\u514B\u65F6\u95F4", "KRAT"}; String KST[] = new String[] {"\u97e9\u56fd\u6807\u51c6\u65f6\u95f4", "KST", "\u97e9\u56fd\u590f\u4ee4\u65f6", "KDT", "\u97E9\u56FD\u65F6\u95F4", "KT"}; String LORD_HOWE[] = new String[] {"\u8c6a\u516c\u6807\u51c6\u65f6\u95f4", "LHST", - "\u8c6a\u516c\u590f\u4ee4\u65f6", "LHST", + "\u8c6a\u516c\u590f\u4ee4\u65f6", "LHDT", "\u8C6A\u516C\u65F6\u95F4", "LHT"}; String MHT[] = new String[] {"\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u65f6\u95f4", "MHT", "\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u590f\u4ee4\u65f6", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String SGT[] = new String[] {"\u65b0\u52a0\u5761\u65f6\u95f4", "SGT", "\u65b0\u52a0\u5761\u590f\u4ee4\u65f6", "SGST", "\u65B0\u52A0\u5761\u65F6\u95F4", "SGT"}; - String SLST[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u65f6\u95f4", "GMT", - "\u585e\u62c9\u5229\u6602\u590f\u4ee4\u65f6", "SLST", - "\u585E\u62C9\u91CC\u6602\u65F6\u95F4", "SLT"}; - String TASMANIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "EST", - "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "EST", - "\u4E1C\u90E8\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "ET"}; + String TASMANIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "AEST", + "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "AEDT", + "\u4E1C\u90E8\u65F6\u95F4 (\u5854\u65AF\u9A6C\u5C3C\u4E9A)", "AET"}; String TMT[] = new String[] {"\u571f\u5e93\u66fc\u65f6\u95f4", "TMT", "\u571f\u5e93\u66fc\u590f\u4ee4\u65f6", "TMST", "\u571F\u5E93\u66FC\u65F6\u95F4", "TMT"}; String ULAT[]= new String[] {"\u5e93\u4f26\u65f6\u95f4", "ULAT", "\u5e93\u4f26\u590f\u4ee4\u65f6", "ULAST", "\u5E93\u4F26\u65F6\u95F4", "ULAT"}; - String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u65f6\u95f4", "WART", - "\u897f\u963f\u6839\u5ef7\u590f\u4ee4\u65f6", "WARST"}; String WAT[] = new String[] {"\u897f\u975e\u65f6\u95f4", "WAT", "\u897f\u975e\u590f\u4ee4\u65f6", "WAST", "\u897F\u975E\u65F6\u95F4", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String WIT[] = new String[] {"\u897f\u5370\u5ea6\u5c3c\u897f\u4e9a\u65f6\u95f4", "WIB", "\u897f\u5370\u5ea6\u5c3c\u897f\u4e9a\u590f\u4ee4\u65f6", "WIST", "\u897F\u5370\u5EA6\u5C3C\u897F\u4E9A\u65F6\u95F4", "WIB"}; - String WST_AUS[] = new String[] {"\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "WST", - "\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "WST", - "\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "WT"}; + String WST_AUS[] = new String[] {"\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "AWST", + "\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "AWDT", + "\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "AWT"}; String SAMOA[] = new String[] {"\u8428\u6469\u4e9a\u7fa4\u5c9b\u6807\u51c6\u65f6\u95f4", "SST", "\u8428\u6469\u4e9a\u7fa4\u5c9b\u590f\u4ee4\u65f6", "SDT", "\u8428\u6469\u4E9A\u65F6\u95F4", "ST"}; - String WST_SAMOA[] = new String[] {"\u897f\u8428\u6469\u4e9a\u65f6\u95f4", "WST", + String WST_SAMOA[] = new String[] {"\u897f\u8428\u6469\u4e9a\u65f6\u95f4", "WSST", "\u897f\u8428\u6469\u4e9a\u590f\u4ee4\u65f6", "WSDT", "\u897F\u8428\u6469\u4E9A\u65F6\u95F4", "WST"}; String ChST[] = new String[] {"Chamorro \u6807\u51c6\u65f6\u95f4", "ChST", "Chamorro \u590f\u4ee4\u65f6", "ChDT", "\u67E5\u6469\u6D1B\u65F6\u95F4", "ChT"}; - String VICTORIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "EST", - "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u7EF4\u591A\u5229\u4E9A)", "EST", - "\u4E1C\u90E8\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "ET"}; + String VICTORIA[] = new String[] {"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "AEST", + "\u4E1C\u90E8\u590F\u4EE4\u65F6 (\u7EF4\u591A\u5229\u4E9A)", "AEDT", + "\u4E1C\u90E8\u65F6\u95F4 (\u7EF4\u591A\u5229\u4E9A)", "AET"}; String UTC[] = new String[] {"\u534f\u8c03\u4e16\u754c\u65f6\u95f4", "UTC", "\u534f\u8c03\u4e16\u754c\u65f6\u95f4", "UTC", "\u534F\u8C03\u4E16\u754C\u65F6\u95F4", "UTC"}; String UZT[] = new String[] {"\u4e4c\u5179\u522b\u514b\u65af\u5766\u65f6\u95f4", "UZT", "\u4e4c\u5179\u522b\u514b\u65af\u5766\u590f\u4ee4\u65f6", "UZST", "\u4E4C\u5179\u522B\u514B\u65AF\u5766\u65F6\u95F4", "UZT"}; + String XJT[] = new String[] {"\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", "XJT", + "\u4e2d\u56fd\u590f\u4ee4\u65f6", "XJDT", + "\u4E2D\u56FD\u65F6\u95F4", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u897f\u683c\u6797\u5170\u5c9b\u590f\u4ee4\u65f6", "WGST", "\u897F\u683C\u6797\u5170\u5C9B\u65F6\u95F4", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"\u6885\u7279\u62C9\u5361\u7279\u62C9\u6807\u51C6\u65F6\u95F4", "MeST", - "\u6885\u7279\u62C9\u5361\u7279\u62C9\u590F\u4EE4\u65F6", "MeDT", - "\u6885\u7279\u62C9\u5361\u7279\u62C9\u65F6\u95F4", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"\u76ae\u57c3\u5c14\u5c9b\u53ca\u5bc6\u514b\u9686\u5c9b\u6807\u51c6\u65f6\u95f4", "PMST", "\u76ae\u57c3\u5c14\u5c9b\u53ca\u5bc6\u514b\u9686\u5c9b\u590f\u4ee4\u65f6", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u6587\u83b1\u590f\u4ee4\u65f6", "BNST", "\u6587\u83B1\u65F6\u95F4", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Choibalsan \u65f6\u95f4", "CHOT", "Choibalsan \u590f\u4ee4\u65f6", "CHOST", "Choibalsan \u65F6\u95F4", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"\u79d1\u5e03\u591a\u65f6\u95f4", "HOVT", "\u79d1\u5e03\u591a\u590f\u4ee4\u65f6", "HOVST", "\u79D1\u5E03\u591A\u65F6\u95F4", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"\u4f0a\u5c14\u5e93\u6b21\u514b\u65f6\u95f4", "IRKT", - "\u4f0a\u5c14\u5e93\u6b21\u514b\u590f\u4ee4\u65f6", "IRKST", - "\u4F0A\u5C14\u5E93\u6B21\u514B\u65F6\u95F4", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"\u4e1c\u5370\u5ea6\u5c3c\u897f\u4e9a\u65f6\u95f4", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u5f7c\u5f97\u7f57\u5df4\u752b\u6d1b\u592b\u65af\u514b\u590f\u4ee4\u65f6", "PETST", "\u5F7C\u5F97\u7F57\u5DF4\u752B\u6D1B\u592B\u65AF\u514B\u65F6\u95F4", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"\u6C49\u5FB7\u52A0\u65F6\u95F4", "YAKT", "\u6C49\u5FB7\u52A0\u590F\u4EE4\u65F6", "YAKST", "\u6C49\u5FB7\u52A0\u65F6\u95F4", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u65f6\u95f4", "KRAT", - "\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u590f\u4ee4\u65f6", "KRAST", - "\u514B\u62C9\u65AF\u8BFA\u4E9A\u5C14\u65AF\u514B\u65F6\u95F4", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u83F2\u5F8B\u5BBE\u65F6\u95F4", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral \u65f6\u95f4", "ORAT", "Oral \u590f\u4ee4\u65f6", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -708,7 +710,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"\u4E4C\u65AF\u5B63\u6D85\u62C9\u65F6\u95F4", "VLAT", "\u4E4C\u65AF\u5B63\u6D85\u62C9\u590F\u4EE4\u65F6", "VLAST", "\u4E4C\u65AF\u5B63\u6D85\u62C9\u65F6\u95F4", "VLAT"}}, @@ -750,9 +752,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "CWST", - "\u4E2D\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "CWST", - "\u4E2D\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "CWT"}}, + {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6807\u51C6\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "ACWST", + "\u4E2D\u897F\u90E8\u590F\u4EE4\u65F6 (\u6FB3\u5927\u5229\u4E9A)", "ACWDT", + "\u4E2D\u897F\u90E8\u65F6\u95F4 (\u6FB3\u5927\u5229\u4E9A)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -818,7 +820,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -853,9 +855,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"\u4f0f\u5c14\u52a0\u683c\u52d2\u65f6\u95f4", "VOLT", - "\u4f0f\u5c14\u52a0\u683c\u52d2\u590f\u4ee4\u65f6", "VOLST", - "\u4F0F\u5C14\u52A0\u683C\u52D2\u65F6\u95F4", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java index 20cfa231737b83ece0d1634d837f028a617a6024..696b571ddc3f7ffb97428d3550e5f812472a665d 100644 --- a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java +++ b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java @@ -48,9 +48,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String ACT[] = new String[] {"Acre \u6642\u9593", "ACT", "Acre \u590f\u4ee4\u6642\u9593", "ACST", "Acre \u6642\u9593", "ACT"}; - String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "CST", - "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340)", "CST", - "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "CT"}; + String ADELAIDE[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "ACST", + "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340)", "ACDT", + "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8)", "ACT"}; String AGT[] = new String[] {"\u963f\u6839\u5ef7\u6642\u9593", "ART", "\u963f\u6839\u5ef7\u590f\u4ee4\u6642\u9593", "ARST", "\u963F\u6839\u5EF7\u6642\u9593", "ART"}; @@ -72,12 +72,12 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String BDT[] = new String[] {"\u5b5f\u52a0\u62c9\u6642\u9593", "BDT", "\u5b5f\u52a0\u62c9\u590f\u4ee4\u6642\u9593", "BDST", "\u5B5F\u52A0\u62C9\u6642\u9593", "BDT"}; - String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u6606\u58EB\u862D)", "EST", - "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u6606\u58EB\u862D)", "EST", - "\u6771\u90E8\u6642\u9593 (\u6606\u58EB\u862D)", "ET"}; - String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "CST", - "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "CST", - "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8/\u65B0\u5357\u5A01\u723E\u65AF)", "CT"}; + String BRISBANE[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u6606\u58EB\u862D)", "AEST", + "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u6606\u58EB\u862D)", "AEDT", + "\u6771\u90E8\u6642\u9593 (\u6606\u58EB\u862D)", "AET"}; + String BROKEN_HILL[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "ACST", + "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u5340/\u65B0\u5357\u5A01\u723E\u65AF)", "ACDT", + "\u4E2D\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E\u5357\u90E8/\u65B0\u5357\u5A01\u723E\u65AF)", "ACT"}; String BRT[] = new String[] {"\u5df4\u897f\u5229\u4e9e\u6642\u9593", "BRT", "\u5df4\u897f\u5229\u4e9e\u590f\u4ee4\u6642\u9593", "BRST", "\u5DF4\u897F\u5229\u4E9E\u6642\u9593", "BRT"}; @@ -111,9 +111,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String CUBA[] = new String[] {"\u53e4\u5df4\u6a19\u6e96\u6642\u9593", "CST", "\u53e4\u5df4\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT", "\u53E4\u5DF4\u6642\u9593", "CT"}; - String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "CST", - "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "CST", - "\u6FB3\u5927\u5229\u4E9E\u4E2D\u90E8\u6642\u9593 (\u5317\u65B9\u5340\u57DF)", "CT"}; + String DARWIN[] = new String[] {"\u4E2D\u90E8\u6A19\u6E96\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "ACST", + "\u4E2D\u90E8\u590F\u4EE4\u6642\u9593 (\u5317\u90E8\u5404\u5730\u5340)", "ACDT", + "\u6FB3\u5927\u5229\u4E9E\u4E2D\u90E8\u6642\u9593 (\u5317\u65B9\u5340\u57DF)", "ACT"}; String DUBLIN[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u5e73\u5747\u6642\u9593", "GMT", "\u611b\u723e\u862d\u590f\u4ee4\u6642\u9593", "IST", "\u611B\u723E\u862D\u6587\u6642\u9593", "IT"}; @@ -132,9 +132,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String EST[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593", "EST", "\u6771\u65b9\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "EDT", "\u7F8E\u570B\u6771\u90E8\u6642\u9593", "ET"}; - String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "EST", - "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "EST", - "\u6771\u90E8\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "ET"}; + String EST_NSW[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "AEST", + "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "AEDT", + "\u6771\u90E8\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)", "AET"}; String FET[] = new String[] {"\u6771\u6B50\u5167\u9678\u6642\u9593", "FET", "\u6771\u6B50\u5167\u9678\u590F\u4EE4\u6642\u9593", "FEST", "\u6771\u6B50\u5167\u9678\u6642\u9593", "FET"}; @@ -165,6 +165,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String ICT[] = new String[] {"\u5370\u5ea6\u652f\u90a3\u6642\u9593", "ICT", "\u5370\u5ea6\u652f\u90a3\u590f\u4ee4\u6642\u9593", "ICST", "\u5370\u5EA6\u652F\u90A3\u6642\u9593", "ICT"}; + String IRKT[] = new String[] {"Irkutsk \u6642\u9593", "IRKT", + "Irkutsk \u590f\u4ee4\u6642\u9593", "IRKST", + "\u4F0A\u723E\u5EAB\u6B21\u514B\u6642\u9593", "IRKT"}; String IRT[] = new String[] {"\u4f0a\u6717\u6a19\u6e96\u6642\u9593", "IRST", "\u4f0a\u6717\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "IRDT", "\u4F0A\u6717\u6642\u9593", "IRT"}; @@ -177,11 +180,14 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String JST[] = new String[] {"\u65e5\u672c\u6a19\u6e96\u6642\u9593", "JST", "\u65e5\u672c\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "JDT", "\u65E5\u672C\u6642\u9593", "JT"}; + String KRAT[] = new String[] {"\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u6642\u9593", "KRAT", + "\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u590f\u4ee4\u6642\u9593", "KRAST", + "\u514B\u62C9\u65AF\u8AFE\u4E9E\u723E\u65AF\u514B\u6642\u9593", "KRAT"}; String KST[] = new String[] {"\u97d3\u570b\u6a19\u6e96\u6642\u9593", "KST", "\u97d3\u570b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "KDT", "\u97D3\u570B\u6642\u9593", "KT"}; String LORD_HOWE[] = new String[] {"\u8c6a\u52f3\u7235\u5cf6\u6a19\u6e96\u6642\u9593", "LHST", - "\u8c6a\u52f3\u7235\u5cf6\u590f\u4ee4\u6642\u9593", "LHST", + "\u8c6a\u52f3\u7235\u5cf6\u590f\u4ee4\u6642\u9593", "LHDT", "\u8C6A\u52F3\u7235\u5CF6\u6642\u9593", "LHT"}; String MHT[] = new String[] {"\u99ac\u7d39\u723e\u7fa4\u5cf6\u6642\u9593", "MHT", "\u99ac\u7d39\u723e\u7fa4\u5cf6\u590f\u4ee4\u6642\u9593", "MHST", @@ -231,20 +237,15 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String SGT[] = new String[] {"\u65b0\u52a0\u5761\u6642\u9593", "SGT", "\u65b0\u52a0\u5761\u590f\u4ee4\u6642\u9593", "SGST", "\u65B0\u52A0\u5761\u6642\u9593", "SGT"}; - String SLST[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u5e73\u5747\u6642\u9593", "GMT", - "\u7345\u5b50\u5c71\u590f\u4ee4\u6642\u9593", "SLST", - "\u7345\u5B50\u5C71\u6642\u9593", "SLT"}; - String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "EST", - "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "EST", - "\u6FB3\u5927\u5229\u4E9E\u6771\u90E8\u6642\u9593 (\u5854\u65AF\u99AC\u5C3C\u4E9E\u5CF6)", "ET"}; + String TASMANIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "AEST", + "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u5854\u65AF\u6885\u5C3C\u4E9E\u5CF6)", "AEDT", + "\u6FB3\u5927\u5229\u4E9E\u6771\u90E8\u6642\u9593 (\u5854\u65AF\u99AC\u5C3C\u4E9E\u5CF6)", "AET"}; String TMT[] = new String[] {"\u571f\u5eab\u66fc\u6642\u9593", "TMT", "\u571f\u5eab\u66fc\u590f\u4ee4\u6642\u9593", "TMST", "\u571F\u5EAB\u66FC\u6642\u9593", "TMT"}; String ULAT[]= new String[] {"\u5eab\u502b\u6642\u9593", "ULAT", "\u5eab\u502b\u590f\u4ee4\u6642\u9593", "ULAST", "\u5EAB\u502B\u6642\u9593", "ULAT"}; - String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u6642\u9593", "WART", - "\u897f\u963f\u6839\u5ef7\u590f\u4ee4\u6642\u9593", "WARST"}; String WAT[] = new String[] {"\u897f\u975e\u6642\u9593", "WAT", "\u897f\u975e\u590f\u4ee4\u6642\u9593", "WAST", "\u897F\u975E\u6642\u9593", "WAT"}; @@ -254,27 +255,30 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String WIT[] = new String[] {"\u897f\u5370\u5c3c\u6642\u9593", "WIB", "\u897f\u5370\u5c3c\u590f\u4ee4\u6642\u9593", "WIST", "\u897F\u5370\u5C3C\u6642\u9593", "WIB"}; - String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "WST", - "\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "WST", - "\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "WT"}; + String WST_AUS[] = new String[] {"\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "AWST", + "\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "AWDT", + "\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "AWT"}; String SAMOA[] = new String[] {"\u85a9\u6469\u4e9e\u6a19\u6e96\u6642\u9593", "SST", "\u85a9\u6469\u4e9e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "SDT", "\u85A9\u6469\u4E9E\u6642\u9593", "ST"}; - String WST_SAMOA[] = new String[] {"\u897f\u85a9\u6469\u4e9e\u6642\u9593", "WST", + String WST_SAMOA[] = new String[] {"\u897f\u85a9\u6469\u4e9e\u6642\u9593", "WSST", "\u897f\u85a9\u6469\u4e9e\u590f\u4ee4\u6642\u9593", "WSDT", "\u897F\u85A9\u6469\u4E9E\u6642\u9593", "WST"}; String ChST[] = new String[] {"\u67e5\u83ab\u6d1b\u6a19\u6e96\u6642\u9593", "ChST", "\u67e5\u83ab\u6d1b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "ChDT", "\u67E5\u83AB\u7F85\u6642\u9593", "ChT"}; - String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "EST", - "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "EST", - "\u6771\u90E8\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E)", "ET"}; + String VICTORIA[] = new String[] {"\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "AEST", + "\u6771\u90E8\u590F\u4EE4\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E\u90A6)", "AEDT", + "\u6771\u90E8\u6642\u9593 (\u7DAD\u591A\u5229\u4E9E)", "AET"}; String UTC[] = new String[] {"\u5354\u8abf\u4e16\u754c\u6642\u9593", "UTC", "\u5354\u8abf\u4e16\u754c\u6642\u9593", "UTC", "\u5354\u8ABF\u4E16\u754C\u6642\u9593", "UTC"}; String UZT[] = new String[] {"\u70cf\u8332\u5225\u514b\u65af\u5766\u6642\u9593", "UZT", "\u70cf\u8332\u5225\u514b\u65af\u5766\u590f\u4ee4\u6642\u9593", "UZST", "\u70CF\u8332\u5225\u514B\u65AF\u5766\u6642\u9593", "UZT"}; + String XJT[] = new String[] {"\u4e2d\u570b\u6a19\u6e96\u6642\u9593", "XJT", + "\u4e2d\u570b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "XJDT", + "\u4E2D\u570B\u6642\u9593", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +340,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +441,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u897f\u683c\u6797\u862d\u5cf6\u590f\u4ee4\u6642\u9593", "WGST", "\u897F\u683C\u9675\u862D\u6642\u9593", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +488,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"\u6885\u7279\u62C9\u5361\u7279\u62C9\u6A19\u6E96\u6642\u9593", "MeST", - "\u6885\u7279\u62C9\u5361\u7279\u62C9\u65E5\u5149\u7BC0\u7D04\u6642\u9593", "MeDT", - "\u6885\u7279\u62C9\u5361\u7279\u62C9\u6642\u9593", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"\u76ae\u57c3\u723e\u5cf6\u53ca\u5bc6\u514b\u9686\u5cf6\u6a19\u6e96\u6642\u9593", "PMST", "\u76ae\u57c3\u723e\u5cf6\u53ca\u5bc6\u514b\u9686\u5cf6\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PMDT", @@ -607,6 +609,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u6c76\u840a\u590f\u4ee4\u6642\u9593", "BNST", "\u6C76\u840A\u6642\u9593", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"\u5de7\u5df4\u5c71 (Choibalsan) \u6642\u9593", "CHOT", "\u5de7\u5df4\u5c71 (Choibalsan) \u590f\u4ee4\u6642\u9593", "CHOST", "\u5DE7\u5DF4\u5C71 (Choibalsan) \u6642\u9593", "CHOT"}}, @@ -631,9 +634,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"\u4faf\u5fb7 (Hovd) \u6642\u9593", "HOVT", "\u4faf\u5fb7 (Hovd) \u590f\u4ee4\u6642\u9593", "HOVST", "\u4FAF\u5FB7 (Hovd) \u6642\u9593", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Irkutsk \u6642\u9593", "IRKT", - "Irkutsk \u590f\u4ee4\u6642\u9593", "IRKST", - "\u4F0A\u723E\u5EAB\u6B21\u514B\u6642\u9593", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"\u6771\u5370\u5ea6\u5c3c\u897f\u4e9e\u6642\u9593", "WIT", @@ -646,16 +647,14 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "Petropavlovsk-Kamchatski \u590f\u4ee4\u6642\u9593", "PETST", "Petropavlovsk-Kamchatski \u6642\u9593", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"\u6F22\u5730\u52A0 (Khandyga) \u6642\u9593", "YAKT", "\u6F22\u5730\u52A0 (Khandyga) \u590F\u4EE4\u6642\u9593", "YAKST", "\u6F22\u5730\u52A0 (Khandyga) \u6642\u9593", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u6642\u9593", "KRAT", - "\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u590f\u4ee4\u6642\u9593", "KRAST", - "\u514B\u62C9\u65AF\u8AFE\u4E9E\u723E\u65AF\u514B\u6642\u9593", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -670,7 +669,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u83F2\u5F8B\u8CD3\u6642\u9593", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"\u6b50\u4f5b\u6642\u9593", "ORAT", "\u6b50\u4f5b\u590f\u4ee4\u6642\u9593", "ORAST", @@ -696,6 +695,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", new String[] {"\u53f0\u7063\u6a19\u6e96\u6642\u9593", "TST", "\u53f0\u7063\u590f\u4ee4\u6642\u9593", "TDT", "\u53f0\u7063\u6642\u9593", "TT"}}, @@ -710,7 +712,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"\u70CF\u65AF\u5167\u62C9 (Ust-Nera) \u6642\u9593", "VLAT", "\u70CF\u65AF\u5167\u62C9 (Ust-Nera) \u590F\u4EE4\u6642\u9593", "VLAST", "\u70CF\u65AF\u5167\u62C9 (Ust-Nera) \u6642\u9593", "VLAT"}}, @@ -752,9 +754,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "CWST", - "\u4E2D\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "CWST", - "\u4E2D\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "CWT"}}, + {"Australia/Eucla", new String[] {"\u4E2D\u897F\u90E8\u6A19\u6E96\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "ACWST", + "\u4E2D\u897F\u90E8\u590F\u4EE4\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "ACWDT", + "\u4E2D\u897F\u90E8\u6642\u9593 (\u6FB3\u5927\u5229\u4E9E)", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -820,7 +822,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -855,9 +857,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"\u4f0f\u723e\u52a0\u683c\u52d2\u6642\u9593", "VOLT", - "\u4f0f\u723e\u52a0\u683c\u52d2\u590f\u4ee4\u6642\u9593", "VOLST", - "\u4F0F\u723E\u52A0\u683C\u52D2\u6642\u9593", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/src/share/javavm/export/jvm.h b/src/share/javavm/export/jvm.h index 2d67c13724d3ff26c81f73142b06285c667dd3c8..1aaec31c3226b1019c43ffccef79c701ba45e757 100644 --- a/src/share/javavm/export/jvm.h +++ b/src/share/javavm/export/jvm.h @@ -439,9 +439,6 @@ JVM_GetClassName(JNIEnv *env, jclass cls); JNIEXPORT jobjectArray JNICALL JVM_GetClassInterfaces(JNIEnv *env, jclass cls); -JNIEXPORT jobject JNICALL -JVM_GetClassLoader(JNIEnv *env, jclass cls); - JNIEXPORT jboolean JNICALL JVM_IsInterface(JNIEnv *env, jclass cls); diff --git a/src/share/native/common/check_code.c b/src/share/native/common/check_code.c index 92d96b19675c1a852e27b672811876d2b2b0d44f..4ffbd67eaf246a6c68ec4a68365c9a7d82f5cb06 100644 --- a/src/share/native/common/check_code.c +++ b/src/share/native/common/check_code.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1357,16 +1357,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) } (*env)->DeleteLocalRef(env, super); - /* The optimizer make cause this to happen on local code */ + /* The optimizer may cause this to happen on local code */ if (not_found) { -#ifdef BROKEN_JAVAC - jobject loader = JVM_GetClassLoader(env, context->class); - int has_loader = (loader != 0); - (*env)->DeleteLocalRef(env, loader); - if (has_loader) -#endif /* BROKEN_JAVAC */ - CCerror(context, - "Illegal use of nonvirtual function call"); + CCerror(context, "Illegal use of nonvirtual function call"); } } } diff --git a/src/share/native/java/lang/Class.c b/src/share/native/java/lang/Class.c index 2f5e6b5c8c29788e472479af0cdbda447c9bbfaa..b80b71786d2690a2b8d12a1304303e317d15b91d 100644 --- a/src/share/native/java/lang/Class.c +++ b/src/share/native/java/lang/Class.c @@ -45,7 +45,6 @@ extern jboolean VerifyFixClassname(char *utf_name); #define CLS "Ljava/lang/Class;" #define CPL "Lsun/reflect/ConstantPool;" #define STR "Ljava/lang/String;" -#define JCL "Ljava/lang/ClassLoader;" #define FLD "Ljava/lang/reflect/Field;" #define MHD "Ljava/lang/reflect/Method;" #define CTR "Ljava/lang/reflect/Constructor;" @@ -56,7 +55,6 @@ static JNINativeMethod methods[] = { {"getName0", "()" STR, (void *)&JVM_GetClassName}, {"getSuperclass", "()" CLS, NULL}, {"getInterfaces0", "()[" CLS, (void *)&JVM_GetClassInterfaces}, - {"getClassLoader0", "()" JCL, (void *)&JVM_GetClassLoader}, {"isInterface", "()Z", (void *)&JVM_IsInterface}, {"getSigners", "()[" OBJ, (void *)&JVM_GetClassSigners}, {"setSigners", "([" OBJ ")V", (void *)&JVM_SetClassSigners}, @@ -81,7 +79,6 @@ static JNINativeMethod methods[] = { #undef OBJ #undef CLS #undef STR -#undef JCL #undef FLD #undef MHD #undef CTR diff --git a/src/share/native/sun/java2d/cmm/lcms/cmscam02.c b/src/share/native/sun/java2d/cmm/lcms/cmscam02.c index 38d164ad3cffff36bf58b506bff4abe5bb7fa89b..86ec167cd9554be43d246a850e93a82fe870a271 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmscam02.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmscam02.c @@ -467,11 +467,12 @@ void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh CAM02COLOR clr; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; - memset(&clr, 0, sizeof(clr)); _cmsAssert(lpMod != NULL); _cmsAssert(pIn != NULL); _cmsAssert(pOut != NULL); + memset(&clr, 0, sizeof(clr)); + clr.XYZ[0] = pIn ->X; clr.XYZ[1] = pIn ->Y; clr.XYZ[2] = pIn ->Z; @@ -492,11 +493,12 @@ void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ CAM02COLOR clr; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; - memset(&clr, 0, sizeof(clr)); _cmsAssert(lpMod != NULL); _cmsAssert(pIn != NULL); _cmsAssert(pOut != NULL); + memset(&clr, 0, sizeof(clr)); + clr.J = pIn -> J; clr.C = pIn -> C; clr.h = pIn -> h; @@ -511,4 +513,3 @@ void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ pOut ->Y = clr.XYZ[1]; pOut ->Z = clr.XYZ[2]; } - diff --git a/src/share/native/sun/java2d/cmm/lcms/cmscgats.c b/src/share/native/sun/java2d/cmm/lcms/cmscgats.c index 11fe36e6c2c7c5bacbc7d23e6e331166e5e241dc..e3079d10983ac54cebd198fb4e325f1e15506c5e 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmscgats.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmscgats.c @@ -77,7 +77,7 @@ // Symbols typedef enum { - SNONE, + SUNDEFINED, SINUM, // Integer SDNUM, // Real SIDENT, // Identifier @@ -550,7 +550,7 @@ SYMBOL BinSrchKey(const char *id) else l = x + 1; } - return SNONE; + return SUNDEFINED; } @@ -735,7 +735,7 @@ void InSymbol(cmsIT8* it8) key = BinSrchKey(it8->id); - if (key == SNONE) it8->sy = SIDENT; + if (key == SUNDEFINED) it8->sy = SIDENT; else it8->sy = key; } @@ -1326,7 +1326,7 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID) it8->ValidKeywords = NULL; it8->ValidSampleID = NULL; - it8 -> sy = SNONE; + it8 -> sy = SUNDEFINED; it8 -> ch = ' '; it8 -> Source = NULL; it8 -> inum = 0; @@ -2179,9 +2179,9 @@ void CookPointers(cmsIT8* it8) if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) { - t -> SampleID = idField; + t -> SampleID = idField; - for (i=0; i < t -> nPatches; i++) { + for (i=0; i < t -> nPatches; i++) { char *Data = GetData(it8, i, idField); if (Data) { @@ -2196,7 +2196,7 @@ void CookPointers(cmsIT8* it8) SetData(it8, i, idField, Buffer); } - } + } } diff --git a/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c b/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c index cea3b8bb424918266782bd7b9ffc53979c10a378..bc2b0daf5c9b6d02a787646f3128b8fde47efc1f 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c @@ -137,15 +137,68 @@ static cmsIntentsList DefaultIntents[] = { // A pointer to the begining of the list -static cmsIntentsList *Intents = DefaultIntents; +_cmsIntentsPluginChunkType _cmsIntentsPluginChunk = { NULL }; + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginIntentsList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsIntentsPluginChunkType newHead = { NULL }; + cmsIntentsList* entry; + cmsIntentsList* Anterior = NULL; + _cmsIntentsPluginChunkType* head = (_cmsIntentsPluginChunkType*) src->chunks[IntentPlugin]; + + // Walk the list copying all nodes + for (entry = head->Intents; + entry != NULL; + entry = entry ->Next) { + + cmsIntentsList *newEntry = ( cmsIntentsList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsIntentsList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.Intents == NULL) + newHead.Intents = newEntry; + } + + ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsIntentsPluginChunkType)); +} + +void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginIntentsList(ctx, src); + } + else { + static _cmsIntentsPluginChunkType IntentsPluginChunkType = { NULL }; + ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx ->MemPool, &IntentsPluginChunkType, sizeof(_cmsIntentsPluginChunkType)); + } +} + // Search the list for a suitable intent. Returns NULL if not found static -cmsIntentsList* SearchIntent(cmsUInt32Number Intent) +cmsIntentsList* SearchIntent(cmsContext ContextID, cmsUInt32Number Intent) { + _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin); cmsIntentsList* pt; - for (pt = Intents; pt != NULL; pt = pt -> Next) + for (pt = ctx -> Intents; pt != NULL; pt = pt -> Next) + if (pt ->Intent == Intent) return pt; + + for (pt = DefaultIntents; pt != NULL; pt = pt -> Next) if (pt ->Intent == Intent) return pt; return NULL; @@ -1031,7 +1084,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, // this case would present some issues if the custom intent tries to do things like // preserve primaries. This solution is not perfect, but works well on most cases. - Intent = SearchIntent(TheIntents[0]); + Intent = SearchIntent(ContextID, TheIntents[0]); if (Intent == NULL) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]); return NULL; @@ -1046,12 +1099,14 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, // Get information about available intents. nMax is the maximum space for the supplied "Codes" // and "Descriptions" the function returns the total number of intents, which may be greater // than nMax, although the matrices are not populated beyond this level. -cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) +cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) { + _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin); cmsIntentsList* pt; cmsUInt32Number nIntents; - for (nIntents=0, pt = Intents; pt != NULL; pt = pt -> Next) + + for (nIntents=0, pt = ctx->Intents; pt != NULL; pt = pt -> Next) { if (nIntents < nMax) { if (Codes != NULL) @@ -1064,37 +1119,52 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32 nIntents++; } + for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next) + { + if (nIntents < nMax) { + if (Codes != NULL) + Codes[nIntents] = pt ->Intent; + + if (Descriptions != NULL) + Descriptions[nIntents] = pt ->Description; + } + + nIntents++; + } return nIntents; } +cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) +{ + return cmsGetSupportedIntentsTHR(NULL, nMax, Codes, Descriptions); +} + // The plug-in registration. User can add new intents or override default routines cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data) { + _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(id, IntentPlugin); cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data; cmsIntentsList* fl; - // Do we have to reset the intents? + // Do we have to reset the custom intents? if (Data == NULL) { - Intents = DefaultIntents; - return TRUE; + ctx->Intents = NULL; + return TRUE; } - fl = SearchIntent(Plugin ->Intent); + fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList)); + if (fl == NULL) return FALSE; - if (fl == NULL) { - fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList)); - if (fl == NULL) return FALSE; - } fl ->Intent = Plugin ->Intent; - strncpy(fl ->Description, Plugin ->Description, 255); - fl ->Description[255] = 0; + strncpy(fl ->Description, Plugin ->Description, sizeof(fl ->Description)-1); + fl ->Description[sizeof(fl ->Description)-1] = 0; fl ->Link = Plugin ->Link; - fl ->Next = Intents; - Intents = fl; + fl ->Next = ctx ->Intents; + ctx ->Intents = fl; return TRUE; } diff --git a/src/share/native/sun/java2d/cmm/lcms/cmserr.c b/src/share/native/sun/java2d/cmm/lcms/cmserr.c index bf1e26063242fa137a402294cff95e3383985609..306d036fc6134f8fd6df5f889f77dda08e54c9ed 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmserr.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmserr.c @@ -60,13 +60,14 @@ // compare two strings ignoring case int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2) { - register const unsigned char *us1 = (const unsigned char *)s1, - *us2 = (const unsigned char *)s2; + register const unsigned char *us1 = (const unsigned char *)s1, + *us2 = (const unsigned char *)s2; - while (toupper(*us1) == toupper(*us2++)) - if (*us1++ == '\0') - return (0); - return (toupper(*us1) - toupper(*--us2)); + while (toupper(*us1) == toupper(*us2++)) + if (*us1++ == '\0') + return 0; + + return (toupper(*us1) - toupper(*--us2)); } // long int because C99 specifies ftell in such way (7.19.9.2) @@ -91,9 +92,8 @@ long int CMSEXPORT cmsfilelength(FILE* f) // // This is the interface to low-level memory management routines. By default a simple // wrapping to malloc/free/realloc is provided, although there is a limit on the max -// amount of memoy that can be reclaimed. This is mostly as a safety feature to -// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms -// would never need. +// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent +// bogus or evil code to allocate huge blocks that otherwise lcms would never need. #define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U)) @@ -103,7 +103,7 @@ long int CMSEXPORT cmsfilelength(FILE* f) // required to be implemented: malloc, realloc and free, although the user may want to // replace the optional mallocZero, calloc and dup as well. -cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); // ********************************************************************************* @@ -143,7 +143,7 @@ void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr) cmsUNUSED_PARAMETER(ContextID); } -// The default realloc function. Again it check for exploits. If Ptr is NULL, +// The default realloc function. Again it checks for exploits. If Ptr is NULL, // realloc behaves the same way as malloc and allocates a new block of size bytes. static void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) @@ -196,28 +196,73 @@ void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number si return mem; } -// Pointers to malloc and _cmsFree functions in current environment -static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn; -static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn; -static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn; -static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn; -static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn; -static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn; + +// Pointers to memory manager functions in Context0 +_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn, + _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn + }; + + +// Reset and duplicate memory manager +void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Duplicate + ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); + } + else { + + // To reset it, we use the default allocators, which cannot be overriden + ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; + } +} + +// Auxiliar to fill memory management functions from plugin (or context 0 defaults) +void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) +{ + if (Plugin == NULL) { + + memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk)); + } + else { + + ptr ->MallocPtr = Plugin -> MallocPtr; + ptr ->FreePtr = Plugin -> FreePtr; + ptr ->ReallocPtr = Plugin -> ReallocPtr; + + // Make sure we revert to defaults + ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn; + ptr ->CallocPtr = _cmsCallocDefaultFn; + ptr ->DupPtr = _cmsDupDefaultFn; + + if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; + if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; + if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; + + } +} + // Plug-in replacement entry -cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data) +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data) { cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data; + _cmsMemPluginChunkType* ptr; - // NULL forces to reset to defaults + // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure. + // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the + // context internal data should be malloce'd by using those functions. if (Data == NULL) { - MallocPtr = _cmsMallocDefaultFn; - MallocZeroPtr= _cmsMallocZeroDefaultFn; - FreePtr = _cmsFreeDefaultFn; - ReallocPtr = _cmsReallocDefaultFn; - CallocPtr = _cmsCallocDefaultFn; - DupPtr = _cmsDupDefaultFn; + struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID; + + // Return to the default allocators + if (ContextID != NULL) { + ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager; + } return TRUE; } @@ -227,51 +272,56 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data) Plugin -> ReallocPtr == NULL) return FALSE; // Set replacement functions - MallocPtr = Plugin -> MallocPtr; - FreePtr = Plugin -> FreePtr; - ReallocPtr = Plugin -> ReallocPtr; - - if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr; - if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr; - if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr; + ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + if (ptr == NULL) + return FALSE; + _cmsInstallAllocFunctions(Plugin, ptr); return TRUE; } // Generic allocate void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) { - return MallocPtr(ContextID, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr ->MallocPtr(ContextID, size); } // Generic allocate & zero void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) { - return MallocZeroPtr(ContextID, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr->MallocZeroPtr(ContextID, size); } // Generic calloc void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) { - return CallocPtr(ContextID, num, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr->CallocPtr(ContextID, num, size); } // Generic reallocate void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) { - return ReallocPtr(ContextID, Ptr, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr->ReallocPtr(ContextID, Ptr, size); } // Generic free memory void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) { - if (Ptr != NULL) FreePtr(ContextID, Ptr); + if (Ptr != NULL) { + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + ptr ->FreePtr(ContextID, Ptr); + } } // Generic block duplication void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) { - return DupPtr(ContextID, Org, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr ->DupPtr(ContextID, Org, size); } // ******************************************************************************************** @@ -380,6 +430,26 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size) return (void*) ptr; } +// Duplicate in pool +void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size) +{ + void *NewPtr; + + // Dup of null pointer is also NULL + if (ptr == NULL) + return NULL; + + NewPtr = _cmsSubAlloc(s, size); + + if (ptr != NULL && NewPtr != NULL) { + memcpy(NewPtr, ptr, size); + } + + return NewPtr; +} + + + // Error logging ****************************************************************** // There is no error handling at all. When a funtion fails, it returns proper value. @@ -401,8 +471,26 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size) // This is our default log error static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); -// The current handler in actual environment -static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction; +// Context0 storage, which is global +_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction }; + +// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value +// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients +void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction }; + void* from; + + if (src != NULL) { + from = src ->chunks[Logger]; + } + else { + from = &LogErrorChunk; + } + + ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType)); +} // The default error logger does nothing. static @@ -416,13 +504,24 @@ void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorC cmsUNUSED_PARAMETER(Text); } -// Change log error +// Change log error, context based +void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn) +{ + _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); + + if (lhg != NULL) { + + if (Fn == NULL) + lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction; + else + lhg -> LogErrorHandler = Fn; + } +} + +// Change log error, legacy void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn) { - if (Fn == NULL) - LogErrorHandler = DefaultLogErrorHandlerFunction; - else - LogErrorHandler = Fn; + cmsSetLogErrorHandlerTHR(NULL, Fn); } // Log an error @@ -431,13 +530,18 @@ void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, c { va_list args; char Buffer[MAX_ERROR_MESSAGE_LEN]; + _cmsLogErrorChunkType* lhg; + va_start(args, ErrorText); vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args); va_end(args); - // Call handler - LogErrorHandler(ContextID, ErrorCode, Buffer); + // Check for the context, if specified go there. If not, go for the global + lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); + if (lhg ->LogErrorHandler) { + lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer); + } } // Utility function to print signatures @@ -455,3 +559,125 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig) String[4] = 0; } +//-------------------------------------------------------------------------------------------------- + + +static +void* defMtxCreate(cmsContext id) +{ + _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); + _cmsInitMutexPrimitive(ptr_mutex); + return (void*) ptr_mutex; +} + +static +void defMtxDestroy(cmsContext id, void* mtx) +{ + _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); + _cmsFree(id, mtx); +} + +static +cmsBool defMtxLock(cmsContext id, void* mtx) +{ + cmsUNUSED_PARAMETER(id); + return _cmsLockPrimitive((_cmsMutex *) mtx) == 0; +} + +static +void defMtxUnlock(cmsContext id, void* mtx) +{ + cmsUNUSED_PARAMETER(id); + _cmsUnlockPrimitive((_cmsMutex *) mtx); +} + + + +// Pointers to memory manager functions in Context0 +_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; + +// Allocate and init mutex container. +void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; + void* from; + + if (src != NULL) { + from = src ->chunks[MutexPlugin]; + } + else { + from = &MutexChunk; + } + + ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType)); +} + +// Register new ways to transform +cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data) +{ + cmsPluginMutex* Plugin = (cmsPluginMutex*) Data; + _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (Data == NULL) { + + // No lock routines + ctx->CreateMutexPtr = NULL; + ctx->DestroyMutexPtr = NULL; + ctx->LockMutexPtr = NULL; + ctx ->UnlockMutexPtr = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL || + Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE; + + + ctx->CreateMutexPtr = Plugin->CreateMutexPtr; + ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr; + ctx ->LockMutexPtr = Plugin ->LockMutexPtr; + ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr; + + // All is ok + return TRUE; +} + +// Generic Mutex fns +void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->CreateMutexPtr == NULL) return NULL; + + return ptr ->CreateMutexPtr(ContextID); +} + +void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->DestroyMutexPtr != NULL) { + + ptr ->DestroyMutexPtr(ContextID, mtx); + } +} + +cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->LockMutexPtr == NULL) return TRUE; + + return ptr ->LockMutexPtr(ContextID, mtx); +} + +void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->UnlockMutexPtr != NULL) { + + ptr ->UnlockMutexPtr(ContextID, mtx); + } +} diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c b/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c index 79affb09fb4f7f61e09cc70e221ea82cf49e4e7d..e68f2585d0e1afbf56270da0ca513251c77aab4a 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c @@ -82,7 +82,6 @@ typedef struct _cmsParametricCurvesCollection_st { } _cmsParametricCurvesCollection; - // This is the default (built-in) evaluator static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R); @@ -95,22 +94,77 @@ static _cmsParametricCurvesCollection DefaultCurves = { NULL // Next in chain }; +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginCurvesList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsCurvesPluginChunkType newHead = { NULL }; + _cmsParametricCurvesCollection* entry; + _cmsParametricCurvesCollection* Anterior = NULL; + _cmsCurvesPluginChunkType* head = (_cmsCurvesPluginChunkType*) src->chunks[CurvesPlugin]; + + _cmsAssert(head != NULL); + + // Walk the list copying all nodes + for (entry = head->ParametricCurves; + entry != NULL; + entry = entry ->Next) { + + _cmsParametricCurvesCollection *newEntry = ( _cmsParametricCurvesCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsParametricCurvesCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.ParametricCurves == NULL) + newHead.ParametricCurves = newEntry; + } + + ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsCurvesPluginChunkType)); +} + +// The allocator have to follow the chain +void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Copy all linked list + DupPluginCurvesList(ctx, src); + } + else { + static _cmsCurvesPluginChunkType CurvesPluginChunk = { NULL }; + ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx ->MemPool, &CurvesPluginChunk, sizeof(_cmsCurvesPluginChunkType)); + } +} + + // The linked list head -static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves; +_cmsCurvesPluginChunkType _cmsCurvesPluginChunk = { NULL }; // As a way to install new parametric curves -cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Data) { + _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin); cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data; _cmsParametricCurvesCollection* fl; if (Data == NULL) { - ParametricCurves = &DefaultCurves; + ctx -> ParametricCurves = NULL; return TRUE; } - fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection)); + fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsParametricCurvesCollection)); if (fl == NULL) return FALSE; // Copy the parameters @@ -126,8 +180,8 @@ cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data) memmove(fl->ParameterCount, Plugin ->ParameterCount, fl->nFunctions * sizeof(cmsUInt32Number)); // Keep linked list - fl ->Next = ParametricCurves; - ParametricCurves = fl; + fl ->Next = ctx->ParametricCurves; + ctx->ParametricCurves = fl; // All is ok return TRUE; @@ -149,12 +203,24 @@ int IsInSet(int Type, _cmsParametricCurvesCollection* c) // Search for the collection which contains a specific type static -_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index) +_cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, int Type, int* index) { _cmsParametricCurvesCollection* c; int Position; + _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin); + + for (c = ctx->ParametricCurves; c != NULL; c = c ->Next) { + + Position = IsInSet(Type, c); - for (c = ParametricCurves; c != NULL; c = c ->Next) { + if (Position != -1) { + if (index != NULL) + *index = Position; + return c; + } + } + // If none found, revert for defaults + for (c = &DefaultCurves; c != NULL; c = c ->Next) { Position = IsInSet(Type, c); @@ -251,7 +317,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr p ->Segments[i].SampledPoints = NULL; - c = GetParametricCurveByType(Segments[i].Type, NULL); + c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL); if (c != NULL) p ->Evals[i] = c ->Evaluator; } @@ -677,12 +743,12 @@ cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt cmsCurveSegment Seg0; int Pos = 0; cmsUInt32Number size; - _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos); + _cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos); _cmsAssert(Params != NULL); if (c == NULL) { - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type); + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type); return NULL; } @@ -872,7 +938,10 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, con _cmsAssert(InCurve != NULL); // Try to reverse it analytically whatever possible - if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) { + + if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && + /* InCurve -> Segments[0].Type <= 5 */ + GetParametricCurveByType(InCurve ->InterpParams->ContextID, InCurve ->Segments[0].Type, NULL) != NULL) { return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID, -(InCurve -> Segments[0].Type), diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c b/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c index 8ace203e86d2f0ed28e429c6848bdc0f7f2cc4a3..0be9173948aa6b294ae8e2eec1d1bc1eb9f0f793 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c @@ -191,7 +191,7 @@ cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID, out = ComputeKToLstar(ContextID, nPoints, 1, Intents + (nProfiles - 1), - hProfiles + (nProfiles - 1), + &hProfiles [nProfiles - 1], BPC + (nProfiles - 1), AdaptationStates + (nProfiles - 1), dwFlags); diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c b/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c index ad971b5bc60392826aa6c1d8de9c969d9947dee7..e57e6ea0e1c04fe42d1e00db00ef16caac402f28 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c @@ -62,31 +62,57 @@ static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags); // This is the default factory -static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory; +_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL }; + +// The interpolation plug-in memory chunk allocator/dup +void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) +{ + void* from; + + _cmsAssert(ctx != NULL); + + if (src != NULL) { + from = src ->chunks[InterpPlugin]; + } + else { + static _cmsInterpPluginChunkType InterpPluginChunk = { NULL }; + + from = &InterpPluginChunk; + } + + _cmsAssert(from != NULL); + ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType)); +} // Main plug-in entry -cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data) +cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data) { cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data; + _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin); if (Data == NULL) { - Interpolators = DefaultInterpolatorsFactory; + ptr ->Interpolators = NULL; return TRUE; } // Set replacement functions - Interpolators = Plugin ->InterpolatorsFactory; + ptr ->Interpolators = Plugin ->InterpolatorsFactory; return TRUE; } // Set the interpolation method -cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p) +cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p) { - // Invoke factory, possibly in the Plug-in - p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags); + _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin); + + p ->Interpolation.Lerp16 = NULL; + + // Invoke factory, possibly in the Plug-in + if (ptr ->Interpolators != NULL) + p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags); // If unsupported by the plug-in, go for the LittleCMS default. // If happens only if an extern plug-in is being used @@ -97,6 +123,7 @@ cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p) if (p ->Interpolation.Lerp16 == NULL) { return FALSE; } + return TRUE; } @@ -141,7 +168,7 @@ cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i]; - if (!_cmsSetInterpolationRoutine(p)) { + if (!_cmsSetInterpolationRoutine(ContextID, p)) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan); _cmsFree(ContextID, p); return NULL; diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsio0.c b/src/share/native/sun/java2d/cmm/lcms/cmsio0.c index 8f421c2f4ec2d562b4b561194a92479de5ab3646..d4dc1b0d8764a6bd737c4ea2f0e38eef1c6889b0 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsio0.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsio0.c @@ -229,15 +229,14 @@ cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, con if (ResData == NULL) return FALSE; // Housekeeping // Check for available space. Clip. - if (iohandler ->UsedSpace + size > ResData->Size) { - size = ResData ->Size - iohandler ->UsedSpace; + if (ResData->Pointer + size > ResData->Size) { + size = ResData ->Size - ResData->Pointer; } if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing memmove(ResData ->Block + ResData ->Pointer, Ptr, size); ResData ->Pointer += size; - iohandler->UsedSpace += size; if (ResData ->Pointer > iohandler->UsedSpace) iohandler->UsedSpace = ResData ->Pointer; @@ -371,7 +370,7 @@ cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) static cmsUInt32Number FileTell(cmsIOHANDLER* iohandler) { - return ftell((FILE*)iohandler ->stream); + return (cmsUInt32Number) ftell((FILE*)iohandler ->stream); } // Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error @@ -414,7 +413,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName); return NULL; } - iohandler -> ReportedSize = cmsfilelength(fm); + iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(fm); break; case 'w': @@ -461,7 +460,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* S iohandler -> ContextID = ContextID; iohandler -> stream = (void*) Stream; iohandler -> UsedSpace = 0; - iohandler -> ReportedSize = cmsfilelength(Stream); + iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(Stream); iohandler -> PhysicalFile[0] = 0; iohandler ->Read = FileRead; @@ -501,6 +500,9 @@ cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID) // Set creation date/time memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created)); + // Create a mutex if the user provided proper plugin. NULL otherwise + Icc ->UsrMutex = _cmsCreateMutex(ContextID); + // Return the handle return (cmsHPROFILE) Icc; } @@ -579,9 +581,39 @@ int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks return n; } +// Deletes a tag entry + +static +void _cmsDeleteTagByPos(_cmsICCPROFILE* Icc, int i) +{ + _cmsAssert(Icc != NULL); + _cmsAssert(i >= 0); + -// Create a new tag entry + if (Icc -> TagPtrs[i] != NULL) { + // Free previous version + if (Icc ->TagSaveAsRaw[i]) { + _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); + } + else { + cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i]; + + if (TypeHandler != NULL) { + + cmsTagTypeHandler LocalTypeHandler = *TypeHandler; + LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter + LocalTypeHandler.ICCVersion = Icc ->Version; + LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); + Icc ->TagPtrs[i] = NULL; + } + } + + } +} + + +// Creates a new tag entry static cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) { @@ -589,15 +621,15 @@ cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) // Search for the tag i = _cmsSearchTag(Icc, sig, FALSE); - - // Now let's do it easy. If the tag has been already written, that's an error if (i >= 0) { - cmsSignalError(Icc ->ContextID, cmsERROR_ALREADY_DEFINED, "Tag '%x' already exists", sig); - return FALSE; + + // Already exists? delete it + _cmsDeleteTagByPos(Icc, i); + *NewPos = i; } else { - // New one + // No, make a new one if (Icc -> TagCount >= MAX_TABLE_TAG) { cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); @@ -979,7 +1011,7 @@ void CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Vers // 4.2 -> 0x4200000 - Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0), 10, 16) << 16; + Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0 + 0.5), 10, 16) << 16; } cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile) @@ -1011,6 +1043,32 @@ Error: return NULL; } +// Create profile from IOhandler +cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write) +{ + _cmsICCPROFILE* NewIcc; + cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); + + if (hEmpty == NULL) return NULL; + + NewIcc = (_cmsICCPROFILE*) hEmpty; + + NewIcc ->IOhandler = io; + if (write) { + + NewIcc -> IsWrite = TRUE; + return hEmpty; + } + + if (!_cmsReadHeader(NewIcc)) goto Error; + return hEmpty; + +Error: + cmsCloseProfile(hEmpty); + return NULL; +} + + // Create profile from disk file cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *lpFileName, const char *sAccess) { @@ -1202,7 +1260,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) else { // Search for support on this tag - TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]); + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, Icc -> TagNames[i]); if (TagDescriptor == NULL) continue; // Unsupported, ignore it if (TagDescriptor ->DecideType != NULL) { @@ -1214,7 +1272,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) Type = TagDescriptor ->SupportedTypes[0]; } - TypeHandler = _cmsGetTagTypeHandler(Type); + TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type); if (TypeHandler == NULL) { cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]); @@ -1282,10 +1340,12 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH { _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE Keep; - cmsIOHANDLER* PrevIO; + cmsIOHANDLER* PrevIO = NULL; cmsUInt32Number UsedSpace; cmsContext ContextID; + _cmsAssert(hProfile != NULL); + memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); ContextID = cmsGetProfileContextID(hProfile); @@ -1294,18 +1354,19 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH // Pass #1 does compute offsets - if (!_cmsWriteHeader(Icc, 0)) return 0; - if (!SaveTags(Icc, &Keep)) return 0; + if (!_cmsWriteHeader(Icc, 0)) goto Error; + if (!SaveTags(Icc, &Keep)) goto Error; UsedSpace = PrevIO ->UsedSpace; // Pass #2 does save to iohandler if (io != NULL) { + Icc ->IOhandler = io; - if (!SetLinks(Icc)) goto CleanUp; - if (!_cmsWriteHeader(Icc, UsedSpace)) goto CleanUp; - if (!SaveTags(Icc, &Keep)) goto CleanUp; + if (!SetLinks(Icc)) goto Error; + if (!_cmsWriteHeader(Icc, UsedSpace)) goto Error; + if (!SaveTags(Icc, &Keep)) goto Error; } memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); @@ -1314,7 +1375,7 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH return UsedSpace; -CleanUp: +Error: cmsCloseIOhandler(PrevIO); memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); return 0; @@ -1362,11 +1423,13 @@ cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUIn cmsIOHANDLER* io; cmsContext ContextID = cmsGetProfileContextID(hProfile); + _cmsAssert(BytesNeeded != NULL); + // Should we just calculate the needed space? if (MemPtr == NULL) { *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL); - return (*BytesNeeded == 0 ? FALSE : TRUE); + return (*BytesNeeded == 0) ? FALSE : TRUE; } // That is a real write operation @@ -1419,6 +1482,8 @@ cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) rc &= cmsCloseIOhandler(Icc->IOhandler); } + _cmsDestroyMutex(Icc->ContextID, Icc->UsrMutex); + _cmsFree(Icc ->ContextID, Icc); // Free placeholder memory return rc; @@ -1459,14 +1524,18 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) cmsUInt32Number ElemCount; int n; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL; + n = _cmsSearchTag(Icc, sig, TRUE); - if (n < 0) return NULL; // Not found, return NULL + if (n < 0) goto Error; // Not found, return NULL // If the element is already in memory, return the pointer if (Icc -> TagPtrs[n]) { - if (Icc ->TagSaveAsRaw[n]) return NULL; // We don't support read raw tags as cooked + if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked + + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc -> TagPtrs[n]; } @@ -1476,23 +1545,32 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) // Seek to its location if (!io -> Seek(io, Offset)) - return NULL; + goto Error; // Search for support on this tag - TagDescriptor = _cmsGetTagDescriptor(sig); - if (TagDescriptor == NULL) return NULL; // Unsupported. + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); + if (TagDescriptor == NULL) { + + char String[5]; + + _cmsTagSignature2String(String, sig); + + // An unknown element was found. + cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown tag type '%s' found.", String); + goto Error; // Unsupported. + } // if supported, get type and check if in list BaseType = _cmsReadTypeBase(io); - if (BaseType == 0) return NULL; + if (BaseType == 0) goto Error; - if (!IsTypeSupported(TagDescriptor, BaseType)) return NULL; + if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; TagSize -= 8; // Alredy read by the type base logic // Get type handler - TypeHandler = _cmsGetTagTypeHandler(BaseType); - if (TypeHandler == NULL) return NULL; + TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType); + if (TypeHandler == NULL) goto Error; LocalTypeHandler = *TypeHandler; @@ -1511,7 +1589,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) _cmsTagSignature2String(String, sig); cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String); - return NULL; + goto Error; } // This is a weird error that may be a symptom of something more serious, the number of @@ -1527,7 +1605,14 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) // Return the data + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc -> TagPtrs[n]; + + + // Return error and unlock tha data +Error: + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return NULL; } @@ -1561,49 +1646,26 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v cmsFloat64Number Version; char TypeString[5], SigString[5]; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE; + // To delete tags. if (data == NULL) { + // Delete the tag i = _cmsSearchTag(Icc, sig, FALSE); - if (i >= 0) + if (i >= 0) { + + // Use zero as a mark of deleted + _cmsDeleteTagByPos(Icc, i); Icc ->TagNames[i] = (cmsTagSignature) 0; - // Unsupported by now, reserved for future ampliations (delete) - return FALSE; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return TRUE; + } + // Didn't find the tag + goto Error; } - i = _cmsSearchTag(Icc, sig, FALSE); - if (i >=0) { - - if (Icc -> TagPtrs[i] != NULL) { - - // Already exists. Free previous version - if (Icc ->TagSaveAsRaw[i]) { - _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); - } - else { - TypeHandler = Icc ->TagTypeHandlers[i]; - - if (TypeHandler != NULL) { - - LocalTypeHandler = *TypeHandler; - LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter - LocalTypeHandler.ICCVersion = Icc ->Version; - LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); - } - } - } - } - else { - // New one - i = Icc -> TagCount; - - if (i >= MAX_TABLE_TAG) { - cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); - return FALSE; - } - - Icc -> TagCount++; - } + if (!_cmsNewTag(Icc, sig, &i)) goto Error; // This is not raw Icc ->TagSaveAsRaw[i] = FALSE; @@ -1612,10 +1674,10 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v Icc ->TagLinked[i] = (cmsTagSignature) 0; // Get information about the TAG. - TagDescriptor = _cmsGetTagDescriptor(sig); + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); if (TagDescriptor == NULL){ cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig); - return FALSE; + goto Error; } @@ -1633,7 +1695,6 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v } else { - Type = TagDescriptor ->SupportedTypes[0]; } @@ -1644,18 +1705,18 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v _cmsTagSignature2String(SigString, sig); cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); - return FALSE; + goto Error; } // Does we have a handler for this type? - TypeHandler = _cmsGetTagTypeHandler(Type); + TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type); if (TypeHandler == NULL) { _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); _cmsTagSignature2String(SigString, sig); cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); - return FALSE; // Should never happen + goto Error; // Should never happen } @@ -1668,7 +1729,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v LocalTypeHandler = *TypeHandler; LocalTypeHandler.ContextID = Icc ->ContextID; LocalTypeHandler.ICCVersion = Icc ->Version; - Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount); + Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount); if (Icc ->TagPtrs[i] == NULL) { @@ -1676,10 +1737,16 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v _cmsTagSignature2String(SigString, sig); cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%s' for tag '%s'", TypeString, SigString); - return FALSE; + goto Error; } + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TRUE; + +Error: + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return FALSE; + } // Read and write raw data. The only way those function would work and keep consistence with normal read and write @@ -1700,9 +1767,11 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig cmsUInt32Number rc; cmsUInt32Number Offset, TagSize; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; + // Search for given tag in ICC profile directory i = _cmsSearchTag(Icc, sig, TRUE); - if (i < 0) return 0; // Not found, return 0 + if (i < 0) goto Error; // Not found, // It is already read? if (Icc -> TagPtrs[i] == NULL) { @@ -1717,12 +1786,14 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig if (BufferSize < TagSize) TagSize = BufferSize; - if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0; - if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0; + if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) goto Error; + if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) goto Error; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TagSize; } + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc ->TagSizes[i]; } @@ -1738,16 +1809,22 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig memmove(data, Icc ->TagPtrs[i], TagSize); + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TagSize; } + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc ->TagSizes[i]; } // Already readed, or previously set by cmsWriteTag(). We need to serialize that // data to raw in order to maintain consistency. + + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); Object = cmsReadTag(hProfile, sig); - if (Object == NULL) return 0; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; + + if (Object == NULL) goto Error; // Now we need to serialize to a memory block: just use a memory iohandler @@ -1756,17 +1833,18 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig } else{ MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w"); } - if (MemIO == NULL) return 0; + if (MemIO == NULL) goto Error; // Obtain type handling for the tag TypeHandler = Icc ->TagTypeHandlers[i]; - TagDescriptor = _cmsGetTagDescriptor(sig); + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); if (TagDescriptor == NULL) { cmsCloseIOhandler(MemIO); - return 0; + goto Error; } - // FIXME: No handling for TypeHandler == NULL here? + if (TypeHandler == NULL) goto Error; + // Serialize LocalTypeHandler = *TypeHandler; LocalTypeHandler.ContextID = Icc ->ContextID; @@ -1774,19 +1852,24 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) { cmsCloseIOhandler(MemIO); - return 0; + goto Error; } if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) { cmsCloseIOhandler(MemIO); - return 0; + goto Error; } // Get Size and close rc = MemIO ->Tell(MemIO); cmsCloseIOhandler(MemIO); // Ignore return code this time + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return rc; + +Error: + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return 0; } // Similar to the anterior. This function allows to write directly to the ICC profile any data, without @@ -1798,7 +1881,12 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; int i; - if (!_cmsNewTag(Icc, sig, &i)) return FALSE; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; + + if (!_cmsNewTag(Icc, sig, &i)) { + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return FALSE; + } // Mark the tag as being written as RAW Icc ->TagSaveAsRaw[i] = TRUE; @@ -1809,6 +1897,7 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size); Icc ->TagSizes[i] = Size; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TRUE; } @@ -1818,7 +1907,12 @@ cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSi _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; int i; - if (!_cmsNewTag(Icc, sig, &i)) return FALSE; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE; + + if (!_cmsNewTag(Icc, sig, &i)) { + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return FALSE; + } // Keep necessary information Icc ->TagSaveAsRaw[i] = FALSE; @@ -1829,6 +1923,7 @@ cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSi Icc ->TagSizes[i] = 0; Icc ->TagOffsets[i] = 0; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TRUE; } diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsio1.c b/src/share/native/sun/java2d/cmm/lcms/cmsio1.c index efdc6bf9d24cb33350c93ab4e94971cd6b4c7f18..61c2ca5338a7bcbac98f307256cc6b28d4c53d5d 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsio1.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsio1.c @@ -334,7 +334,8 @@ Error: // Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc -// is adjusted here in order to create a LUT that takes care of all those details +// is adjusted here in order to create a LUT that takes care of all those details. +// We add intent = -1 as a way to read matrix shaper always, no matter of other LUT cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) { cmsTagTypeSignature OriginalType; @@ -364,49 +365,54 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) return Lut; } - if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + // This is an attempt to reuse this funtion to retrieve the matrix-shaper as pipeline no + // matter other LUT are present and have precedence. Intent = -1 means just this. + if (Intent != -1) { - // Floating point LUT are always V4, but the encoding range is no - // longer 0..1.0, so we need to add an stage depending on the color space - return _cmsReadFloatInputTag(hProfile, tagFloat); - } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence - // Revert to perceptual if no tag is found - if (!cmsIsTag(hProfile, tag16)) { - tag16 = Device2PCS16[0]; - } + // Floating point LUT are always V4, but the encoding range is no + // longer 0..1.0, so we need to add an stage depending on the color space + return _cmsReadFloatInputTag(hProfile, tagFloat); + } - if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? + // Revert to perceptual if no tag is found + if (!cmsIsTag(hProfile, tag16)) { + tag16 = Device2PCS16[0]; + } - // Check profile version and LUT type. Do the necessary adjustments if needed + if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? - // First read the tag - cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); - if (Lut == NULL) return NULL; + // Check profile version and LUT type. Do the necessary adjustments if needed - // After reading it, we have now info about the original type - OriginalType = _cmsGetTagTrueType(hProfile, tag16); + // First read the tag + cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; - // The profile owns the Lut, so we need to copy it - Lut = cmsPipelineDup(Lut); + // After reading it, we have now info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); - // We need to adjust data only for Lab16 on output - if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) - return Lut; + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); - // If the input is Lab, add also a conversion at the begin - if (cmsGetColorSpace(hProfile) == cmsSigLabData && - !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) - goto Error; + // We need to adjust data only for Lab16 on output + if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) + return Lut; - // Add a matrix for conversion V2 to V4 Lab PCS - if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) - goto Error; + // If the input is Lab, add also a conversion at the begin + if (cmsGetColorSpace(hProfile) == cmsSigLabData && + !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) + goto Error; - return Lut; + // Add a matrix for conversion V2 to V4 Lab PCS + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; + + return Lut; Error: - cmsPipelineFree(Lut); - return NULL; + cmsPipelineFree(Lut); + return NULL; + } } // Lut was not found, try to create a matrix-shaper @@ -551,7 +557,7 @@ void ChangeInterpolationToTrilinear(cmsPipeline* Lut) _cmsStageCLutData* CLUT = (_cmsStageCLutData*) Stage ->Data; CLUT ->Params->dwFlags |= CMS_LERP_FLAGS_TRILINEAR; - _cmsSetInterpolationRoutine(CLUT ->Params); + _cmsSetInterpolationRoutine(Lut->ContextID, CLUT ->Params); } } } @@ -609,54 +615,58 @@ cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) cmsTagSignature tagFloat = PCS2DeviceFloat[Intent]; cmsContext ContextID = cmsGetProfileContextID(hProfile); - if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence - // Floating point LUT are always V4 - return _cmsReadFloatOutputTag(hProfile, tagFloat); - } + if (Intent != -1) { - // Revert to perceptual if no tag is found - if (!cmsIsTag(hProfile, tag16)) { - tag16 = PCS2Device16[0]; - } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence - if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? + // Floating point LUT are always V4 + return _cmsReadFloatOutputTag(hProfile, tagFloat); + } - // Check profile version and LUT type. Do the necessary adjustments if needed + // Revert to perceptual if no tag is found + if (!cmsIsTag(hProfile, tag16)) { + tag16 = PCS2Device16[0]; + } - // First read the tag - cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); - if (Lut == NULL) return NULL; + if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? - // After reading it, we have info about the original type - OriginalType = _cmsGetTagTrueType(hProfile, tag16); + // Check profile version and LUT type. Do the necessary adjustments if needed - // The profile owns the Lut, so we need to copy it - Lut = cmsPipelineDup(Lut); - if (Lut == NULL) return NULL; + // First read the tag + cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; - // Now it is time for a controversial stuff. I found that for 3D LUTS using - // Lab used as indexer space, trilinear interpolation should be used - if (cmsGetPCS(hProfile) == cmsSigLabData) - ChangeInterpolationToTrilinear(Lut); + // After reading it, we have info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); - // We need to adjust data only for Lab and Lut16 type - if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) - return Lut; + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); + if (Lut == NULL) return NULL; - // Add a matrix for conversion V4 to V2 Lab PCS - if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) - goto Error; + // Now it is time for a controversial stuff. I found that for 3D LUTS using + // Lab used as indexer space, trilinear interpolation should be used + if (cmsGetPCS(hProfile) == cmsSigLabData) + ChangeInterpolationToTrilinear(Lut); - // If the output is Lab, add also a conversion at the end - if (cmsGetColorSpace(hProfile) == cmsSigLabData) - if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + // We need to adjust data only for Lab and Lut16 type + if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) + return Lut; + + // Add a matrix for conversion V4 to V2 Lab PCS + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) goto Error; - return Lut; + // If the output is Lab, add also a conversion at the end + if (cmsGetColorSpace(hProfile) == cmsSigLabData) + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; + + return Lut; Error: - cmsPipelineFree(Lut); - return NULL; + cmsPipelineFree(Lut); + return NULL; + } } // Lut not found, try to create a matrix-shaper @@ -782,7 +792,7 @@ Error: // Now it is time for a controversial stuff. I found that for 3D LUTS using // Lab used as indexer space, trilinear interpolation should be used - if (cmsGetColorSpace(hProfile) == cmsSigLabData) + if (cmsGetPCS(hProfile) == cmsSigLabData) ChangeInterpolationToTrilinear(Lut); // After reading it, we have info about the original type @@ -793,12 +803,12 @@ Error: // Here it is possible to get Lab on both sides - if (cmsGetPCS(hProfile) == cmsSigLabData) { + if (cmsGetColorSpace(hProfile) == cmsSigLabData) { if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) goto Error2; } - if (cmsGetColorSpace(hProfile) == cmsSigLabData) { + if (cmsGetPCS(hProfile) == cmsSigLabData) { if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) goto Error2; } diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsopt.c b/src/share/native/sun/java2d/cmm/lcms/cmsopt.c index d184ed74b44133b7fa30d361d3efd480acb3c4e5..b9d69512cdd79873bb103c752b2dbada02c54b8f 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsopt.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsopt.c @@ -542,11 +542,13 @@ cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColor cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]); if (InversePostLin == NULL) { - WhiteOut[i] = 0; - continue; + WhiteOut[i] = WhitePointOut[i]; + + } else { + + WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]); + cmsFreeToneCurve(InversePostLin); } - WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]); - cmsFreeToneCurve(InversePostLin); } } else { @@ -1666,44 +1668,102 @@ static _cmsOptimizationCollection DefaultOptimization[] = { }; // The linked list head -static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization; +_cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginOptimizationList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsOptimizationPluginChunkType newHead = { NULL }; + _cmsOptimizationCollection* entry; + _cmsOptimizationCollection* Anterior = NULL; + _cmsOptimizationPluginChunkType* head = (_cmsOptimizationPluginChunkType*) src->chunks[OptimizationPlugin]; + + _cmsAssert(ctx != NULL); + _cmsAssert(head != NULL); + + // Walk the list copying all nodes + for (entry = head->OptimizationCollection; + entry != NULL; + entry = entry ->Next) { + + _cmsOptimizationCollection *newEntry = ( _cmsOptimizationCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsOptimizationCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.OptimizationCollection == NULL) + newHead.OptimizationCollection = newEntry; + } + + ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsOptimizationPluginChunkType)); +} + +void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginOptimizationList(ctx, src); + } + else { + static _cmsOptimizationPluginChunkType OptimizationPluginChunkType = { NULL }; + ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx ->MemPool, &OptimizationPluginChunkType, sizeof(_cmsOptimizationPluginChunkType)); + } +} + // Register new ways to optimize -cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Data) { cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data; + _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin); _cmsOptimizationCollection* fl; if (Data == NULL) { - OptimizationCollection = DefaultOptimization; + ctx->OptimizationCollection = NULL; return TRUE; } // Optimizer callback is required if (Plugin ->OptimizePtr == NULL) return FALSE; - fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection)); + fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsOptimizationCollection)); if (fl == NULL) return FALSE; // Copy the parameters fl ->OptimizePtr = Plugin ->OptimizePtr; // Keep linked list - fl ->Next = OptimizationCollection; - OptimizationCollection = fl; + fl ->Next = ctx->OptimizationCollection; + + // Set the head + ctx ->OptimizationCollection = fl; // All is ok return TRUE; } // The entry point for LUT optimization -cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut, +cmsBool _cmsOptimizePipeline(cmsContext ContextID, + cmsPipeline** PtrLut, int Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { + _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin); _cmsOptimizationCollection* Opts; cmsBool AnySuccess = FALSE; @@ -1733,8 +1793,8 @@ cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut, if (*dwFlags & cmsFLAGS_NOOPTIMIZE) return FALSE; - // Try built-in optimizations and plug-in - for (Opts = OptimizationCollection; + // Try plug-in optimizations + for (Opts = ctx->OptimizationCollection; Opts != NULL; Opts = Opts ->Next) { @@ -1745,6 +1805,17 @@ cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut, } } + // Try built-in optimizations + for (Opts = DefaultOptimization; + Opts != NULL; + Opts = Opts ->Next) { + + if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) { + + return TRUE; + } + } + // Only simple optimizations succeeded return AnySuccess; } diff --git a/src/share/native/sun/java2d/cmm/lcms/cmspack.c b/src/share/native/sun/java2d/cmm/lcms/cmspack.c index b89830c5506aa151eb1ce0bd51885238e610ce69..66597747cc528bf785e0ae725fde94685f63e582 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmspack.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmspack.c @@ -883,6 +883,42 @@ cmsUInt8Number* UnrollXYZDoubleTo16(register _cmsTRANSFORM* info, } } +// This is a conversion of XYZ float to 16 bits +static +cmsUInt8Number* UnrollXYZFloatTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(info -> InputFormat)) { + + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + cmsCIEXYZ XYZ; + + XYZ.X = Pt[0]; + XYZ.Y = Pt[Stride]; + XYZ.Z = Pt[Stride*2]; + cmsFloat2XYZEncoded(wIn, &XYZ); + + return accum + sizeof(cmsFloat32Number); + + } + + else { + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + cmsCIEXYZ XYZ; + + XYZ.X = Pt[0]; + XYZ.Y = Pt[1]; + XYZ.Z = Pt[2]; + cmsFloat2XYZEncoded(wIn, &XYZ); + + accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number); + + return accum; + } +} + // Check if space is marked as ink cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type) { @@ -2333,6 +2369,39 @@ cmsUInt8Number* PackXYZDoubleFrom16(register _cmsTRANSFORM* Info, } } +static +cmsUInt8Number* PackXYZFloatFrom16(register _cmsTRANSFORM* Info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(Info -> OutputFormat)) { + + cmsCIEXYZ XYZ; + cmsFloat32Number* Out = (cmsFloat32Number*) output; + cmsXYZEncoded2Float(&XYZ, wOut); + + Out[0] = (cmsFloat32Number) XYZ.X; + Out[Stride] = (cmsFloat32Number) XYZ.Y; + Out[Stride*2] = (cmsFloat32Number) XYZ.Z; + + return output + sizeof(cmsFloat32Number); + + } + else { + + cmsCIEXYZ XYZ; + cmsFloat32Number* Out = (cmsFloat32Number*) output; + cmsXYZEncoded2Float(&XYZ, wOut); + + Out[0] = (cmsFloat32Number) XYZ.X; + Out[1] = (cmsFloat32Number) XYZ.Y; + Out[2] = (cmsFloat32Number) XYZ.Z; + + return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); + } +} + static cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, register cmsUInt16Number wOut[], @@ -2893,6 +2962,7 @@ static cmsFormatters16 InputFormatters16[] = { { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16}, { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16}, { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16}, + { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatTo16}, { TYPE_GRAY_DBL, 0, UnrollDouble1Chan}, { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16}, @@ -3027,6 +3097,7 @@ static cmsFormatters16 OutputFormatters16[] = { { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16}, { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16}, + { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFrom16}, { FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16}, @@ -3182,40 +3253,98 @@ typedef struct _cms_formatters_factory_list { } cmsFormattersFactoryList; -static cmsFormattersFactoryList* FactoryList = NULL; +_cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupFormatterFactoryList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsFormattersPluginChunkType newHead = { NULL }; + cmsFormattersFactoryList* entry; + cmsFormattersFactoryList* Anterior = NULL; + _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin]; + + _cmsAssert(head != NULL); + + // Walk the list copying all nodes + for (entry = head->FactoryList; + entry != NULL; + entry = entry ->Next) { + + cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.FactoryList == NULL) + newHead.FactoryList = newEntry; + } + + ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType)); +} + +// The interpolation plug-in memory chunk allocator/dup +void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Duplicate the LIST + DupFormatterFactoryList(ctx, src); + } + else { + static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL }; + ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType)); + } +} + // Formatters management -cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data) { + _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data; cmsFormattersFactoryList* fl ; - // Reset + // Reset to built-in defaults if (Data == NULL) { - FactoryList = NULL; + ctx ->FactoryList = NULL; return TRUE; } - fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList)); + fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList)); if (fl == NULL) return FALSE; fl ->Factory = Plugin ->FormattersFactory; - fl ->Next = FactoryList; - FactoryList = fl; + fl ->Next = ctx -> FactoryList; + ctx ->FactoryList = fl; return TRUE; } -cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 +cmsFormatter _cmsGetFormatter(cmsContext ContextID, + cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 cmsFormatterDirection Dir, cmsUInt32Number dwFlags) { + _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); cmsFormattersFactoryList* f; - for (f = FactoryList; f != NULL; f = f ->Next) { + for (f =ctx->FactoryList; f != NULL; f = f ->Next) { cmsFormatter fn = f ->Factory(Type, Dir, dwFlags); if (fn.Fmt16 != NULL) return fn; diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c b/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c index 3d434859e09fb28b4480e2993f7c2c026e643ffd..ef75e13935bbba42aa448ea75a62a3c68af2a37c 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c @@ -544,22 +544,31 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...) // Plugin memory management ------------------------------------------------------------------------------------------------- -static _cmsSubAllocator* PluginPool = NULL; - // Specialized malloc for plug-ins, that is freed upon exit. -void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size) +void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size) { - if (PluginPool == NULL) - PluginPool = _cmsCreateSubAlloc(id, 4*1024); + struct _cmsContext_struct* ctx = _cmsGetContext(ContextID); + + if (ctx ->MemPool == NULL) { + + if (ContextID == NULL) { + + ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024); + } + else { + cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context"); + return NULL; + } + } - return _cmsSubAlloc(PluginPool, size); + return _cmsSubAlloc(ctx->MemPool, size); } // Main plug-in dispatcher cmsBool CMSEXPORT cmsPlugin(void* Plug_in) { - return cmsPluginTHR(NULL, Plug_in); + return cmsPluginTHR(NULL, Plug_in); } cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) @@ -571,12 +580,12 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) Plugin = Plugin -> Next) { if (Plugin -> Magic != cmsPluginMagicNumber) { - cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin"); + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin"); return FALSE; } if (Plugin ->ExpectedVersion > LCMS_VERSION) { - cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d", + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d", Plugin ->ExpectedVersion, LCMS_VERSION); return FALSE; } @@ -584,11 +593,11 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) switch (Plugin -> Type) { case cmsPluginMemHandlerSig: - if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE; + if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE; break; case cmsPluginInterpolationSig: - if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE; + if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE; break; case cmsPluginTagTypeSig: @@ -623,8 +632,12 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE; break; + case cmsPluginMutexSig: + if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE; + break; + default: - cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); return FALSE; } } @@ -637,19 +650,337 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) // Revert all plug-ins to default void CMSEXPORT cmsUnregisterPlugins(void) { - _cmsRegisterMemHandlerPlugin(NULL); - _cmsRegisterInterpPlugin(NULL); - _cmsRegisterTagTypePlugin(NULL, NULL); - _cmsRegisterTagPlugin(NULL, NULL); - _cmsRegisterFormattersPlugin(NULL, NULL); - _cmsRegisterRenderingIntentPlugin(NULL, NULL); - _cmsRegisterParametricCurvesPlugin(NULL, NULL); - _cmsRegisterMultiProcessElementPlugin(NULL, NULL); - _cmsRegisterOptimizationPlugin(NULL, NULL); - _cmsRegisterTransformPlugin(NULL, NULL); + cmsUnregisterPluginsTHR(NULL); +} + + +// The Global storage for system context. This is the one and only global variable +// pointers structure. All global vars are referenced here. +static struct _cmsContext_struct globalContext = { + + NULL, // Not in the linked list + NULL, // No suballocator + { + NULL, // UserPtr, + &_cmsLogErrorChunk, // Logger, + &_cmsAlarmCodesChunk, // AlarmCodes, + &_cmsAdaptationStateChunk, // AdaptationState, + &_cmsMemPluginChunk, // MemPlugin, + &_cmsInterpPluginChunk, // InterpPlugin, + &_cmsCurvesPluginChunk, // CurvesPlugin, + &_cmsFormattersPluginChunk, // FormattersPlugin, + &_cmsTagTypePluginChunk, // TagTypePlugin, + &_cmsTagPluginChunk, // TagPlugin, + &_cmsIntentsPluginChunk, // IntentPlugin, + &_cmsMPETypePluginChunk, // MPEPlugin, + &_cmsOptimizationPluginChunk, // OptimizationPlugin, + &_cmsTransformPluginChunk, // TransformPlugin, + &_cmsMutexPluginChunk // MutexPlugin + }, + + { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0 +}; - if (PluginPool != NULL) - _cmsSubAllocDestroy(PluginPool); - PluginPool = NULL; +// The context pool (linked list head) +static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER; +static struct _cmsContext_struct* _cmsContextPoolHead = NULL; + +// Internal, get associated pointer, with guessing. Never returns NULL. +struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID) +{ + struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID; + struct _cmsContext_struct* ctx; + + + // On 0, use global settings + if (id == NULL) + return &globalContext; + + // Search + for (ctx = _cmsContextPoolHead; + ctx != NULL; + ctx = ctx ->Next) { + + // Found it? + if (id == ctx) + return ctx; // New-style context, + } + + return &globalContext; } + + +// Internal: get the memory area associanted with each context client +// Returns the block assigned to the specific zone. +void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc) +{ + struct _cmsContext_struct* ctx; + void *ptr; + + if (mc < 0 || mc >= MemoryClientMax) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client"); + return NULL; + } + + ctx = _cmsGetContext(ContextID); + ptr = ctx ->chunks[mc]; + + if (ptr != NULL) + return ptr; + + // A null ptr means no special settings for that context, and this + // reverts to Context0 globals + return globalContext.chunks[mc]; +} + + +// This function returns the given context its default pristine state, +// as no plug-ins were declared. There is no way to unregister a single +// plug-in, as a single call to cmsPluginTHR() function may register +// many different plug-ins simultaneously, then there is no way to +// identify which plug-in to unregister. +void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID) +{ + _cmsRegisterMemHandlerPlugin(ContextID, NULL); + _cmsRegisterInterpPlugin(ContextID, NULL); + _cmsRegisterTagTypePlugin(ContextID, NULL); + _cmsRegisterTagPlugin(ContextID, NULL); + _cmsRegisterFormattersPlugin(ContextID, NULL); + _cmsRegisterRenderingIntentPlugin(ContextID, NULL); + _cmsRegisterParametricCurvesPlugin(ContextID, NULL); + _cmsRegisterMultiProcessElementPlugin(ContextID, NULL); + _cmsRegisterOptimizationPlugin(ContextID, NULL); + _cmsRegisterTransformPlugin(ContextID, NULL); + _cmsRegisterMutexPlugin(ContextID, NULL); +} + + +// Returns the memory manager plug-in, if any, from the Plug-in bundle +static +cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle) +{ + cmsPluginBase* Plugin; + + for (Plugin = (cmsPluginBase*) PluginBundle; + Plugin != NULL; + Plugin = Plugin -> Next) { + + if (Plugin -> Magic == cmsPluginMagicNumber && + Plugin -> ExpectedVersion <= LCMS_VERSION && + Plugin -> Type == cmsPluginMemHandlerSig) { + + // Found! + return (cmsPluginMemHandler*) Plugin; + } + } + + // Nope, revert to defaults + return NULL; +} + + +// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined +// data that will be forwarded to plug-ins and logger. +cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData) +{ + struct _cmsContext_struct* ctx; + struct _cmsContext_struct fakeContext; + + _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager); + + fakeContext.chunks[UserPtr] = UserData; + fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager; + + // Create the context structure. + ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct)); + if (ctx == NULL) + return NULL; // Something very wrong happened! + + // Init the structure and the memory manager + memset(ctx, 0, sizeof(struct _cmsContext_struct)); + + // Keep memory manager + memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk)); + + // Maintain the linked list (with proper locking) + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + ctx ->Next = _cmsContextPoolHead; + _cmsContextPoolHead = ctx; + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + + ctx ->chunks[UserPtr] = UserData; + ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; + + // Now we can allocate the pool by using default memory manager + ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers + if (ctx ->MemPool == NULL) { + + cmsDeleteContext(ctx); + return NULL; + } + + _cmsAllocLogErrorChunk(ctx, NULL); + _cmsAllocAlarmCodesChunk(ctx, NULL); + _cmsAllocAdaptationStateChunk(ctx, NULL); + _cmsAllocMemPluginChunk(ctx, NULL); + _cmsAllocInterpPluginChunk(ctx, NULL); + _cmsAllocCurvesPluginChunk(ctx, NULL); + _cmsAllocFormattersPluginChunk(ctx, NULL); + _cmsAllocTagTypePluginChunk(ctx, NULL); + _cmsAllocMPETypePluginChunk(ctx, NULL); + _cmsAllocTagPluginChunk(ctx, NULL); + _cmsAllocIntentsPluginChunk(ctx, NULL); + _cmsAllocOptimizationPluginChunk(ctx, NULL); + _cmsAllocTransformPluginChunk(ctx, NULL); + _cmsAllocMutexPluginChunk(ctx, NULL); + + // Setup the plug-ins + if (!cmsPluginTHR(ctx, Plugin)) { + + cmsDeleteContext(ctx); + return NULL; + } + + return (cmsContext) ctx; +} + +// Duplicates a context with all associated plug-ins. +// Caller may specify an optional pointer to user-defined +// data that will be forwarded to plug-ins and logger. +cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) +{ + int i; + struct _cmsContext_struct* ctx; + const struct _cmsContext_struct* src = _cmsGetContext(ContextID); + + void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr]; + + + ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct)); + if (ctx == NULL) + return NULL; // Something very wrong happened + + // Setup default memory allocators + memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); + + // Maintain the linked list + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + ctx ->Next = _cmsContextPoolHead; + _cmsContextPoolHead = ctx; + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + + ctx ->chunks[UserPtr] = userData; + ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; + + ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); + if (ctx ->MemPool == NULL) { + + cmsDeleteContext(ctx); + return NULL; + } + + // Allocate all required chunks. + _cmsAllocLogErrorChunk(ctx, src); + _cmsAllocAlarmCodesChunk(ctx, src); + _cmsAllocAdaptationStateChunk(ctx, src); + _cmsAllocMemPluginChunk(ctx, src); + _cmsAllocInterpPluginChunk(ctx, src); + _cmsAllocCurvesPluginChunk(ctx, src); + _cmsAllocFormattersPluginChunk(ctx, src); + _cmsAllocTagTypePluginChunk(ctx, src); + _cmsAllocMPETypePluginChunk(ctx, src); + _cmsAllocTagPluginChunk(ctx, src); + _cmsAllocIntentsPluginChunk(ctx, src); + _cmsAllocOptimizationPluginChunk(ctx, src); + _cmsAllocTransformPluginChunk(ctx, src); + _cmsAllocMutexPluginChunk(ctx, src); + + // Make sure no one failed + for (i=Logger; i < MemoryClientMax; i++) { + + if (src ->chunks[i] == NULL) { + cmsDeleteContext((cmsContext) ctx); + return NULL; + } + } + + return (cmsContext) ctx; +} + + + +static +struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) +{ + struct _cmsContext_struct* prev; + + // Search for previous + for (prev = _cmsContextPoolHead; + prev != NULL; + prev = prev ->Next) + { + if (prev ->Next == id) + return prev; + } + + return NULL; // List is empty or only one element! +} + +// Frees any resources associated with the given context, +// and destroys the context placeholder. +// The ContextID can no longer be used in any THR operation. +void CMSEXPORT cmsDeleteContext(cmsContext ContextID) +{ + if (ContextID != NULL) { + + struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID; + struct _cmsContext_struct fakeContext; + struct _cmsContext_struct* prev; + + memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); + + fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr]; + fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager; + + // Get rid of plugins + cmsUnregisterPluginsTHR(ContextID); + + // Since all memory is allocated in the private pool, all what we need to do is destroy the pool + if (ctx -> MemPool != NULL) + _cmsSubAllocDestroy(ctx ->MemPool); + ctx -> MemPool = NULL; + + // Maintain list + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + if (_cmsContextPoolHead == ctx) { + + _cmsContextPoolHead = ctx->Next; + } + else { + + // Search for previous + for (prev = _cmsContextPoolHead; + prev != NULL; + prev = prev ->Next) + { + if (prev -> Next == ctx) { + prev -> Next = ctx ->Next; + break; + } + } + } + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + + // free the memory block itself + _cmsFree(&fakeContext, ctx); + } +} + +// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation +void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID) +{ + return _cmsContextGetClientChunk(ContextID, UserPtr); +} + + diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsps2.c b/src/share/native/sun/java2d/cmm/lcms/cmsps2.c index 2da5a2b6a0db34893bf5d095e8443b31a8ada493..22089d094ab8e99e2b2dbea8a24ffb1b57c8edb5 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsps2.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsps2.c @@ -942,7 +942,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Nu if (DeviceLink == NULL) return 0; dwFlags |= cmsFLAGS_FORCE_CLUT; - _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); + _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); cmsPipelineFree(DeviceLink); @@ -1359,7 +1359,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32N // We need a CLUT dwFlags |= cmsFLAGS_FORCE_CLUT; - _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); + _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); _cmsIOPrintf(m, "<<\n"); _cmsIOPrintf(m, "/ColorRenderingType 1\n"); diff --git a/src/share/native/sun/java2d/cmm/lcms/cmstypes.c b/src/share/native/sun/java2d/cmm/lcms/cmstypes.c index f434cfde6b0202a7da72ee9d6a65f3b01ae8a5ac..08cad5ea61988ae21f6a3001df76b91a6b41c1e2 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmstypes.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmstypes.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -61,7 +61,7 @@ // are no profiles holding them. The programmer can also extend this list by defining his own types // by using the appropiate plug-in. There are three types of plug ins regarding that. First type // allows to define new tags using any existing type. Next plug-in type allows to define new types -// and the third one is very specific: allows to extend the number of elements in the multiprofile +// and the third one is very specific: allows to extend the number of elements in the multiprocessing // elements special type. //-------------------------------------------------------------------------------------------------- @@ -89,54 +89,49 @@ typedef struct _cmsTagTypeLinkedList_st { // Helper macro to define a MPE handler. Callbacks do have a fixed naming convention #define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 } -// Register a new type handler. This routine is shared between normal types and MPE +// Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head static -cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount) +cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos) { cmsPluginTagType* Plugin = (cmsPluginTagType*) Data; - _cmsTagTypeLinkedList *pt, *Anterior = NULL; + _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos); + _cmsTagTypeLinkedList *pt; // Calling the function with NULL as plug-in would unregister the plug in. if (Data == NULL) { - LinkedList[DefaultListCount-1].Next = NULL; + // There is no need to set free the memory, as pool is destroyed as a whole. + ctx ->TagTypes = NULL; return TRUE; } - pt = Anterior = LinkedList; - while (pt != NULL) { - - if (Plugin->Handler.Signature == pt -> Handler.Signature) { - pt ->Handler = Plugin ->Handler; // Replace old behaviour. - // Note that since no memory is allocated, unregister does not - // reset this action. - return TRUE; - } - - Anterior = pt; - pt = pt ->Next; - } - - // Registering happens in plug-in memory pool + // Registering happens in plug-in memory pool. pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList)); if (pt == NULL) return FALSE; pt ->Handler = Plugin ->Handler; - pt ->Next = NULL; + pt ->Next = ctx ->TagTypes; - if (Anterior) - Anterior -> Next = pt; + ctx ->TagTypes = pt; return TRUE; } -// Return handler for a given type or NULL if not found. Shared between normal types and MPE +// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons +// made by plug-ins and then the built-in defaults. static -cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* LinkedList) +cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList) { _cmsTagTypeLinkedList* pt; - for (pt = LinkedList; + for (pt = PluginLinkedList; + pt != NULL; + pt = pt ->Next) { + + if (sig == pt -> Handler.Signature) return &pt ->Handler; + } + + for (pt = DefaultLinkedList; pt != NULL; pt = pt ->Next) { @@ -163,6 +158,7 @@ cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* return TRUE; } +// Auxiliar to read an array of wchar_t static cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array) { @@ -777,6 +773,8 @@ cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, // Create memory Text = (char*) _cmsMalloc(self ->ContextID, size); + if (Text == NULL) return FALSE; + cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size); // Write it, including separator @@ -1783,7 +1781,6 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms if (!_cmsReadUInt8Number(io, NULL)) goto Error; // Do some checking - if (InputChannels > cmsMAXCHANNELS) goto Error; if (OutputChannels > cmsMAXCHANNELS) goto Error; @@ -1824,9 +1821,16 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms if (T == NULL) goto Error; Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize); - if (Temp == NULL) goto Error; + if (Temp == NULL) { + _cmsFree(self ->ContextID, T); + goto Error; + } - if (io ->Read(io, Temp, nTabSize, 1) != 1) goto Error; + if (io ->Read(io, Temp, nTabSize, 1) != 1) { + _cmsFree(self ->ContextID, T); + _cmsFree(self ->ContextID, Temp); + goto Error; + } for (i = 0; i < nTabSize; i++) { @@ -2371,27 +2375,30 @@ cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUI // Precision can be 1 or 2 bytes if (Precision == 1) { - cmsUInt8Number v; + cmsUInt8Number v; for (i=0; i < Data ->nEntries; i++) { - if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; - Data ->Tab.T[i] = FROM_8_TO_16(v); + if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; + Data ->Tab.T[i] = FROM_8_TO_16(v); } } else if (Precision == 2) { - if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) return NULL; - } - else { - cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision); - return NULL; - } - + if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) { + cmsStageFree(CLUT); + return NULL; + } + } + else { + cmsStageFree(CLUT); + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision); + return NULL; + } - return CLUT; + return CLUT; } static @@ -4374,7 +4381,7 @@ static _cmsTagTypeLinkedList SupportedMPEtypes[] = { {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType, MPEclut), NULL }, }; -#define DEFAULT_MPE_TYPE_COUNT (sizeof(SupportedMPEtypes) / sizeof(_cmsTagTypeLinkedList)) +_cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL }; static cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, @@ -4387,6 +4394,8 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, cmsTagTypeHandler* TypeHandler; cmsUInt32Number nItems; cmsPipeline *NewLUT = (cmsPipeline *) Cargo; + _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin); + // Take signature and channels for each element. if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE; @@ -4395,7 +4404,7 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, if (!_cmsReadUInt32Number(io, NULL)) return FALSE; // Read diverse MPE types - TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes); + TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes); if (TypeHandler == NULL) { char String[5]; @@ -4472,6 +4481,7 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v cmsPipeline* Lut = (cmsPipeline*) Ptr; cmsStage* Elem = Lut ->Elements; cmsTagTypeHandler* TypeHandler; + _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin); BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); @@ -4505,7 +4515,7 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v ElementSig = Elem ->Type; - TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes); + TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes); if (TypeHandler == NULL) { char String[5]; @@ -5125,7 +5135,7 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i } else { - rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); + rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); } if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS); @@ -5282,24 +5292,95 @@ static _cmsTagTypeLinkedList SupportedTagTypes[] = { {TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL } }; -#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList)) + +_cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL }; + + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupTagTypeList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src, + int loc) +{ + _cmsTagTypePluginChunkType newHead = { NULL }; + _cmsTagTypeLinkedList* entry; + _cmsTagTypeLinkedList* Anterior = NULL; + _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc]; + + // Walk the list copying all nodes + for (entry = head->TagTypes; + entry != NULL; + entry = entry ->Next) { + + _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.TagTypes == NULL) + newHead.TagTypes = newEntry; + } + + ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType)); +} + + +void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Duplicate the LIST + DupTagTypeList(ctx, src, TagTypePlugin); + } + else { + static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL }; + ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType)); + } +} + +void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Duplicate the LIST + DupTagTypeList(ctx, src, MPEPlugin); + } + else { + static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL }; + ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType)); + } + +} + // Both kind of plug-ins share same structure cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data) { - return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT); + return RegisterTypesPlugin(id, Data, TagTypePlugin); } cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data) { - return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT); + return RegisterTypesPlugin(id, Data,MPEPlugin); } // Wrapper for tag types -cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig) +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig) { - return GetHandler(sig, SupportedTagTypes); + _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin); + + return GetHandler(sig, ctx->TagTypes, SupportedTagTypes); } // ******************************************************************************** @@ -5414,30 +5495,68 @@ static _cmsTagLinkedList SupportedTags[] = { cmsSigDeviceSettingsTag ==> Deprecated, useless */ -#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList)) -cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data) +_cmsTagPluginChunkType _cmsTagPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupTagList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) { - cmsPluginTag* Plugin = (cmsPluginTag*) Data; - _cmsTagLinkedList *pt, *Anterior; + _cmsTagPluginChunkType newHead = { NULL }; + _cmsTagLinkedList* entry; + _cmsTagLinkedList* Anterior = NULL; + _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin]; + // Walk the list copying all nodes + for (entry = head->Tag; + entry != NULL; + entry = entry ->Next) { - if (Data == NULL) { + _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList)); - SupportedTags[DEFAULT_TAG_COUNT-1].Next = NULL; - return TRUE; + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.Tag == NULL) + newHead.Tag = newEntry; + } + + ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType)); +} + +void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + DupTagList(ctx, src); } + else { + static _cmsTagPluginChunkType TagPluginChunk = { NULL }; + ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagPluginChunk, sizeof(_cmsTagPluginChunkType)); + } + +} - pt = Anterior = SupportedTags; - while (pt != NULL) { +cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginTag* Plugin = (cmsPluginTag*) Data; + _cmsTagLinkedList *pt; + _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(id, TagPlugin); - if (Plugin->Signature == pt -> Signature) { - pt ->Descriptor = Plugin ->Descriptor; // Replace old behaviour - return TRUE; - } + if (Data == NULL) { - Anterior = pt; - pt = pt ->Next; + TagPluginChunk->Tag = NULL; + return TRUE; } pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList)); @@ -5445,17 +5564,25 @@ cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data) pt ->Signature = Plugin ->Signature; pt ->Descriptor = Plugin ->Descriptor; - pt ->Next = NULL; + pt ->Next = TagPluginChunk ->Tag; - if (Anterior != NULL) Anterior -> Next = pt; + TagPluginChunk ->Tag = pt; return TRUE; } // Return a descriptor for a given tag or NULL -cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig) +cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig) { _cmsTagLinkedList* pt; + _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(ContextID, TagPlugin); + + for (pt = TagPluginChunk->Tag; + pt != NULL; + pt = pt ->Next) { + + if (sig == pt -> Signature) return &pt ->Descriptor; + } for (pt = SupportedTags; pt != NULL; diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c b/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c index 699abcc93ca5be35a70fcddf4c69440ca1ce4a2e..359875149fc4fd5f7988ab95b12ff4400b809299 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -1019,7 +1019,7 @@ typedef struct { static const cmsAllowedLUT AllowedLUTTypes[] = { - { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, + { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}}, { TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, @@ -1150,7 +1150,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat if (AllowedLUT == NULL) { // Try to optimize - _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); + _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } @@ -1159,7 +1159,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat if (AllowedLUT == NULL) { dwFlags |= cmsFLAGS_FORCE_CLUT; - _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); + _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); // Put identity curves if needed if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) diff --git a/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c b/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c index 71fb76508361765f8288d0b45d0fe7003a51d2bd..1eb9a87800f6c3f0b8a0f7f2910152f9f1bd9c15 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsxform.c b/src/share/native/sun/java2d/cmm/lcms/cmsxform.c index 879056f41ce8d9256c3527aead2044e3f5ad8b8b..3e244c390a853d178b2d4a3c09d86b2f2fded83e 100644 --- a/src/share/native/sun/java2d/cmm/lcms/cmsxform.c +++ b/src/share/native/sun/java2d/cmm/lcms/cmsxform.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -58,44 +58,120 @@ // Transformations stuff // ----------------------------------------------------------------------- -// Alarm codes for 16-bit transformations, because the fixed range of containers there are -// no values left to mark out of gamut. volatile is C99 per 6.2.5 -static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS] = { 0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static volatile cmsFloat64Number GlobalAdaptationState = 1; +#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 + +// The Context0 observer adaptation state. +_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + +// Init and duplicate observer adaptation state +void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AdaptationStateContext]; + } + else { + from = &AdaptationStateChunk; + } + + ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); +} + + +// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all +// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states. +cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d) +{ + cmsFloat64Number prev; + _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); + + // Get previous value for return + prev = ptr ->AdaptationState; + + // Set the value if d is positive or zero + if (d >= 0.0) { + + ptr ->AdaptationState = d; + } + + // Always return previous value + return prev; +} + // The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) { - cmsFloat64Number OldVal = GlobalAdaptationState; + return cmsSetAdaptationStateTHR(NULL, d); +} + +// ----------------------------------------------------------------------- + +// Alarm codes for 16-bit transformations, because the fixed range of containers there are +// no values left to mark out of gamut. + +#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + +// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be +// encoded in 16 bits. +void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) +{ + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); - if (d >= 0) - GlobalAdaptationState = d; + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen - return OldVal; + memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); } -// Alarm codes are always global -void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) +// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. +// Values are meant to be encoded in 16 bits. +void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) { - int i; + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); +} +void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) +{ _cmsAssert(NewAlarm != NULL); - for (i=0; i < cmsMAXCHANNELS; i++) - Alarm[i] = NewAlarm[i]; + cmsSetAlarmCodesTHR(NULL, NewAlarm); } -// You can get the codes cas well void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) { - int i; - _cmsAssert(OldAlarm != NULL); + cmsGetAlarmCodesTHR(NULL, OldAlarm); +} + - for (i=0; i < cmsMAXCHANNELS; i++) - OldAlarm[i] = Alarm[i]; +// Init and duplicate alarm codes +void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AlarmCodesContext]; + } + else { + from = &AlarmCodesChunk; + } + + ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); } +// ----------------------------------------------------------------------- + // Get rid of transform resources void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) { @@ -202,6 +278,30 @@ void FloatXFORM(_cmsTRANSFORM* p, } } + +static +void NullFloatXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number Size, + cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; + + for (i=0; i < n; i++) { + + accum = p -> FromInputFloat(p, fIn, accum, Stride); + output = p -> ToOutputFloat(p, fIn, output, Stride); + } +} + // 16 bit precision ----------------------------------------------------------------------------------------------------------- // Null transformation, only applies formatters. No cach @@ -252,7 +352,7 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p, } -// Auxiliar: Handle precalculated gamut check +// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. static void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, const cmsUInt16Number wIn[], @@ -264,9 +364,12 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, if (wOutOfGamut >= 1) { cmsUInt16Number i; + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext); + + for (i=0; i < p ->Lut->OutputChannels; i++) { - for (i=0; i < p ->Lut->OutputChannels; i++) - wOut[i] = Alarm[i]; + wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; + } } else p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); @@ -393,34 +496,86 @@ typedef struct _cmsTransformCollection_st { } _cmsTransformCollection; // The linked list head -static _cmsTransformCollection* TransformCollection = NULL; +_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginTransformList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsTransformPluginChunkType newHead = { NULL }; + _cmsTransformCollection* entry; + _cmsTransformCollection* Anterior = NULL; + _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; + + // Walk the list copying all nodes + for (entry = head->TransformCollection; + entry != NULL; + entry = entry ->Next) { + + _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.TransformCollection == NULL) + newHead.TransformCollection = newEntry; + } + + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); +} + +void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginTransformList(ctx, src); + } + else { + static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); + } +} + + // Register new ways to transform -cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) { cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; _cmsTransformCollection* fl; + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); - if (Data == NULL) { + if (Data == NULL) { // Free the chain. Memory is safely freed at exit - TransformCollection = NULL; + ctx->TransformCollection = NULL; return TRUE; } // Factory callback is required - if (Plugin ->Factory == NULL) return FALSE; + if (Plugin ->Factory == NULL) return FALSE; - fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection)); + fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); if (fl == NULL) return FALSE; - // Copy the parameters + // Copy the parameters fl ->Factory = Plugin ->Factory; // Keep linked list - fl ->Next = TransformCollection; - TransformCollection = fl; + fl ->Next = ctx->TransformCollection; + ctx->TransformCollection = fl; // All is ok return TRUE; @@ -463,6 +618,7 @@ static _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); _cmsTransformCollection* Plugin; // Allocate needed memory @@ -473,7 +629,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, p ->Lut = lut; // Let's see if any plug-in want to do the transform by itself - for (Plugin = TransformCollection; + for (Plugin = ctx ->TransformCollection; Plugin != NULL; Plugin = Plugin ->Next) { @@ -493,10 +649,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, // Fill the formatters just in case the optimized routine is interested. // No error is thrown if the formatter doesn't exist. It is up to the optimization // factory to decide what to do in those cases. - p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; return p; } @@ -504,14 +660,14 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, // Not suitable for the transform plug-in, let's check the pipeline plug-in if (p ->Lut != NULL) - _cmsOptimizePipeline(&p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); // Check whatever this is a true floating point transform if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { // Get formatter function always return a valid union, but the contents of this union may be NULL. - p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { @@ -521,8 +677,15 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, return NULL; } - // Float transforms don't use cach, always are non-NULL - p ->xform = FloatXFORM; + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { + + p ->xform = NullFloatXFORM; + } + else { + // Float transforms don't use cach, always are non-NULL + p ->xform = FloatXFORM; + } + } else { @@ -534,8 +697,8 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, int BytesPerPixelInput; - p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; if (p ->FromInput == NULL || p ->ToOutput == NULL) { @@ -727,6 +890,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, // Check channel count if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { + cmsPipelineFree(Lut); cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); return NULL; } @@ -829,7 +993,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, for (i=0; i < nProfiles; i++) { BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; Intents[i] = Intent; - AdaptationStates[i] = GlobalAdaptationState; + AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1); } @@ -909,7 +1073,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; - Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = GlobalAdaptationState; + Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1); if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); @@ -984,8 +1148,8 @@ cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, return FALSE; } - FromInput = _cmsGetFormatter(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - ToOutput = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; if (FromInput == NULL || ToOutput == NULL) { diff --git a/src/share/native/sun/java2d/cmm/lcms/lcms2.h b/src/share/native/sun/java2d/cmm/lcms/lcms2.h index c6c35b185f6aa513f67b67a67eecb4e444fd2030..2fd2b56bdb85fde48b1a8fc12718575987f26a8d 100644 --- a/src/share/native/sun/java2d/cmm/lcms/lcms2.h +++ b/src/share/native/sun/java2d/cmm/lcms/lcms2.h @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2013 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -52,7 +52,7 @@ // //--------------------------------------------------------------------------------- // -// Version 2.5 +// Version 2.6 // #ifndef _lcms2_H @@ -84,6 +84,9 @@ // Uncomment to get rid of the tables for "half" float support // #define CMS_NO_HALF_SUPPORT 1 +// Uncomment to get rid of pthreads/windows dependency +// #define CMS_NO_PTHREADS 1 + // ********** End of configuration toggles ****************************** // Needed for streams @@ -101,7 +104,7 @@ extern "C" { #endif // Version/release -#define LCMS_VERSION 2050 +#define LCMS_VERSION 2060 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED @@ -202,28 +205,42 @@ typedef int cmsBool; // Try to detect big endian platforms. This list can be endless, so only some checks are performed over here. // you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar -#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN) +#if defined(__sgi__) || defined(__sgi) || defined(sparc) # define CMS_USE_BIG_ENDIAN 1 #endif -#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) -# define CMS_USE_BIG_ENDIAN 1 +#if defined(__s390__) || defined(__s390x__) +# define CMS_USE_BIG_ENDIAN 1 #endif -#if defined(__ppc__) || defined(__s390__) || defined(__s390x__) +# ifdef TARGET_CPU_PPC +# if TARGET_CPU_PPC +# define CMS_USE_BIG_ENDIAN 1 +# endif +# endif + +#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC) # define CMS_USE_BIG_ENDIAN 1 +# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) +# if __BYTE_ORDER == __LITTLE_ENDIAN +// // Don't use big endian for PowerPC little endian mode +# undef CMS_USE_BIG_ENDIAN +# endif +# endif #endif -#ifdef TARGET_CPU_PPC -# if TARGET_CPU_PPC -# define CMS_USE_BIG_ENDIAN 1 -# endif +// WORDS_BIGENDIAN takes precedence +#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN) +# define CMS_USE_BIG_ENDIAN 1 #endif #ifdef macintosh # ifdef __BIG_ENDIAN__ # define CMS_USE_BIG_ENDIAN 1 # endif +# ifdef __LITTLE_ENDIAN__ +# undef CMS_USE_BIG_ENDIAN +# endif #endif // Calling convention -- this is hardly platform and compiler dependent @@ -249,6 +266,14 @@ typedef int cmsBool; # define CMSAPI #endif +#ifdef HasTHREADS +# if HasTHREADS == 1 +# undef CMS_NO_PTHREADS +# else +# define CMS_NO_PTHREADS 1 +# endif +#endif + // Some common definitions #define cmsMAX_PATH 256 @@ -642,7 +667,6 @@ typedef struct { // Little CMS specific typedefs -typedef void* cmsContext; // Context identifier for multithreaded environments typedef void* cmsHANDLE ; // Generic handle typedef void* cmsHPROFILE; // Opaque typedefs to hide internals typedef void* cmsHTRANSFORM; @@ -1012,11 +1036,25 @@ typedef struct { CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2); CMSAPI long int CMSEXPORT cmsfilelength(FILE* f); -// Plug-In registering --------------------------------------------------------------------------------------------------- + +// Context handling -------------------------------------------------------------------------------------------------------- + +// Each context holds its owns globals and its own plug-ins. There is a global context with the id = 0 for lecacy compatibility +// though using the global context is not recomended. Proper context handling makes lcms more thread-safe. + +typedef struct _cmsContext_struct* cmsContext; + +CMSAPI cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData); +CMSAPI void CMSEXPORT cmsDeleteContext(cmsContext ContexID); +CMSAPI cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData); +CMSAPI void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID); + +// Plug-In registering -------------------------------------------------------------------------------------------------- CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin); CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin); CMSAPI void CMSEXPORT cmsUnregisterPlugins(void); +CMSAPI void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID); // Error logging ---------------------------------------------------------------------------------------------------------- @@ -1053,6 +1091,7 @@ typedef void (* cmsLogErrorHandlerFunction)(cmsContext ContextID, cmsUInt32Numb // Allows user to set any specific logger CMSAPI void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn); +CMSAPI void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn); // Conversions -------------------------------------------------------------------------------------------------------------- @@ -1514,6 +1553,7 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext Context CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void * MemPtr, cmsUInt32Number dwSize); CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void * MemPtr, cmsUInt32Number dwSize); CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write); CMSAPI cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile); CMSAPI cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName); @@ -1604,6 +1644,7 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransfo // Call with NULL as parameters to get the intent count CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions); // Flags @@ -1715,11 +1756,22 @@ CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, cmsUInt32Number Stride); -CMSAPI void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); +CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); + +CMSAPI void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, + const cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]); +CMSAPI void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, + cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]); + + + // Adaptation state for absolute colorimetric intent CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d); +CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d); + + // Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed CMSAPI cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform); diff --git a/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h b/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h index 6fbbb95b244e2e5ceb6ab6ddcf7f4afd936d7c12..7f28f3d277a77909df09795374dc9057f8ddad76 100644 --- a/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h +++ b/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h @@ -30,7 +30,7 @@ // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -193,16 +193,171 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) return _cmsQuickFloorWord(d); } -// Plug-In registering --------------------------------------------------------------- + +// Pthread support -------------------------------------------------------------------- +#ifndef CMS_NO_PTHREADS + +// This is the threading support. Unfortunately, it has to be platform-dependent because +// windows does not support pthreads. + +#ifdef CMS_IS_WINDOWS_ + +#define WIN32_LEAN_AND_MEAN 1 +#include + + +// From: http://locklessinc.com/articles/pthreads_on_windows/ +// The pthreads API has an initialization macro that has no correspondence to anything in +// the windows API. By investigating the internal definition of the critical section type, +// one may work out how to initialize one without calling InitializeCriticalSection(). +// The trick here is that InitializeCriticalSection() is not allowed to fail. It tries +// to allocate a critical section debug object, but if no memory is available, it sets +// the pointer to a specific value. (One would expect that value to be NULL, but it is +// actually (void *)-1 for some reason.) Thus we can use this special value for that +// pointer, and the critical section code will work. + +// The other important part of the critical section type to initialize is the number +// of waiters. This controls whether or not the mutex is locked. Fortunately, this +// part of the critical section is unlikely to change. Apparently, many programs +// already test critical sections to see if they are locked using this value, so +// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical +// section, even when they changed the underlying algorithm to be more scalable. +// The final parts of the critical section object are unimportant, and can be set +// to zero for their defaults. This yields an initialization macro: + +typedef CRITICAL_SECTION _cmsMutex; + +#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0} + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + EnterCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + LeaveCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + InitializeCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + DeleteCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + EnterCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + LeaveCriticalSection(m); + return 0; +} + +#else + +// Rest of the wide world +#include + +#define CMS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t _cmsMutex; + + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + return pthread_mutex_lock(m); +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + return pthread_mutex_unlock(m); +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + return pthread_mutex_init(m, NULL); +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + return pthread_mutex_destroy(m); +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + return pthread_mutex_lock(m); +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + return pthread_mutex_unlock(m); +} + +#endif +#else + +#define CMS_MUTEX_INITIALIZER 0 +typedef int _cmsMutex; + + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} +#endif + +// Plug-In registration --------------------------------------------------------------- // Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once. void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size); // Memory management -cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); // Interpolation -cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin); +cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Plugin); // Parametric curves cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin); @@ -228,9 +383,12 @@ cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plu // Transform cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin); +// Mutex +cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + // --------------------------------------------------------------------------------------------------------- -// Suballocators. Those are blocks of memory that is freed at the end on whole block. +// Suballocators. typedef struct _cmsSubAllocator_chunk_st { cmsUInt8Number* Block; @@ -253,9 +411,264 @@ typedef struct { _cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial); void _cmsSubAllocDestroy(_cmsSubAllocator* s); void* _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size); +void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size); // ---------------------------------------------------------------------------------- +// The context clients. +typedef enum { + + UserPtr, // User-defined pointer + Logger, + AlarmCodesContext, + AdaptationStateContext, + MemPlugin, + InterpPlugin, + CurvesPlugin, + FormattersPlugin, + TagTypePlugin, + TagPlugin, + IntentPlugin, + MPEPlugin, + OptimizationPlugin, + TransformPlugin, + MutexPlugin, + + // Last in list + MemoryClientMax + +} _cmsMemoryClient; + + +// Container for memory management plug-in. +typedef struct { + + _cmsMallocFnPtrType MallocPtr; + _cmsMalloZerocFnPtrType MallocZeroPtr; + _cmsFreeFnPtrType FreePtr; + _cmsReallocFnPtrType ReallocPtr; + _cmsCallocFnPtrType CallocPtr; + _cmsDupFnPtrType DupPtr; + +} _cmsMemPluginChunkType; + +// Copy memory management function pointers from plug-in to chunk, taking care of missing routines +void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr); + +// Internal structure for context +struct _cmsContext_struct { + + struct _cmsContext_struct* Next; // Points to next context in the new style + _cmsSubAllocator* MemPool; // The memory pool that stores context data + + void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is hold in the suballocator. + // If NULL, then it reverts to global Context0 + + _cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overriden +}; + +// Returns a pointer to a valid context structure, including the global one if id is zero. +// Verifies the magic number. +struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID); + +// Returns the block assigned to the specific zone. +void* _cmsContextGetClientChunk(cmsContext id, _cmsMemoryClient mc); + + +// Chunks of context memory by plug-in client ------------------------------------------------------- + +// Those structures encapsulates all variables needed by the several context clients (mostly plug-ins) + +// Container for error logger -- not a plug-in +typedef struct { + + cmsLogErrorHandlerFunction LogErrorHandler; // Set to NULL for Context0 fallback + +} _cmsLogErrorChunkType; + +// The global Context0 storage for error logger +extern _cmsLogErrorChunkType _cmsLogErrorChunk; + +// Allocate and init error logger container. +void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for alarm codes -- not a plug-in +typedef struct { + + cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]; + +} _cmsAlarmCodesChunkType; + +// The global Context0 storage for alarm codes +extern _cmsAlarmCodesChunkType _cmsAlarmCodesChunk; + +// Allocate and init alarm codes container. +void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for adaptation state -- not a plug-in +typedef struct { + + cmsFloat64Number AdaptationState; + +} _cmsAdaptationStateChunkType; + +// The global Context0 storage for adaptation state +extern _cmsAdaptationStateChunkType _cmsAdaptationStateChunk; + +// Allocate and init adaptation state container. +void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + + +// The global Context0 storage for memory management +extern _cmsMemPluginChunkType _cmsMemPluginChunk; + +// Allocate and init memory management container. +void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for interpolation plug-in +typedef struct { + + cmsInterpFnFactory Interpolators; + +} _cmsInterpPluginChunkType; + +// The global Context0 storage for interpolation plug-in +extern _cmsInterpPluginChunkType _cmsInterpPluginChunk; + +// Allocate and init interpolation container. +void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for parametric curves plug-in +typedef struct { + + struct _cmsParametricCurvesCollection_st* ParametricCurves; + +} _cmsCurvesPluginChunkType; + +// The global Context0 storage for tone curves plug-in +extern _cmsCurvesPluginChunkType _cmsCurvesPluginChunk; + +// Allocate and init parametric curves container. +void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for formatters plug-in +typedef struct { + + struct _cms_formatters_factory_list* FactoryList; + +} _cmsFormattersPluginChunkType; + +// The global Context0 storage for formatters plug-in +extern _cmsFormattersPluginChunkType _cmsFormattersPluginChunk; + +// Allocate and init formatters container. +void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// This chunk type is shared by TagType plug-in and MPE Plug-in +typedef struct { + + struct _cmsTagTypeLinkedList_st* TagTypes; + +} _cmsTagTypePluginChunkType; + + +// The global Context0 storage for tag types plug-in +extern _cmsTagTypePluginChunkType _cmsTagTypePluginChunk; + + +// The global Context0 storage for mult process elements plug-in +extern _cmsTagTypePluginChunkType _cmsMPETypePluginChunk; + +// Allocate and init Tag types container. +void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); +// Allocate and init MPE container. +void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); +// Container for tag plug-in +typedef struct { + + struct _cmsTagLinkedList_st* Tag; + +} _cmsTagPluginChunkType; + + +// The global Context0 storage for tag plug-in +extern _cmsTagPluginChunkType _cmsTagPluginChunk; + +// Allocate and init Tag container. +void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for intents plug-in +typedef struct { + + struct _cms_intents_list* Intents; + +} _cmsIntentsPluginChunkType; + + +// The global Context0 storage for intents plug-in +extern _cmsIntentsPluginChunkType _cmsIntentsPluginChunk; + +// Allocate and init intents container. +void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for optimization plug-in +typedef struct { + + struct _cmsOptimizationCollection_st* OptimizationCollection; + +} _cmsOptimizationPluginChunkType; + + +// The global Context0 storage for optimizers plug-in +extern _cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk; + +// Allocate and init optimizers container. +void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for transform plug-in +typedef struct { + + struct _cmsTransformCollection_st* TransformCollection; + +} _cmsTransformPluginChunkType; + +// The global Context0 storage for full-transform replacement plug-in +extern _cmsTransformPluginChunkType _cmsTransformPluginChunk; + +// Allocate and init transform container. +void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for mutex plug-in +typedef struct { + + _cmsCreateMutexFnPtrType CreateMutexPtr; + _cmsDestroyMutexFnPtrType DestroyMutexPtr; + _cmsLockMutexFnPtrType LockMutexPtr; + _cmsUnlockMutexFnPtrType UnlockMutexPtr; + +} _cmsMutexPluginChunkType; + +// The global Context0 storage for mutex plug-in +extern _cmsMutexPluginChunkType _cmsMutexPluginChunk; + +// Allocate and init mutex container. +void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// ---------------------------------------------------------------------------------- // MLU internal representation typedef struct { @@ -347,10 +760,14 @@ typedef struct _cms_iccprofile_struct { cmsBool TagSaveAsRaw[MAX_TABLE_TAG]; // True to write uncooked void * TagPtrs[MAX_TABLE_TAG]; cmsTagTypeHandler* TagTypeHandlers[MAX_TABLE_TAG]; // Same structure may be serialized on different types - // depending on profile version, so we keep track of the // type handler for each tag in the list. + // depending on profile version, so we keep track of the + // type handler for each tag in the list. // Special cmsBool IsWrite; + // Keep a mutex for cmsReadTag -- Note that this only works if the user includes a mutex plugin + void * UsrMutex; + } _cmsICCPROFILE; // IO helpers for profiles @@ -359,9 +776,9 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSp int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks); // Tag types -cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig); +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig); cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig); -cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig); +cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig); // Error logging --------------------------------------------------------------------------------------------------------- @@ -372,7 +789,7 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); void _cmsFreeInterpParams(cmsInterpParams* p); -cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p); +cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p); // Curves ---------------------------------------------------------------------------------------------------------------- @@ -503,7 +920,8 @@ cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space, cmsUInt16Number **Black, cmsUInt32Number *nOutputs); -cmsBool _cmsOptimizePipeline(cmsPipeline** Lut, +cmsBool _cmsOptimizePipeline(cmsContext ContextID, + cmsPipeline** Lut, int Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, @@ -528,7 +946,8 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type); cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type); -cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 +cmsFormatter _cmsGetFormatter(cmsContext ContextID, + cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 cmsFormatterDirection Dir, cmsUInt32Number dwFlags); diff --git a/src/share/native/sun/java2d/cmm/lcms/lcms2_plugin.h b/src/share/native/sun/java2d/cmm/lcms/lcms2_plugin.h index 1df7cf79b8d624da6a937d36a7a447c35e5b7835..77ff22846eb646dbbb28a686d51f1c34bd9ddd46 100644 --- a/src/share/native/sun/java2d/cmm/lcms/lcms2_plugin.h +++ b/src/share/native/sun/java2d/cmm/lcms/lcms2_plugin.h @@ -231,6 +231,7 @@ typedef void* (* _cmsDupUserDataFn)(cmsContext ContextID, const void* Data); #define cmsPluginMultiProcessElementSig 0x6D706548 // 'mpeH' #define cmsPluginOptimizationSig 0x6F707448 // 'optH' #define cmsPluginTransformSig 0x7A666D48 // 'xfmH' +#define cmsPluginMutexSig 0x6D747A48 // 'mtxH' typedef struct _cmsPluginBaseStruct { @@ -247,19 +248,28 @@ typedef struct _cmsPluginBaseStruct { //---------------------------------------------------------------------------------------------------------- // Memory handler. Each new plug-in type replaces current behaviour + +typedef void* (* _cmsMallocFnPtrType)(cmsContext ContextID, cmsUInt32Number size); +typedef void (* _cmsFreeFnPtrType)(cmsContext ContextID, void *Ptr); +typedef void* (* _cmsReallocFnPtrType)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize); + +typedef void* (* _cmsMalloZerocFnPtrType)(cmsContext ContextID, cmsUInt32Number size); +typedef void* (* _cmsCallocFnPtrType)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size); +typedef void* (* _cmsDupFnPtrType)(cmsContext ContextID, const void* Org, cmsUInt32Number size); + typedef struct { cmsPluginBase base; // Required - void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size); - void (* FreePtr)(cmsContext ContextID, void *Ptr); - void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize); + _cmsMallocFnPtrType MallocPtr; + _cmsFreeFnPtrType FreePtr; + _cmsReallocFnPtrType ReallocPtr; // Optional - void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size); - void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size); - void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size); + _cmsMalloZerocFnPtrType MallocZeroPtr; + _cmsCallocFnPtrType CallocPtr; + _cmsDupFnPtrType DupPtr; } cmsPluginMemHandler; @@ -622,6 +632,29 @@ typedef struct { } cmsPluginTransform; +//---------------------------------------------------------------------------------------------------------- +// Mutex + +typedef void* (* _cmsCreateMutexFnPtrType)(cmsContext ContextID); +typedef void (* _cmsDestroyMutexFnPtrType)(cmsContext ContextID, void* mtx); +typedef cmsBool (* _cmsLockMutexFnPtrType)(cmsContext ContextID, void* mtx); +typedef void (* _cmsUnlockMutexFnPtrType)(cmsContext ContextID, void* mtx); + +typedef struct { + cmsPluginBase base; + + _cmsCreateMutexFnPtrType CreateMutexPtr; + _cmsDestroyMutexFnPtrType DestroyMutexPtr; + _cmsLockMutexFnPtrType LockMutexPtr; + _cmsUnlockMutexFnPtrType UnlockMutexPtr; + +} cmsPluginMutex; + +CMSAPI void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID); +CMSAPI void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx); +CMSAPI cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx); +CMSAPI void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx); + #ifndef CMS_USE_CPP_API # ifdef __cplusplus diff --git a/src/solaris/classes/sun/awt/X11/XWindow.java b/src/solaris/classes/sun/awt/X11/XWindow.java index e55b8b82fd16b20f6ae850c2a0fe29e06d41496b..19cf22985b824c7444529815f69d77fe407bb5d8 100644 --- a/src/solaris/classes/sun/awt/X11/XWindow.java +++ b/src/solaris/classes/sun/awt/X11/XWindow.java @@ -55,7 +55,6 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { */ private final static int AWT_MULTICLICK_SMUDGE = 4; // ButtonXXX events stuff - static int rbutton = 0; static int lastX = 0, lastY = 0; static long lastTime = 0; static long lastButton = 0; @@ -632,23 +631,6 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { return res; } - /** - * Returns true if this event is disabled and shouldn't be passed to Java. - * Default implementation returns false for all events. - */ - static int getRightButtonNumber() { - if (rbutton == 0) { // not initialized yet - XToolkit.awtLock(); - try { - rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3); - } - finally { - XToolkit.awtUnlock(); - } - } - return rbutton; - } - static int getMouseMovementSmudge() { //TODO: It's possible to read corresponding settings return AWT_MULTICLICK_SMUDGE; @@ -716,11 +698,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { /* Check for popup trigger !! */ - if (lbutton == getRightButtonNumber() || lbutton > 2) { - popupTrigger = true; - } else { - popupTrigger = false; - } + popupTrigger = (lbutton == 3); } button = XConstants.buttons[lbutton - 1]; diff --git a/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java b/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java index d58a4c100f67eb81c28aca1c09b46b81087fad2e..ad344f1411eb09fb6dcd73dcb65856218ffbaa91 100644 --- a/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java +++ b/src/solaris/classes/sun/tools/attach/BsdVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,14 +24,14 @@ */ package sun.tools.attach; -import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.AttachOperationFailedException; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; + import java.io.InputStream; import java.io.IOException; import java.io.File; -import java.util.Properties; /* * Bsd implementation of HotSpotVirtualMachine @@ -191,6 +191,8 @@ public class BsdVirtualMachine extends HotSpotVirtualMachine { } if (completionStatus != 0) { + // read from the stream and use that as the error message + String message = readErrorMessage(sis); sis.close(); // In the event of a protocol mismatch then the target VM @@ -205,7 +207,11 @@ public class BsdVirtualMachine extends HotSpotVirtualMachine { if (cmd.equals("load")) { throw new AgentLoadException("Failed to load agent library"); } else { - throw new IOException("Command failed in target VM"); + if (message == null) { + throw new AttachOperationFailedException("Command failed in target VM"); + } else { + throw new AttachOperationFailedException(message); + } } } @@ -237,8 +243,9 @@ public class BsdVirtualMachine extends HotSpotVirtualMachine { if ((off < 0) || (off > bs.length) || (len < 0) || ((off + len) > bs.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); - } else if (len == 0) + } else if (len == 0) { return 0; + } return BsdVirtualMachine.read(s, bs, off, len); } diff --git a/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java b/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java index 1e08d70446e4516deceaa45afcd585dd85f0fdff..9dec425da0ddcc5668f149a45be04f972fe775c9 100644 --- a/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java +++ b/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,14 +24,14 @@ */ package sun.tools.attach; -import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.AttachOperationFailedException; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; + import java.io.InputStream; import java.io.IOException; import java.io.File; -import java.util.Properties; /* * Linux implementation of HotSpotVirtualMachine @@ -207,6 +207,8 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine { } if (completionStatus != 0) { + // read from the stream and use that as the error message + String message = readErrorMessage(sis); sis.close(); // In the event of a protocol mismatch then the target VM @@ -221,7 +223,11 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine { if (cmd.equals("load")) { throw new AgentLoadException("Failed to load agent library"); } else { - throw new IOException("Command failed in target VM"); + if (message == null) { + throw new AttachOperationFailedException("Command failed in target VM"); + } else { + throw new AttachOperationFailedException(message); + } } } diff --git a/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java b/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java index c7dcf21cf03c5c3f7db111bc13e0bfb8fc1c9713..3c57e4bda6ad24f198a81ab339ad44fac4691d39 100644 --- a/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java +++ b/src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,15 @@ */ package sun.tools.attach; -import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.AttachOperationFailedException; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; + import java.io.InputStream; import java.io.IOException; import java.io.File; import java.io.FileNotFoundException; -import java.util.Properties; /* * Solaris implementation of HotSpotVirtualMachine. @@ -147,11 +147,17 @@ public class SolarisVirtualMachine extends HotSpotVirtualMachine { // If non-0 it means an error but we need to special-case the // "load" command to ensure that the right exception is thrown. if (completionStatus != 0) { + // read from the stream and use that as the error message + String message = readErrorMessage(sis); sis.close(); if (cmd.equals("load")) { throw new AgentLoadException("Failed to load agent library"); } else { - throw new IOException("Command failed in target VM"); + if (message == null) { + throw new AttachOperationFailedException("Command failed in target VM"); + } else { + throw new AttachOperationFailedException(message); + } } } diff --git a/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c b/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c index cf3ff20300f02c79ab48b104a3484c1451899a2e..f8283ab1a830f11df79373d92105b577707dbec8 100644 --- a/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c +++ b/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,14 +198,14 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_BsdVirtualMachine_read len = remaining; } - RESTARTABLE(read(fd, buf+off, len), n); + RESTARTABLE(read(fd, buf, len), n); if (n == -1) { JNU_ThrowIOExceptionWithLastError(env, "read"); } else { if (n == 0) { n = -1; // EOF } else { - (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off)); + (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf)); } } return n; diff --git a/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c b/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c index 8c8c4eb1d69ef9be967fb67f3889b4696c4762b7..beb57648eeccf5e76ebd671f7eff7b685f326dab 100644 --- a/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c +++ b/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c @@ -416,14 +416,14 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_LinuxVirtualMachine_read len = remaining; } - RESTARTABLE(read(fd, buf+off, len), n); + RESTARTABLE(read(fd, buf, len), n); if (n == -1) { JNU_ThrowIOExceptionWithLastError(env, "read"); } else { if (n == 0) { n = -1; // EOF } else { - (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off)); + (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf)); } } return n; diff --git a/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c b/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c index 45b38eafe5eb8e073db249fa0ef1dc7e5b14aed1..32dd249f321b93619e2cdab83e6244626f31b467 100644 --- a/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c +++ b/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,14 +161,14 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_read len = remaining; } - RESTARTABLE(read(fd, buf+off, len), n); + RESTARTABLE(read(fd, buf, len), n); if (n == -1) { JNU_ThrowIOExceptionWithLastError(env, "read"); } else { if (n == 0) { n = -1; // EOF } else { - (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf+off)); + (*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf)); } } return n; diff --git a/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java b/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java index 6ea66773f1d82a81972873266779574ccaac9b35..3b34c0d181a3968ada615618142da57cc55b7f77 100644 --- a/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java +++ b/src/windows/classes/sun/tools/attach/WindowsVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,15 @@ */ package sun.tools.attach; -import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.AttachOperationFailedException; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; + import sun.tools.attach.HotSpotVirtualMachine; + import java.io.IOException; -import java.io.File; import java.io.InputStream; -import java.util.Properties; import java.util.Random; public class WindowsVirtualMachine extends HotSpotVirtualMachine { @@ -105,11 +105,17 @@ public class WindowsVirtualMachine extends HotSpotVirtualMachine { // read completion status int status = readInt(is); if (status != 0) { + // read from the stream and use that as the error message + String message = readErrorMessage(is); // special case the load command so that the right exception is thrown if (cmd.equals("load")) { throw new AgentLoadException("Failed to load agent library"); } else { - throw new IOException("Command failed in target VM"); + if (message == null) { + throw new AttachOperationFailedException("Command failed in target VM"); + } else { + throw new AttachOperationFailedException(message); + } } } diff --git a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c index 958cf59b5b16eab2cf4fe845a478446d48b84dd3..ed6efdfa24e0f8a88c08ce0058efb7de01258533 100644 --- a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c +++ b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c @@ -489,6 +489,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, } } } else { + /* NET_BindV6() closes both sockets upon a failure */ + (*env)->SetObjectField(env, this, pdsi_fdID, NULL); + (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); NET_ThrowCurrent (env, "Cannot bind"); return; } diff --git a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c index 3fb28f8714e4a0b4606c34f599ccde5ef2e70866..e7aa49b39d8976ee64b1e388e38b5ad7bf5f5626 100644 --- a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c +++ b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c @@ -467,6 +467,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); } } + } else { + /* NET_BindV6() closes both sockets upon a failure */ + (*env)->SetObjectField(env, this, psi_fdID, NULL); + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); } } else { rv = NET_WinBind(fd, (struct sockaddr *)&him, len, exclBind); diff --git a/src/windows/native/java/net/net_util_md.c b/src/windows/native/java/net/net_util_md.c index ae71733d8ad83ac891b06f5f69ff3a85b7172f95..274d90995bac49d7c673ec906a749afdbf2c6ecc 100644 --- a/src/windows/native/java/net/net_util_md.c +++ b/src/windows/native/java/net/net_util_md.c @@ -627,7 +627,7 @@ void dumpAddr (char *str, void *addr) { * and returns SOCKET_ERROR. Used in NET_BindV6 only. */ -#define CLOSE_SOCKETS_AND_RETURN { \ +#define CLOSE_SOCKETS_AND_RETURN do { \ if (fd != -1) { \ closesocket (fd); \ fd = -1; \ @@ -646,7 +646,7 @@ void dumpAddr (char *str, void *addr) { } \ b->ipv4_fd = b->ipv6_fd = -1; \ return SOCKET_ERROR; \ -} +} while(0) /* * if ipv6 is available, call NET_BindV6 to bind to the required address/port. diff --git a/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c b/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c index d7016723c3b093303909c02c88806ffe23d83ea7..82628e17e4cc67676b95daafb858021745af99ad 100644 --- a/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c +++ b/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c @@ -341,7 +341,7 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_WindowsVirtualMachine_readPipe if (nread == 0) { return (jint)-1; // EOF } else { - (*env)->SetByteArrayRegion(env, ba, off, (jint)nread, (jbyte *)(buf+off)); + (*env)->SetByteArrayRegion(env, ba, off, (jint)nread, (jbyte *)(buf)); } } diff --git a/test/ProblemList.txt b/test/ProblemList.txt index ffcfdfaf39b58f87186fdf3fcd7aff5999855f1d..dbf65eb13bc209d6f4f4a273bcbc15cccf193007 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -269,4 +269,7 @@ tools/launcher/FXLauncherTest.java linux-all # Filed 6772009 java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all +# 8051641 +sun/util/calendar/zi/TestZoneInfo310.java generic-all + ############################################################################ diff --git a/test/com/sun/tools/attach/SimpleProvider.java b/test/com/sun/tools/attach/SimpleProvider.java index 2a380f56215e49b0b5dc51dc3736071c809289c9..54f3dadf040971ccdffd17823eea67454f804081 100644 --- a/test/com/sun/tools/attach/SimpleProvider.java +++ b/test/com/sun/tools/attach/SimpleProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,4 +100,12 @@ class SimpleVirtualMachine extends VirtualMachine { public void dataDumpRequest() throws IOException { } + + public String startLocalManagementAgent() { + return null; + } + + public void startManagementAgent(Properties agentProperties) { + } + } diff --git a/test/com/sun/tools/attach/StartManagementAgent.java b/test/com/sun/tools/attach/StartManagementAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..16e701ede37c6d7b3f214c7cf01261730691a394 --- /dev/null +++ b/test/com/sun/tools/attach/StartManagementAgent.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.attach.AttachOperationFailedException; +import com.sun.tools.attach.VirtualMachine; + +import java.io.File; +import java.io.FileWriter; +import java.util.Properties; +import java.util.HashMap; + +import javax.management.remote.JMXServiceURL; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; + +import jdk.testlibrary.ProcessThread; +import jdk.testlibrary.Utils; + +/* + * @test + * @summary Test for VirtualMachine.startManagementAgent and VirtualMachine.startLocalManagementAgent + * @library /lib/testlibrary + * @run build Application Shutdown SimpleProvider jdk.testlibrary.* + * @run main StartManagementAgent + */ + +/* + * This test is not meant to test all possible configuration parameters to + * the JMX agent, there are other tests for that. This test makes sure it is + * possible to start the agent via attach. + */ +public class StartManagementAgent { + public static void main(String[] args) throws Throwable { + final String pidFile = "StartManagementAgent.Application.pid"; + ProcessThread processThread = null; + RunnerUtil.ProcessInfo info = null; + try { + processThread = RunnerUtil.startApplication(pidFile); + info = RunnerUtil.readProcessInfo(pidFile); + runTests(info.pid); + } catch (Throwable t) { + System.out.println("StartManagementAgent got unexpected exception: " + t); + t.printStackTrace(); + throw t; + } finally { + // Make sure the Application process is stopped. + RunnerUtil.stopApplication(info.shutdownPort, processThread); + } + } + + private static void basicTests(VirtualMachine vm) throws Exception { + + // Try calling with null argument + boolean exception = false; + try { + vm.startManagementAgent(null); + } catch (NullPointerException e) { + exception = true; + } + if (!exception) { + throw new Exception("startManagementAgent(null) should throw NPE"); + } + + // Try calling with a property value with a space in it + Properties p = new Properties(); + File f = new File("file with space"); + try (FileWriter fw = new FileWriter(f)) { + fw.write("com.sun.management.jmxremote.port=apa"); + } + p.put("com.sun.management.config.file", f.getAbsolutePath()); + try { + vm.startManagementAgent(p); + } catch(AttachOperationFailedException ex) { + // We expect parsing of "apa" above to fail, but if the file path + // can't be read we get a different exception message + if (!ex.getMessage().contains("java.lang.NumberFormatException")) { + throw ex; + } + } + } + + private static final String LOCAL_CONNECTOR_ADDRESS_PROP = + "com.sun.management.jmxremote.localConnectorAddress"; + + private static final int MAX_RETRIES = 10; + + public static void runTests(int pid) throws Exception { + VirtualMachine vm = VirtualMachine.attach(""+pid); + try { + + basicTests(vm); + + testLocalAgent(vm); + + // we retry the remote case several times in case the error + // was caused by a port conflict + int i = 0; + boolean success = false; + do { + try { + System.err.println("Trying remote agent. Try #" + i); + testRemoteAgent(vm); + success = true; + } catch(Exception ex) { + System.err.println("testRemoteAgent failed with exception:"); + ex.printStackTrace(); + System.err.println("Retrying."); + } + i++; + } while(!success && i < MAX_RETRIES); + if (!success) { + throw new Exception("testRemoteAgent failed after " + MAX_RETRIES + " tries"); + } + } finally { + vm.detach(); + } + } + + public static void testLocalAgent(VirtualMachine vm) throws Exception { + Properties agentProps = vm.getAgentProperties(); + String address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); + if (address != null) { + throw new Exception("Local management agent already started"); + } + + String result = vm.startLocalManagementAgent(); + + // try to parse the return value as a JMXServiceURL + new JMXServiceURL(result); + + agentProps = vm.getAgentProperties(); + address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); + if (address == null) { + throw new Exception("Local management agent could not be started"); + } + } + + public static void testRemoteAgent(VirtualMachine vm) throws Exception { + int port = Utils.getFreePort(); + + // try to connect - should fail + tryConnect(port, false); + + // start agent + System.out.println("Starting agent on port: " + port); + Properties mgmtProps = new Properties(); + mgmtProps.put("com.sun.management.jmxremote.port", port); + mgmtProps.put("com.sun.management.jmxremote.authenticate", "false"); + mgmtProps.put("com.sun.management.jmxremote.ssl", "false"); + vm.startManagementAgent(mgmtProps); + + // try to connect - should work + tryConnect(port, true); + + // try to start again - should fail + boolean exception = false; + try { + vm.startManagementAgent(mgmtProps); + } catch(AttachOperationFailedException ex) { + // expected + exception = true; + } + if (!exception) { + throw new Exception("Expected the second call to vm.startManagementAgent() to fail"); + } + } + + private static void tryConnect(int port, boolean shouldSucceed) throws Exception { + String jmxUrlStr = + String.format( + "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", + port); + JMXServiceURL url = new JMXServiceURL(jmxUrlStr); + HashMap env = new HashMap<>(); + + boolean succeeded; + try { + JMXConnector c = JMXConnectorFactory.connect(url, env); + c.getMBeanServerConnection(); + succeeded = true; + } catch(Exception ex) { + succeeded = false; + } + if (succeeded && !shouldSucceed) { + throw new Exception("Could connect to agent, but should not have been possible"); + } + if (!succeeded && shouldSucceed) { + throw new Exception("Could not connect to agent"); + } + } +} diff --git a/test/java/lang/invoke/LambdaFormTest.java b/test/java/lang/invoke/LambdaFormTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f078189c5c095f06d71383790138d32927ecac62 --- /dev/null +++ b/test/java/lang/invoke/LambdaFormTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary unit tests for java.lang.invoke.LambdaForm + * @run junit/othervm test.java.lang.invoke.LambdaFormTest + */ +package test.java.lang.invoke; + +import org.junit.Test; +import java.lang.reflect.Method; +import static org.junit.Assert.*; + +public class LambdaFormTest { + static final Method M_shortenSignature; + static { + try { + Class impl = Class.forName("java.lang.invoke.LambdaForm", false, null); + Method m = impl.getDeclaredMethod("shortenSignature", String.class); + m.setAccessible(true); + M_shortenSignature = m; + } catch(Exception e) { + throw new AssertionError(e); + } + } + + public static String shortenSignature(String signature) throws ReflectiveOperationException { + return (String)M_shortenSignature.invoke(null, signature); + } + + @Test + public void testShortenSignature() throws ReflectiveOperationException { + for (String s : new String[] { + // invariant strings: + "L", "LL", "ILL", "LIL", "LLI", "IILL", "ILIL", "ILLI", + // a few mappings: + "LLL=L3", "LLLL=L4", "LLLLLLLLLL=L10", + "IIIDDD=I3D3", "IDDD=ID3", "IIDDD=IID3", "IIID=I3D", "IIIDD=I3DD" + }) { + String s2 = s.substring(s.indexOf('=')+1); + String s1 = s.equals(s2) ? s : s.substring(0, s.length() - s2.length() - 1); + // mix the above cases with before and after reps of Z* + for (int k = -3; k <= 3; k++) { + String beg = (k < 0 ? "ZZZZ".substring(-k) : ""); + String end = (k > 0 ? "ZZZZ".substring(+k) : ""); + String ks1 = beg+s1+end; + String ks2 = shortenSignature(beg)+s2+shortenSignature(end); + String ks3 = shortenSignature(ks1); + assertEquals(ks2, ks3); + } + } + } + + public static void main(String[] args) throws ReflectiveOperationException { + LambdaFormTest test = new LambdaFormTest(); + test.testShortenSignature(); + } +} diff --git a/test/java/lang/invoke/MethodHandlesTest.java b/test/java/lang/invoke/MethodHandlesTest.java index d607e06aad2d272ed61de19c0b7db07ead0471a6..993eaefef0f1c5af17172dfe74a6f0c933ebd4e2 100644 --- a/test/java/lang/invoke/MethodHandlesTest.java +++ b/test/java/lang/invoke/MethodHandlesTest.java @@ -2160,15 +2160,23 @@ public class MethodHandlesTest { else type = type.changeParameterType(j, argType); if (done.add(type)) - testInvokers(type); + testInvokersWithCatch(type); MethodType vtype = type.changeReturnType(void.class); if (done.add(vtype)) - testInvokers(vtype); + testInvokersWithCatch(vtype); } } } } + public void testInvokersWithCatch(MethodType type) throws Throwable { + try { + testInvokers(type); + } catch (Throwable ex) { + System.out.println("*** testInvokers on "+type+" => "); + ex.printStackTrace(System.out); + } + } public void testInvokers(MethodType type) throws Throwable { if (verbosity >= 3) System.out.println("test invokers for "+type); diff --git a/test/java/lang/invoke/VarargsArrayTest.java b/test/java/lang/invoke/VarargsArrayTest.java new file mode 100644 index 0000000000000000000000000000000000000000..91bf36485f2998f878dd77da2a2e772e7c70f76f --- /dev/null +++ b/test/java/lang/invoke/VarargsArrayTest.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import sun.invoke.util.Wrapper; + +import java.util.Arrays; +import java.util.Collections; + +/* @test + * @summary unit tests for varargs array methods: MethodHandleInfo.varargsArray(int), + * MethodHandleInfo.varargsArray(Class,int) & MethodHandleInfo.varargsList(int) + * + * @run main/bootclasspath java.lang.invoke.VarargsArrayTest + * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250 + * java.lang.invoke.VarargsArrayTest + */ + +/* This might take a while and burn lots of metadata: + * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true java.lang.invoke.VarargsArrayTest + */ +public class VarargsArrayTest { + private static final Class CLASS = VarargsArrayTest.class; + private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40); + private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0); + private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE"); + + public static void main(String[] args) throws Throwable { + testVarargsArray(); + testVarargsReferenceArray(); + testVarargsPrimitiveArray(); + } + + public static void testVarargsArray() throws Throwable { + final int MIN = START_ARITY; + final int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added + for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) { + MethodHandle target = MethodHandleImpl.varargsArray(nargs); + Object[] args = new Object[nargs]; + for (int i = 0; i < nargs; i++) + args[i] = "#"+i; + Object res = target.invokeWithArguments(args); + assertArrayEquals(args, (Object[])res); + } + } + + public static void testVarargsReferenceArray() throws Throwable { + testTypedVarargsArray(Object[].class); + testTypedVarargsArray(String[].class); + testTypedVarargsArray(Number[].class); + } + + public static void testVarargsPrimitiveArray() throws Throwable { + testTypedVarargsArray(int[].class); + testTypedVarargsArray(long[].class); + testTypedVarargsArray(byte[].class); + testTypedVarargsArray(boolean[].class); + testTypedVarargsArray(short[].class); + testTypedVarargsArray(char[].class); + testTypedVarargsArray(float[].class); + testTypedVarargsArray(double[].class); + } + + private static int nextArgCount(int nargs, int density, int MAX) { + if (EXHAUSTIVE) return nargs + 1; + if (nargs >= MAX) return Integer.MAX_VALUE; + int BOT = 20, TOP = MAX-5; + if (density < 10) { BOT = 10; MAX = TOP-2; } + if (nargs <= BOT || nargs >= TOP) { + ++nargs; + } else { + int bump = Math.max(1, 100 / density); + nargs += bump; + if (nargs > TOP) nargs = TOP; + } + return nargs; + } + + private static void testTypedVarargsArray(Class arrayType) throws Throwable { + Class elemType = arrayType.getComponentType(); + int MIN = START_ARITY; + int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added + int density = 3; + if (elemType == int.class || elemType == long.class) density = 7; + if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; } + for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) { + Object[] args = makeTestArray(elemType, nargs); + MethodHandle varargsArray = MethodHandleImpl.varargsArray(arrayType, nargs); + MethodType vaType = varargsArray.type(); + assertEquals(arrayType, vaType.returnType()); + if (nargs != 0) { + assertEquals(elemType, vaType.parameterType(0)); + assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1)); + } + assertEquals(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType)), + vaType); + Object res = varargsArray.invokeWithArguments(args); + assertEquals(res.getClass(), arrayType); + String resString = toArrayString(res); + assertEquals(Arrays.toString(args), resString); + + MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs); + MethodType stype = spreader.type(); + assert(stype == MethodType.methodType(arrayType, arrayType)); + if (nargs <= 5) { + // invoke target as a spreader also: + @SuppressWarnings("cast") + Object res2 = spreader.invokeWithArguments((Object)res); + String res2String = toArrayString(res2); + assertEquals(Arrays.toString(args), res2String); + // invoke the spreader on a generic Object[] array; check for error + try { + Object res3 = spreader.invokeWithArguments((Object)args); + String res3String = toArrayString(res3); + assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class)); + assertEquals(Arrays.toString(args), res3String); + } catch (ClassCastException ex) { + assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class)); + } + } + if (nargs == 0) { + // invoke spreader on null arglist + Object res3 = spreader.invokeWithArguments((Object)null); + String res3String = toArrayString(res3); + assertEquals(Arrays.toString(args), res3String); + } + } + } + + private static Object[] makeTestArray(Class elemType, int len) { + Wrapper elem = null; + if (elemType.isPrimitive()) + elem = Wrapper.forPrimitiveType(elemType); + else if (Wrapper.isWrapperType(elemType)) + elem = Wrapper.forWrapperType(elemType); + Object[] args = new Object[len]; + for (int i = 0; i < len; i++) { + Object arg = i * 100; + if (elem == null) { + if (elemType == String.class) + arg = "#"+arg; + arg = elemType.cast(arg); // just to make sure + } else { + switch (elem) { + case BOOLEAN: arg = (i % 3 == 0); break; + case CHAR: arg = 'a' + i; break; + case LONG: arg = (long)i * 1000_000_000; break; + case FLOAT: arg = (float)i / 100; break; + case DOUBLE: arg = (double)i / 1000_000; break; + } + arg = elem.cast(arg, elemType); + } + args[i] = arg; + } + return args; + } + + private static String toArrayString(Object a) { + if (a == null) return "null"; + Class elemType = a.getClass().getComponentType(); + if (elemType == null) return a.toString(); + if (elemType.isPrimitive()) { + switch (Wrapper.forPrimitiveType(elemType)) { + case INT: return Arrays.toString((int[])a); + case BYTE: return Arrays.toString((byte[])a); + case BOOLEAN: return Arrays.toString((boolean[])a); + case SHORT: return Arrays.toString((short[])a); + case CHAR: return Arrays.toString((char[])a); + case FLOAT: return Arrays.toString((float[])a); + case LONG: return Arrays.toString((long[])a); + case DOUBLE: return Arrays.toString((double[])a); + } + } + return Arrays.toString((Object[])a); + } + + public static void assertArrayEquals(Object[] arr1, Object[] arr2) { + if (arr1 == null && arr2 == null) return; + if (arr1 != null && arr2 != null && arr1.length == arr2.length) { + for (int i = 0; i < arr1.length; i++) { + assertEquals(arr1[i], arr2[i]); + } + return; + } + throw new AssertionError(Arrays.deepToString(arr1) + " != " + Arrays.deepToString(arr2)); + } + + public static void assertEquals(Object o1, Object o2) { + if (o1 == null && o2 == null) return; + if (o1 != null && o1.equals(o2)) return; + throw new AssertionError(o1 + " != " + o2); + } + + public static void assertTrue(String msg, boolean b) { + if (!b) { + throw new AssertionError(msg); + } + } + + public static void assertFalse(String msg, boolean b) { + assertTrue(msg, !b); + } +} diff --git a/test/java/lang/reflect/annotationSharing/AnnotationSharing.java b/test/java/lang/reflect/annotationSharing/AnnotationSharing.java new file mode 100644 index 0000000000000000000000000000000000000000..4606b967c6ad5db79ba2263a64ec02ba162479b1 --- /dev/null +++ b/test/java/lang/reflect/annotationSharing/AnnotationSharing.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8054987 + * @summary Test sharing of annotations between Executable/Field instances. + * Sharing should not be noticeable when performing mutating + * operations. + * @run testng AnnotationSharing + */ + +import java.lang.annotation.*; +import java.lang.reflect.*; + +import org.testng.annotations.Test; + +public class AnnotationSharing { + public static void main(String ... args) throws Exception { + } + + @Test + public void testMethodSharing() throws Exception { + Method[] m1 = AnnotationSharing.class.getMethods(); + Method[] m2 = AnnotationSharing.class.getMethods(); + validateSharingSafelyObservable(m1, m2); + } + + @Test + public void testDeclaredMethodSharing() throws Exception { + Method[] m3 = AnnotationSharing.class.getDeclaredMethods(); + Method[] m4 = AnnotationSharing.class.getDeclaredMethods(); + validateSharingSafelyObservable(m3, m4); + } + + @Test + public void testFieldSharing() throws Exception { + Field[] f1 = AnnotationSharing.class.getFields(); + Field[] f2 = AnnotationSharing.class.getFields(); + validateSharingSafelyObservable(f1, f2); + } + + @Test + public void testDeclaredFieldsSharing() throws Exception { + Field[] f3 = AnnotationSharing.class.getDeclaredFields(); + Field[] f4 = AnnotationSharing.class.getDeclaredFields(); + validateSharingSafelyObservable(f3, f4); + } + + @Test + public void testMethodSharingOccurs() throws Exception { + Method mm1 = AnnotationSharing.class.getDeclaredMethod("m", (Class[])null); + Method mm2 = AnnotationSharing.class.getDeclaredMethod("m", (Class[])null); + validateAnnotationSharing(mm1, mm2); + } + + @Test + public void testMethodSharingIsSafe() throws Exception { + Method mm1 = AnnotationSharing.class.getDeclaredMethod("m", (Class[])null); + Method mm2 = AnnotationSharing.class.getDeclaredMethod("m", (Class[])null); + validateAnnotationSharingIsSafe(mm1, mm2); + validateArrayValues(mm1.getAnnotation(Baz.class), mm2.getAnnotation(Baz.class)); + } + + @Test + public void testFieldSharingOccurs() throws Exception { + Field ff1 = AnnotationSharing.class.getDeclaredField("f"); + Field ff2 = AnnotationSharing.class.getDeclaredField("f"); + validateAnnotationSharing(ff1, ff2); + } + + @Test + public void testFieldSharingIsSafe() throws Exception { + Field ff1 = AnnotationSharing.class.getDeclaredField("f"); + Field ff2 = AnnotationSharing.class.getDeclaredField("f"); + validateAnnotationSharingIsSafe(ff1, ff2); + validateArrayValues(ff1.getAnnotation(Baz.class), ff2.getAnnotation(Baz.class)); + } + + // Validate that AccessibleObject instances are not shared + private static void validateSharingSafelyObservable(AccessibleObject[] m1, AccessibleObject[] m2) + throws Exception { + + // Validate that setAccessible works + for (AccessibleObject m : m1) + m.setAccessible(false); + + for (AccessibleObject m : m2) + m.setAccessible(true); + + for (AccessibleObject m : m1) + if (m.isAccessible()) + throw new RuntimeException(m + " should not be accessible"); + + for (AccessibleObject m : m2) + if (!m.isAccessible()) + throw new RuntimeException(m + " should be accessible"); + + // Validate that methods are still equal() + for (int i = 0; i < m1.length; i++) + if (!m1[i].equals(m2[i])) + throw new RuntimeException(m1[i] + " and " + m2[i] + " should be equal()"); + + // Validate that the arrays aren't shared + for (int i = 0; i < m1.length; i++) + m1[i] = null; + + for (int i = 0; i < m2.length; i++) + if (m2[i] == null) + throw new RuntimeException("Detected sharing of AccessibleObject arrays"); + } + + // Validate that annotations are shared + private static void validateAnnotationSharing(AccessibleObject m1, AccessibleObject m2) { + Bar b1 = m1.getAnnotation(Bar.class); + Bar b2 = m2.getAnnotation(Bar.class); + + if (b1 != b2) + throw new RuntimeException(b1 + " and " + b2 + " should be =="); + + } + + // Validate that Method instances representing the annotation elements + // behave as intended + private static void validateAnnotationSharingIsSafe(AccessibleObject m1, AccessibleObject m2) + throws Exception { + Bar b1 = m1.getAnnotation(Bar.class); + Bar b2 = m2.getAnnotation(Bar.class); + + Method mm1 = b1.annotationType().getMethod("value", (Class[]) null); + Method mm2 = b2.annotationType().getMethod("value", (Class[]) null); + inner(mm1, mm2); + + mm1 = b1.getClass().getMethod("value", (Class[]) null); + mm2 = b2.getClass().getMethod("value", (Class[]) null); + inner(mm1, mm2); + + } + private static void inner(Method mm1, Method mm2) + throws Exception { + if (!mm1.equals(mm2)) + throw new RuntimeException(mm1 + " and " + mm2 + " should be equal()"); + + mm1.setAccessible(false); + mm2.setAccessible(true); + + if (mm1.isAccessible()) + throw new RuntimeException(mm1 + " should not be accessible"); + + if (!mm2.isAccessible()) + throw new RuntimeException(mm2 + " should be accessible"); + } + + // Validate that array element values are not shared + private static void validateArrayValues(Baz a, Baz b) { + String[] s1 = a.value(); + String[] s2 = b.value(); + + s1[0] = "22"; + + if (!s2[0].equals("1")) + throw new RuntimeException("Mutation of array elements should not be detectable"); + } + + @Foo @Bar("val") @Baz({"1", "2"}) + public void m() { + return ; + } + + @Foo @Bar("someValue") @Baz({"1", "22", "33"}) + public Object f = new Object(); +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Foo {} + +@Retention(RetentionPolicy.RUNTIME) +@interface Bar { + String value(); +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Baz { + String [] value(); +} diff --git a/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java index 4021a147c9cd8210749bfee83be74370b4d6fcdf..28ccbfe051674107b951b739a8388633b28d44af 100644 --- a/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java +++ b/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java @@ -138,7 +138,7 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { {"Asia/Taipei", "China Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, {"America/Chicago", "CST", none, Locale.ENGLISH, TextStyle.SHORT}, {"Asia/Taipei", "CST", preferred, Locale.ENGLISH, TextStyle.SHORT}, - {"Australia/South", "CST", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, + {"Australia/South", "ACST", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, {"America/Chicago", "CDT", none, Locale.ENGLISH, TextStyle.SHORT}, {"Asia/Shanghai", "CDT", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, }; diff --git a/test/java/util/Currency/tablea1.txt b/test/java/util/Currency/tablea1.txt index 94c848ae880069220c68e05545a24d164e1c82d5..298856753b5842c98f42e3b93fcaa1d0d02682b2 100644 --- a/test/java/util/Currency/tablea1.txt +++ b/test/java/util/Currency/tablea1.txt @@ -1,12 +1,12 @@ # # -# Amendments up until ISO 4217 AMENDMENT NUMBER 156 -# (As of 23 July 2013) +# Amendments up until ISO 4217 AMENDMENT NUMBER 159 +# (As of 15 August 2014) # # Version FILEVERSION=1 -DATAVERSION=156 +DATAVERSION=159 # ISO 4217 currency data AF AFN 971 2 @@ -142,7 +142,7 @@ LS LSL 426 2 LR LRD 430 2 LY LYD 434 3 LI CHF 756 2 -LT LTL 440 2 +LT LTL 440 2 2014-12-31-22-00-00 EUR 978 2 LU EUR 978 2 MO MOP 446 2 MK MKD 807 2 diff --git a/test/java/util/logging/CheckZombieLockTest.java b/test/java/util/logging/CheckZombieLockTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ab65a814f0b4c3b87396626a2b29fc355205b3f9 --- /dev/null +++ b/test/java/util/logging/CheckZombieLockTest.java @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8048020 + * @author Daniel Fuchs + * @summary Regression on java.util.logging.FileHandler. + * The fix is to avoid filling up the file system with zombie lock files. + * + * @run main/othervm CheckZombieLockTest WRITABLE CLOSE CLEANUP + * @run main/othervm CheckZombieLockTest CLEANUP + * @run main/othervm CheckZombieLockTest WRITABLE + * @run main/othervm CheckZombieLockTest CREATE_FIRST + * @run main/othervm CheckZombieLockTest CREATE_NEXT + * @run main/othervm CheckZombieLockTest CREATE_NEXT + * @run main/othervm CheckZombieLockTest CLEANUP + * @run main/othervm CheckZombieLockTest REUSE + * @run main/othervm CheckZombieLockTest CLEANUP + */ +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +public class CheckZombieLockTest { + + private static final String WRITABLE_DIR = "writable-lockfile-dir"; + private static volatile boolean supportsLocking = true; + + static enum TestCase { + WRITABLE, // just verifies that we can create a file in our 'writable-lockfile-dir' + CLOSE, // checks that closing a FileHandler removes its lock file + CREATE_FIRST, // verifies that 'writable-lockfile-dir' contains no lock, then creates a first FileHandler. + CREATE_NEXT, // verifies that 'writable-lockfile-dir' contains a single lock, then creates the next FileHandler + REUSE, // verifies that zombie lock files can be reused + CLEANUP // removes "writable-lockfile-dir" + }; + + public static void main(String... args) throws IOException { + // we'll base all file creation attempts on the system temp directory, + // %t + File writableDir = setup(); + System.out.println("Writable dir is: " + writableDir.getAbsolutePath()); + // we now have one writable directory to work with: + // writableDir + if (args == null || args.length == 0) { + args = new String[] { "WRITABLE", "CLOSE", "CLEANUP" }; + } + try { + runTests(writableDir, args); + } catch (RuntimeException | IOException | Error x) { + // some error occured: cleanup + delete(writableDir); + throw x; + } + } + + /** + * @param writableDir in which log and lock file are created + * @throws SecurityException + * @throws RuntimeException + * @throws IOException + */ + private static void runTests(File writableDir, String... args) throws SecurityException, + RuntimeException, IOException { + for (String arg : args) { + switch(TestCase.valueOf(arg)) { + // Test 1: makes sure we can create FileHandler in writable directory + case WRITABLE: checkWritable(writableDir); break; + // Test 2: verifies that FileHandler.close() cleans up its lock file + case CLOSE: testFileHandlerClose(writableDir); break; + // Test 3: creates the first file handler + case CREATE_FIRST: testFileHandlerCreate(writableDir, true); break; + // Test 4, 5, ... creates the next file handler + case CREATE_NEXT: testFileHandlerCreate(writableDir, false); break; + // Checks that zombie lock files are reused appropriatly + case REUSE: testFileHandlerReuse(writableDir); break; + // Removes the writableDir + case CLEANUP: delete(writableDir); break; + default: throw new RuntimeException("No such test case: " + arg); + } + } + } + + /** + * @param writableDir in which log and lock file are created + * @throws SecurityException + * @throws RuntimeException + * @throws IOException + */ + private static void checkWritable(File writableDir) throws SecurityException, + RuntimeException, IOException { + // Test 1: make sure we can create/delete files in the writable dir. + final File file = new File(writableDir, "test.txt"); + if (!createFile(file, false)) { + throw new IOException("Can't create " + file + "\n\tUnable to run test"); + } else { + delete(file); + } + } + + + private static FileHandler createFileHandler(File writableDir) throws SecurityException, + RuntimeException, IOException { + // Test 1: make sure we can create FileHandler in writable directory + try { + FileHandler handler = new FileHandler("%t/" + WRITABLE_DIR + "/log.log"); + handler.publish(new LogRecord(Level.INFO, handler.toString())); + handler.flush(); + return handler; + } catch (IOException ex) { + throw new RuntimeException("Test failed: should have been able" + + " to create FileHandler for " + "%t/" + WRITABLE_DIR + + "/log.log in writable directory.", ex); + } + } + + private static List listLocks(File writableDir, boolean print) + throws IOException { + List locks = new ArrayList<>(); + for (File f : writableDir.listFiles()) { + if (print) { + System.out.println("Found file: " + f.getName()); + } + if (f.getName().endsWith(".lck")) { + locks.add(f); + } + } + return locks; + } + + private static void testFileHandlerClose(File writableDir) throws IOException { + File fakeLock = new File(writableDir, "log.log.lck"); + if (!createFile(fakeLock, false)) { + throw new IOException("Can't create fake lock file: " + fakeLock); + } + try { + List before = listLocks(writableDir, true); + System.out.println("before: " + before.size() + " locks found"); + FileHandler handler = createFileHandler(writableDir); + System.out.println("handler created: " + handler); + List after = listLocks(writableDir, true); + System.out.println("after creating handler: " + after.size() + " locks found"); + handler.close(); + System.out.println("handler closed: " + handler); + List afterClose = listLocks(writableDir, true); + System.out.println("after closing handler: " + afterClose.size() + " locks found"); + afterClose.removeAll(before); + if (!afterClose.isEmpty()) { + throw new RuntimeException("Zombie lock file detected: " + afterClose); + } + } finally { + if (fakeLock.canRead()) delete(fakeLock); + } + List finalLocks = listLocks(writableDir, false); + System.out.println("After cleanup: " + finalLocks.size() + " locks found"); + } + + + private static void testFileHandlerReuse(File writableDir) throws IOException { + List before = listLocks(writableDir, true); + System.out.println("before: " + before.size() + " locks found"); + try { + if (!before.isEmpty()) { + throw new RuntimeException("Expected no lock file! Found: " + before); + } + } finally { + before.stream().forEach(CheckZombieLockTest::delete); + } + + FileHandler handler1 = createFileHandler(writableDir); + System.out.println("handler created: " + handler1); + List after = listLocks(writableDir, true); + System.out.println("after creating handler: " + after.size() + " locks found"); + if (after.size() != 1) { + throw new RuntimeException("Unexpected number of lock files found for " + + handler1 + ": " + after); + } + final File lock = after.get(0); + after.clear(); + handler1.close(); + after = listLocks(writableDir, true); + System.out.println("after closing handler: " + after.size() + " locks found"); + if (!after.isEmpty()) { + throw new RuntimeException("Unexpected number of lock files found for " + + handler1 + ": " + after); + } + if (!createFile(lock, false)) { + throw new IOException("Can't create fake lock file: " + lock); + } + try { + before = listLocks(writableDir, true); + System.out.println("before: " + before.size() + " locks found"); + if (before.size() != 1) { + throw new RuntimeException("Unexpected number of lock files found: " + + before + " expected [" + lock + "]."); + } + FileHandler handler2 = createFileHandler(writableDir); + System.out.println("handler created: " + handler2); + after = listLocks(writableDir, true); + System.out.println("after creating handler: " + after.size() + " locks found"); + after.removeAll(before); + if (!after.isEmpty()) { + throw new RuntimeException("Unexpected lock file found: " + after + + "\n\t" + lock + " should have been reused"); + } + handler2.close(); + System.out.println("handler closed: " + handler2); + List afterClose = listLocks(writableDir, true); + System.out.println("after closing handler: " + afterClose.size() + " locks found"); + if (!afterClose.isEmpty()) { + throw new RuntimeException("Zombie lock file detected: " + afterClose); + } + + if (supportsLocking) { + FileChannel fc = FileChannel.open(Paths.get(lock.getAbsolutePath()), + StandardOpenOption.CREATE_NEW, StandardOpenOption.APPEND, + StandardOpenOption.WRITE); + try { + if (fc.tryLock() != null) { + System.out.println("locked: " + lock); + handler2 = createFileHandler(writableDir); + System.out.println("handler created: " + handler2); + after = listLocks(writableDir, true); + System.out.println("after creating handler: " + after.size() + + " locks found"); + after.removeAll(before); + if (after.size() != 1) { + throw new RuntimeException("Unexpected lock files found: " + after + + "\n\t" + lock + " should not have been reused"); + } + } else { + throw new RuntimeException("Failed to lock: " + lock); + } + } finally { + delete(lock); + } + } + } finally { + List finalLocks = listLocks(writableDir, false); + System.out.println("end: " + finalLocks.size() + " locks found"); + delete(writableDir); + } + } + + + private static void testFileHandlerCreate(File writableDir, boolean first) + throws IOException { + List before = listLocks(writableDir, true); + System.out.println("before: " + before.size() + " locks found"); + try { + if (first && !before.isEmpty()) { + throw new RuntimeException("Expected no lock file! Found: " + before); + } else if (!first && before.size() != 1) { + throw new RuntimeException("Expected a single lock file! Found: " + before); + } + } finally { + before.stream().forEach(CheckZombieLockTest::delete); + } + FileHandler handler = createFileHandler(writableDir); + System.out.println("handler created: " + handler); + List after = listLocks(writableDir, true); + System.out.println("after creating handler: " + after.size() + " locks found"); + if (after.size() != 1) { + throw new RuntimeException("Unexpected number of lock files found for " + + handler + ": " + after); + } + } + + + /** + * Setup all the files and directories needed for the tests + * + * @return writable directory created that needs to be deleted when done + * @throws RuntimeException + */ + private static File setup() throws RuntimeException { + // First do some setup in the temporary directory (using same logic as + // FileHandler for %t pattern) + String tmpDir = System.getProperty("java.io.tmpdir"); // i.e. %t + if (tmpDir == null) { + tmpDir = System.getProperty("user.home"); + } + File tmpOrHomeDir = new File(tmpDir); + // Create a writable directory here (%t/writable-lockfile-dir) + File writableDir = new File(tmpOrHomeDir, WRITABLE_DIR); + if (!createFile(writableDir, true)) { + throw new RuntimeException("Test setup failed: unable to create" + + " writable working directory " + + writableDir.getAbsolutePath() ); + } + + // try to determine whether file locking is supported + final String uniqueFileName = UUID.randomUUID().toString()+".lck"; + try { + FileChannel fc = FileChannel.open(Paths.get(writableDir.getAbsolutePath(), + uniqueFileName), + StandardOpenOption.CREATE_NEW, StandardOpenOption.APPEND, + StandardOpenOption.DELETE_ON_CLOSE); + try { + fc.tryLock(); + } catch(IOException x) { + supportsLocking = false; + } finally { + fc.close(); + } + } catch (IOException t) { + // should not happen + System.err.println("Failed to create new file " + uniqueFileName + + " in " + writableDir.getAbsolutePath()); + throw new RuntimeException("Test setup failed: unable to run test", t); + } + return writableDir; + } + + /** + * @param newFile + * @return true if file already exists or creation succeeded + */ + private static boolean createFile(File newFile, boolean makeDirectory) { + if (newFile.exists()) { + return true; + } + if (makeDirectory) { + return newFile.mkdir(); + } else { + try { + return newFile.createNewFile(); + } catch (IOException ioex) { + ioex.printStackTrace(); + return false; + } + } + } + + /* + * Recursively delete all files starting at specified file + */ + private static void delete(File f) { + if (f != null && f.isDirectory()) { + for (File c : f.listFiles()) + delete(c); + } + if (!f.delete()) + System.err.println( + "WARNING: unable to delete/cleanup writable test directory: " + + f ); + } +} diff --git a/test/javax/xml/bind/marshal/8036981/Good.java b/test/javax/xml/bind/marshal/8036981/Good.java new file mode 100644 index 0000000000000000000000000000000000000000..75987f36a67d6d09531fbe0a055bca54ae0a27e0 --- /dev/null +++ b/test/javax/xml/bind/marshal/8036981/Good.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package testjaxbcontext; + +import org.w3c.dom.Element; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.List; + +/** + *

    + * Java class for Good complex type. + * + *

    + * The following schema fragment specifies the expected content contained within + * this class. + * + *

    + * <complexType name="Good">
    + *   <complexContent>
    + *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
    + *       <sequence>
    + *         <any processContents='skip' maxOccurs="70"/>
    + *       </sequence>
    + *     </restriction>
    + *   </complexContent>
    + * </complexType>
    + * 
    + * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "Good", propOrder = { + "any" +}) +public class Good { + + @XmlAnyElement + protected List any; + + /** + * Gets the value of the any property. + * + *

    + * This accessor method returns a reference to the live list, not a + * snapshot. Therefore any modification you make to the returned list will + * be present inside the JAXB object. This is why there is not a + * set method for the any property. + * + *

    + * For example, to add a new item, do as follows: + *

    +     *    getAny().add(newItem);
    +     * 
    + * + * + *

    + * Objects of the following type(s) are allowed in the list + * {@link org.w3c.dom.Element } + * + * + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + return this.any; + } + +} diff --git a/test/javax/xml/bind/marshal/8036981/Main.java b/test/javax/xml/bind/marshal/8036981/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..aa92593489227144ec723e3166df37fdc729a5e2 --- /dev/null +++ b/test/javax/xml/bind/marshal/8036981/Main.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package testjaxbcontext; + +import javax.xml.bind.annotation.*; + +/** + *

    + * Java class for main complex type. + * + *

    + * The following schema fragment specifies the expected content contained within + * this class. + * + *

    + * <complexType name="main">
    + *   <complexContent>
    + *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
    + *       <sequence>
    + *         <element name="Root" type="{}Root"/>
    + *         <element name="Good" type="{}Good"/>
    + *       </sequence>
    + *     </restriction>
    + *   </complexContent>
    + * </complexType>
    + * 
    + * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "main", propOrder = { + "root", + "good" +}) +@XmlRootElement +public class Main { + + @XmlElement(name = "Root", required = true) + protected Root root; + @XmlElement(name = "Good", required = true) + protected Good good; + + /** + * Gets the value of the root property. + * + * @return possible object is {@link Root } + * + */ + public Root getRoot() { + return root; + } + + /** + * Sets the value of the root property. + * + * @param value allowed object is {@link Root } + * + */ + public void setRoot(Root value) { + this.root = value; + } + + /** + * Gets the value of the good property. + * + * @return possible object is {@link Good } + * + */ + public Good getGood() { + return good; + } + + /** + * Sets the value of the good property. + * + * @param value allowed object is {@link Good } + * + */ + public void setGood(Good value) { + this.good = value; + } + +} diff --git a/test/javax/xml/bind/marshal/8036981/ObjectFactory.java b/test/javax/xml/bind/marshal/8036981/ObjectFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..adb2ddf62175e7938323e59efc53af6e5b4195a1 --- /dev/null +++ b/test/javax/xml/bind/marshal/8036981/ObjectFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package testjaxbcontext; + +import javax.xml.bind.annotation.XmlRegistry; + +/** + * This object contains factory methods for each Java content interface and Java + * element interface generated in the generated package. + *

    + * An ObjectFactory allows you to programatically construct new instances of the + * Java representation for XML content. The Java representation of XML content + * can consist of schema derived interfaces and classes representing the binding + * of schema type definitions, element declarations and model groups. Factory + * methods for each of these are provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + /** + * Create a new ObjectFactory that can be used to create new instances of + * schema derived classes for package: generated + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link Root } + * + */ + public Root createRoot() { + return new Root(); + } + + /** + * Create an instance of {@link Good } + * + */ + public Good createGood() { + return new Good(); + } + + /** + * Create an instance of {@link Main } + * + */ + public Main createMain() { + return new Main(); + } + +} diff --git a/test/javax/xml/bind/marshal/8036981/Root.java b/test/javax/xml/bind/marshal/8036981/Root.java new file mode 100644 index 0000000000000000000000000000000000000000..85fff71963336c30621e7ac2b72f670f18f67663 --- /dev/null +++ b/test/javax/xml/bind/marshal/8036981/Root.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package testjaxbcontext; + +import javax.xml.bind.annotation.*; +import java.util.ArrayList; +import java.util.List; + +/** + *

    + * Java class for Root complex type. + * + *

    + * The following schema fragment specifies the expected content contained within + * this class. + * + *

    + * <complexType name="Root">
    + *   <complexContent>
    + *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
    + *       <sequence>
    + *         <any processContents='skip' maxOccurs="70"/>
    + *       </sequence>
    + *     </restriction>
    + *   </complexContent>
    + * </complexType>
    + * 
    + * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "Root", propOrder = { + "content" +}) +public class Root { + + @XmlMixed + @XmlAnyElement + protected List content; + + /** + * Gets the value of the content property. + * + *

    + * This accessor method returns a reference to the live list, not a + * snapshot. Therefore any modification you make to the returned list will + * be present inside the JAXB object. This is why there is not a + * set method for the content property. + * + *

    + * For example, to add a new item, do as follows: + *

    +     *    getContent().add(newItem);
    +     * 
    + * + * + *

    + * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } + * {@link String } + * + * + */ + public List getContent() { + if (content == null) { + content = new ArrayList(); + } + return this.content; + } + +} diff --git a/test/javax/xml/bind/marshal/8036981/Test.java b/test/javax/xml/bind/marshal/8036981/Test.java new file mode 100644 index 0000000000000000000000000000000000000000..beedce12e7958eadfa341990217ba0e6e3d43f26 --- /dev/null +++ b/test/javax/xml/bind/marshal/8036981/Test.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test Test.java + * @bug 8036981 + * @summary JAXB not preserving formatting during unmarshalling/marshalling + * @compile Good.java Main.java ObjectFactory.java Root.java + * @run main/othervm Test + */ + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import java.io.File; +import java.io.StringWriter; + +/** + * Test for marshalling and unmarshalling mixed and unmixed content + */ +public class Test { + + private static final String EXPECTED = "
    \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    "; + + public static void main(String[] args) throws Exception { + JAXBContext jc = JAXBContext.newInstance("testjaxbcontext"); + Unmarshaller u = jc.createUnmarshaller(); + Object result = u.unmarshal(new File(System.getProperty("test.src", ".") + "/test.xml")); + StringWriter sw = new StringWriter(); + Marshaller m = jc.createMarshaller(); + m.marshal(result, sw); + System.out.println("Expected:" + EXPECTED); + System.out.println("Observed:" + sw.toString()); + if (!EXPECTED.equals(sw.toString())) { + throw new Exception("Unmarshal/Marshal generates different content"); + } + } +} diff --git a/test/javax/xml/bind/marshal/8036981/test.xml b/test/javax/xml/bind/marshal/8036981/test.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d001a8ac9ee357e4f3d25a05892606ae99e7627 --- /dev/null +++ b/test/javax/xml/bind/marshal/8036981/test.xml @@ -0,0 +1,19 @@ + +
    + + + + + + + + + + + + + + + + +
    diff --git a/test/sun/invoke/util/ValueConversionsTest.java b/test/sun/invoke/util/ValueConversionsTest.java index 726e90d9dea059e26127abc356b8254af0e43d9d..483afb7625c28d550c0f2700232851f02c398117 100644 --- a/test/sun/invoke/util/ValueConversionsTest.java +++ b/test/sun/invoke/util/ValueConversionsTest.java @@ -25,11 +25,11 @@ package test.sun.invoke.util; import sun.invoke.util.ValueConversions; import sun.invoke.util.Wrapper; +import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.MethodHandle; import java.io.Serializable; import java.util.Arrays; -import java.util.Collections; import org.junit.Test; import static org.junit.Assert.*; @@ -37,24 +37,13 @@ import static org.junit.Assert.*; * @summary unit tests for value-type conversion utilities * @compile -XDignore.symbol.file ValueConversionsTest.java * @run junit/othervm test.sun.invoke.util.ValueConversionsTest - * @run junit/othervm - * -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.START_ARITY=250 - * test.sun.invoke.util.ValueConversionsTest */ -// This might take a while and burn lots of metadata: -// @run junit/othervm -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.EXHAUSTIVE=true test.sun.invoke.util.ValueConversionsTest - /** * * @author jrose */ public class ValueConversionsTest { - private static final Class CLASS = ValueConversionsTest.class; - private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40); - private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0); - private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE"); - @Test public void testUnbox() throws Throwable { testUnbox(false); @@ -66,9 +55,7 @@ public class ValueConversionsTest { } private void testUnbox(boolean doCast) throws Throwable { - //System.out.println("unbox"); for (Wrapper dst : Wrapper.values()) { - //System.out.println(dst); for (Wrapper src : Wrapper.values()) { testUnbox(doCast, dst, src); } @@ -78,6 +65,7 @@ public class ValueConversionsTest { private void testUnbox(boolean doCast, Wrapper dst, Wrapper src) throws Throwable { boolean expectThrow = !doCast && !dst.isConvertibleFrom(src); if (dst == Wrapper.OBJECT || src == Wrapper.OBJECT) return; // must have prims + if (dst == Wrapper.VOID || src == Wrapper.VOID ) return; // must have values if (dst == Wrapper.OBJECT) expectThrow = false; // everything (even VOID==null here) converts to OBJECT try { @@ -91,9 +79,9 @@ public class ValueConversionsTest { } MethodHandle unboxer; if (doCast) - unboxer = ValueConversions.unboxCast(dst.primitiveType()); + unboxer = ValueConversions.unboxCast(dst); else - unboxer = ValueConversions.unbox(dst.primitiveType()); + unboxer = ValueConversions.unboxWiden(dst); Object expResult = (box == null) ? dst.zero() : dst.wrap(box); Object result = null; switch (dst) { @@ -104,9 +92,7 @@ public class ValueConversionsTest { case CHAR: result = (char) unboxer.invokeExact(box); break; case BYTE: result = (byte) unboxer.invokeExact(box); break; case SHORT: result = (short) unboxer.invokeExact(box); break; - case OBJECT: result = (Object) unboxer.invokeExact(box); break; case BOOLEAN: result = (boolean) unboxer.invokeExact(box); break; - case VOID: result = null; unboxer.invokeExact(box); break; } if (expectThrow) { expResult = "(need an exception)"; @@ -123,25 +109,23 @@ public class ValueConversionsTest { @Test public void testBox() throws Throwable { - //System.out.println("box"); for (Wrapper w : Wrapper.values()) { - if (w == Wrapper.VOID) continue; // skip this; no unboxed form - //System.out.println(w); + if (w == Wrapper.VOID) continue; // skip this; no unboxed form + if (w == Wrapper.OBJECT) continue; // skip this; already unboxed for (int n = -5; n < 10; n++) { Object box = w.wrap(n); - MethodHandle boxer = ValueConversions.box(w.primitiveType()); + MethodHandle boxer = ValueConversions.boxExact(w); Object expResult = box; Object result = null; switch (w) { - case INT: result = boxer.invokeExact(/*int*/n); break; - case LONG: result = boxer.invokeExact((long)n); break; - case FLOAT: result = boxer.invokeExact((float)n); break; - case DOUBLE: result = boxer.invokeExact((double)n); break; - case CHAR: result = boxer.invokeExact((char)n); break; - case BYTE: result = boxer.invokeExact((byte)n); break; - case SHORT: result = boxer.invokeExact((short)n); break; - case OBJECT: result = boxer.invokeExact((Object)n); break; - case BOOLEAN: result = boxer.invokeExact((n & 1) != 0); break; + case INT: result = (Integer) boxer.invokeExact(/*int*/n); break; + case LONG: result = (Long) boxer.invokeExact((long)n); break; + case FLOAT: result = (Float) boxer.invokeExact((float)n); break; + case DOUBLE: result = (Double) boxer.invokeExact((double)n); break; + case CHAR: result = (Character) boxer.invokeExact((char)n); break; + case BYTE: result = (Byte) boxer.invokeExact((byte)n); break; + case SHORT: result = (Short) boxer.invokeExact((short)n); break; + case BOOLEAN: result = (Boolean) boxer.invokeExact((n & 1) != 0); break; } assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box), expResult, result); @@ -151,16 +135,14 @@ public class ValueConversionsTest { @Test public void testCast() throws Throwable { - //System.out.println("cast"); Class[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class }; Object[] objects = { new Object(), Boolean.FALSE, "hello", (Long)12L, (Integer)6 }; for (Class dst : types) { - MethodHandle caster = ValueConversions.cast(dst); - assertEquals(caster.type(), ValueConversions.identity().type()); + MethodHandle caster = ValueConversions.cast().bindTo(dst); + assertEquals(caster.type(), MethodHandles.identity(Object.class).type()); for (Object obj : objects) { Class src = obj.getClass(); boolean canCast = dst.isAssignableFrom(src); - //System.out.println("obj="+obj+" <: dst="+dst+(canCast ? " (OK)" : " (will fail)")); try { Object result = caster.invokeExact(obj); if (canCast) @@ -175,26 +157,13 @@ public class ValueConversionsTest { } } - @Test - public void testIdentity() throws Throwable { - //System.out.println("identity"); - MethodHandle id = ValueConversions.identity(); - Object expResult = "foo"; - Object result = id.invokeExact(expResult); - // compiler bug: ValueConversions.identity().invokeExact("bar"); - assertEquals(expResult, result); - } - @Test public void testConvert() throws Throwable { - //System.out.println("convert"); for (long tval = 0, ctr = 0;;) { if (++ctr > 99999) throw new AssertionError("too many test values"); - // next test value: - //System.out.println(Long.toHexString(tval)); // prints 3776 test patterns + // prints 3776 test patterns (3776 = 8*59*8) tval = nextTestValue(tval); if (tval == 0) { - //System.out.println("test value count = "+ctr); // 3776 = 8*59*8 break; // repeat } } @@ -205,15 +174,12 @@ public class ValueConversionsTest { } } static void testConvert(Wrapper src, Wrapper dst, long tval) throws Throwable { - //System.out.println(src+" => "+dst); + if (dst == Wrapper.OBJECT || src == Wrapper.OBJECT) return; // must have prims + if (dst == Wrapper.VOID || src == Wrapper.VOID ) return; // must have values boolean testSingleCase = (tval != 0); final long tvalInit = tval; MethodHandle conv = ValueConversions.convertPrimitive(src, dst); - MethodType convType; - if (src == Wrapper.VOID) - convType = MethodType.methodType(dst.primitiveType() /* , void */); - else - convType = MethodType.methodType(dst.primitiveType(), src.primitiveType()); + MethodType convType = MethodType.methodType(dst.primitiveType(), src.primitiveType()); assertEquals(convType, conv.type()); MethodHandle converter = conv.asType(conv.type().changeReturnType(Object.class)); for (;;) { @@ -229,9 +195,7 @@ public class ValueConversionsTest { case CHAR: result = converter.invokeExact((char)n); break; case BYTE: result = converter.invokeExact((byte)n); break; case SHORT: result = converter.invokeExact((short)n); break; - case OBJECT: result = converter.invokeExact((Object)n); break; case BOOLEAN: result = converter.invokeExact((n & 1) != 0); break; - case VOID: result = converter.invokeExact(); break; default: throw new AssertionError(); } assertEquals("(src,dst,n,testValue)="+Arrays.asList(src,dst,"0x"+Long.toHexString(n),testValue), @@ -269,169 +233,4 @@ public class ValueConversionsTest { } return tweakSign(ux); } - - @Test - public void testVarargsArray() throws Throwable { - //System.out.println("varargsArray"); - final int MIN = START_ARITY; - final int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added - for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) { - MethodHandle target = ValueConversions.varargsArray(nargs); - Object[] args = new Object[nargs]; - for (int i = 0; i < nargs; i++) - args[i] = "#"+i; - Object res = target.invokeWithArguments(args); - assertArrayEquals(args, (Object[])res); - } - } - - @Test - public void testVarargsReferenceArray() throws Throwable { - //System.out.println("varargsReferenceArray"); - testTypedVarargsArray(Object[].class); - testTypedVarargsArray(String[].class); - testTypedVarargsArray(Number[].class); - } - - @Test - public void testVarargsPrimitiveArray() throws Throwable { - //System.out.println("varargsPrimitiveArray"); - testTypedVarargsArray(int[].class); - testTypedVarargsArray(long[].class); - testTypedVarargsArray(byte[].class); - testTypedVarargsArray(boolean[].class); - testTypedVarargsArray(short[].class); - testTypedVarargsArray(char[].class); - testTypedVarargsArray(float[].class); - testTypedVarargsArray(double[].class); - } - - private static int nextArgCount(int nargs, int density, int MAX) { - if (EXHAUSTIVE) return nargs + 1; - if (nargs >= MAX) return Integer.MAX_VALUE; - int BOT = 20, TOP = MAX-5; - if (density < 10) { BOT = 10; MAX = TOP-2; } - if (nargs <= BOT || nargs >= TOP) { - ++nargs; - } else { - int bump = Math.max(1, 100 / density); - nargs += bump; - if (nargs > TOP) nargs = TOP; - } - return nargs; - } - - private void testTypedVarargsArray(Class arrayType) throws Throwable { - //System.out.println(arrayType.getSimpleName()); - Class elemType = arrayType.getComponentType(); - int MIN = START_ARITY; - int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added - int density = 3; - if (elemType == int.class || elemType == long.class) density = 7; - if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; } - for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) { - Object[] args = makeTestArray(elemType, nargs); - MethodHandle varargsArray = ValueConversions.varargsArray(arrayType, nargs); - MethodType vaType = varargsArray.type(); - assertEquals(arrayType, vaType.returnType()); - if (nargs != 0) { - assertEquals(elemType, vaType.parameterType(0)); - assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1)); - } - assertEquals(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType)), - vaType); - Object res = varargsArray.invokeWithArguments(args); - String resString = toArrayString(res); - assertEquals(Arrays.toString(args), resString); - - MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs); - MethodType stype = spreader.type(); - assert(stype == MethodType.methodType(arrayType, arrayType)); - if (nargs <= 5) { - // invoke target as a spreader also: - @SuppressWarnings("cast") - Object res2 = spreader.invokeWithArguments((Object)res); - String res2String = toArrayString(res2); - assertEquals(Arrays.toString(args), res2String); - // invoke the spreader on a generic Object[] array; check for error - try { - Object res3 = spreader.invokeWithArguments((Object)args); - String res3String = toArrayString(res3); - assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class)); - assertEquals(Arrays.toString(args), res3String); - } catch (ClassCastException ex) { - assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class)); - } - } - if (nargs == 0) { - // invoke spreader on null arglist - Object res3 = spreader.invokeWithArguments((Object)null); - String res3String = toArrayString(res3); - assertEquals(Arrays.toString(args), res3String); - } - } - } - - private static Object[] makeTestArray(Class elemType, int len) { - Wrapper elem = null; - if (elemType.isPrimitive()) - elem = Wrapper.forPrimitiveType(elemType); - else if (Wrapper.isWrapperType(elemType)) - elem = Wrapper.forWrapperType(elemType); - Object[] args = new Object[len]; - for (int i = 0; i < len; i++) { - Object arg = i * 100; - if (elem == null) { - if (elemType == String.class) - arg = "#"+arg; - arg = elemType.cast(arg); // just to make sure - } else { - switch (elem) { - case BOOLEAN: arg = (i % 3 == 0); break; - case CHAR: arg = 'a' + i; break; - case LONG: arg = (long)i * 1000_000_000; break; - case FLOAT: arg = (float)i / 100; break; - case DOUBLE: arg = (double)i / 1000_000; break; - } - arg = elem.cast(arg, elemType); - } - args[i] = arg; - } - //System.out.println(elemType.getName()+Arrays.toString(args)); - return args; - } - - private static String toArrayString(Object a) { - if (a == null) return "null"; - Class elemType = a.getClass().getComponentType(); - if (elemType == null) return a.toString(); - if (elemType.isPrimitive()) { - switch (Wrapper.forPrimitiveType(elemType)) { - case INT: return Arrays.toString((int[])a); - case BYTE: return Arrays.toString((byte[])a); - case BOOLEAN: return Arrays.toString((boolean[])a); - case SHORT: return Arrays.toString((short[])a); - case CHAR: return Arrays.toString((char[])a); - case FLOAT: return Arrays.toString((float[])a); - case LONG: return Arrays.toString((long[])a); - case DOUBLE: return Arrays.toString((double[])a); - } - } - return Arrays.toString((Object[])a); - } - - @Test - public void testVarargsList() throws Throwable { - //System.out.println("varargsList"); - final int MIN = START_ARITY; - final int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added - for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 7, MAX)) { - MethodHandle target = ValueConversions.varargsList(nargs); - Object[] args = new Object[nargs]; - for (int i = 0; i < nargs; i++) - args[i] = "#"+i; - Object res = target.invokeWithArguments(args); - assertEquals(Arrays.asList(args), res); - } - } } diff --git a/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java b/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java index 24397656a906c26949efe6fba5780f942d196fe3..558b2dabb041de17b537ec51f9c43cdebd8c7271 100644 --- a/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java +++ b/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,9 +143,12 @@ public class JvmstatCountersTest { String vmid = name.substring(0, name.indexOf("@")); System.out.println("vmid = " + vmid); VirtualMachine vm = VirtualMachine.attach(vmid); - String agent = vm.getSystemProperties().getProperty("java.home") + - File.separator + "lib" + File.separator + "management-agent.jar"; - vm.loadAgent(agent, "com.sun.management.jmxremote.port=0,com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false"); + Properties p = new Properties(); + p.put("com.sun.management.jmxremote.port", "0"); + p.put("com.sun.management.jmxremote.authenticate", "false"); + p.put("com.sun.management.jmxremote.ssl", "false"); + vm.startManagementAgent(p); + vm.startLocalManagementAgent(); vm.detach(); String localAddress2 = ConnectorAddressLink.importFrom(0); if (localAddress2 == null) { diff --git a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java index 6eecbda4d2291aa43b4d18e90570a5a80b216169..54173e6eff9ecf3c42dd6b223689c09c5455acc8 100644 --- a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java +++ b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,16 +79,6 @@ public class LocalManagementTest { return doTest("1", "-Dcom.sun.management.jmxremote"); } - private static boolean test2() throws Exception { - Path agentPath = findAgent(); - if (agentPath != null) { - String agent = agentPath.toString(); - return doTest("2", "-javaagent:" + agent); - } else { - return false; - } - } - /** * no args (blank) - manager should attach and start agent */ @@ -96,41 +86,6 @@ public class LocalManagementTest { return doTest("3", null); } - /** - * sanity check arguments to management-agent.jar - */ - private static boolean test4() throws Exception { - Path agentPath = findAgent(); - if (agentPath != null) { - ProcessBuilder builder = ProcessTools.createJavaProcessBuilder( - "-javaagent:" + agentPath.toString() + - "=com.sun.management.jmxremote.port=7775," + - "com.sun.management.jmxremote.authenticate=false," + - "com.sun.management.jmxremote.ssl=false", - "-cp", - TEST_CLASSPATH, - "TestApplication", - "-exit" - ); - - Process prc = null; - try { - prc = ProcessTools.startProcess( - "TestApplication", - builder - ); - int exitCode = prc.waitFor(); - return exitCode == 0; - } finally { - if (prc != null) { - prc.destroy(); - prc.waitFor(); - } - } - } - return false; - } - /** * use DNS-only name service */ @@ -138,27 +93,6 @@ public class LocalManagementTest { return doTest("5", "-Dsun.net.spi.namservice.provider.1=\"dns,sun\""); } - private static Path findAgent() { - FileSystem FS = FileSystems.getDefault(); - Path agentPath = FS.getPath( - TEST_JDK, "jre", "lib", "management-agent.jar" - ); - if (!isFileOk(agentPath)) { - agentPath = FS.getPath( - TEST_JDK, "lib", "management-agent.jar" - ); - } - if (!isFileOk(agentPath)) { - System.err.println("Can not locate management-agent.jar"); - return null; - } - return agentPath; - } - - private static boolean isFileOk(Path path) { - return Files.isRegularFile(path) && Files.isReadable(path); - } - private static boolean doTest(String testId, String arg) throws Exception { List args = new ArrayList<>(); args.add("-cp"); diff --git a/test/sun/management/jmxremote/bootstrap/TestManager.java b/test/sun/management/jmxremote/bootstrap/TestManager.java index 4495c2d07fe60e9b567dd1677b0650568171dfb5..76b43249df80480fb6057517d0cd389db833e0dc 100644 --- a/test/sun/management/jmxremote/bootstrap/TestManager.java +++ b/test/sun/management/jmxremote/bootstrap/TestManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,6 @@ import java.lang.management.RuntimeMXBean; import static java.lang.management.ManagementFactory.*; import java.net.Socket; import java.net.InetSocketAddress; -import java.io.File; import java.io.IOException; // Sun specific @@ -55,28 +54,8 @@ public class TestManager { * Starts the management agent in the target VM */ private static void startManagementAgent(String pid) throws IOException { - /* - * JAR file normally in ${java.home}/jre/lib but may be in ${java.home}/lib - * with development/non-images builds - */ - String home = System.getProperty("java.home"); - String agent = home + File.separator + "jre" + File.separator + "lib" - + File.separator + "management-agent.jar"; - File f = new File(agent); - if (!f.exists()) { - agent = home + File.separator + "lib" + File.separator + - "management-agent.jar"; - f = new File(agent); - if (!f.exists()) { - throw new RuntimeException("management-agent.jar missing"); - } - } - agent = f.getCanonicalPath(); - - System.out.println("Loading " + agent + " into target VM ..."); - try { - VirtualMachine.attach(pid).loadAgent(agent); + VirtualMachine.attach(pid).startLocalManagementAgent(); } catch (Exception x) { throw new IOException(x.getMessage()); } @@ -122,8 +101,7 @@ public class TestManager { if (agentPropLocalConnectorAddress == null && jvmstatLocalConnectorAddress == null) { - // No JMX Connector address so attach to VM, and load - // management-agent.jar + // No JMX Connector address so attach to VM, and start local agent startManagementAgent(pid); agentPropLocalConnectorAddress = (String) vm.getAgentProperties().get(LOCAL_CONNECTOR_ADDRESS_PROP); diff --git a/test/sun/management/jmxremote/startstop/JMXStartStopTest.java b/test/sun/management/jmxremote/startstop/JMXStartStopTest.java index cacb7087c27bb3c56d207b6769d47d399ab1c1a0..d9372448c500886242fa6b24fbed8e2b566cbc8d 100644 --- a/test/sun/management/jmxremote/startstop/JMXStartStopTest.java +++ b/test/sun/management/jmxremote/startstop/JMXStartStopTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,16 +31,13 @@ import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import javax.management.*; @@ -60,7 +57,6 @@ import jdk.testlibrary.JDKToolLauncher; * JCMD achieves the desired results */ public class JMXStartStopTest { - private static final String TEST_JDK = System.getProperty("test.jdk"); private static final String TEST_SRC = System.getProperty("test.src"); private static final boolean verbose = false; @@ -76,8 +72,8 @@ public class JMXStartStopTest { QueryExp query) throws Exception { - Set names = server.queryNames(pattern,query); - for (Iterator i=names.iterator(); i.hasNext(); ) { + Set names = server.queryNames(pattern,query); + for (Iterator i = names.iterator(); i.hasNext(); ) { ObjectName name = (ObjectName)i.next(); MBeanInfo info = server.getMBeanInfo(name); dbg_print("Got MBean: " + name); @@ -87,7 +83,7 @@ public class JMXStartStopTest { continue; for (MBeanAttributeInfo attr : attrs) { if (attr.isReadable()) { - Object o = server.getAttribute(name, attr.getName()); + server.getAttribute(name, attr.getName()); } } } @@ -108,9 +104,8 @@ public class JMXStartStopTest { } JMXServiceURL url = new JMXServiceURL(jmxUrlStr); - Map m = new HashMap(); - JMXConnector c = JMXConnectorFactory.connect(url,m); + JMXConnector c = JMXConnectorFactory.connect(url, null); MBeanServerConnection conn = c.getMBeanServerConnection(); ObjectName pattern = new ObjectName("java.lang:type=Memory,*"); @@ -180,9 +175,8 @@ public class JMXStartStopTest { port); JMXServiceURL url = new JMXServiceURL(jmxUrlStr); - Map m = new HashMap(); - JMXConnector c = JMXConnectorFactory.connect(url,m); + JMXConnector c = JMXConnectorFactory.connect(url, null); MBeanServerConnection conn = c.getMBeanServerConnection(); ObjectName pattern = new ObjectName("java.lang:type=Memory,*"); @@ -273,25 +267,6 @@ public class JMXStartStopTest { } } - /** - * Retrieves the PID of the test application using JCMD - * @return The PID of the test application - * @throws InterruptedException - * @throws IOException - */ - private static String getPID() throws InterruptedException, IOException { - final AtomicReference pid = new AtomicReference<>(); - jcmd( - null, - line -> { - if (line.endsWith("JMXStartStopDoSomething")) { - pid.set(line.split(" ")[0]); - } - } - ); - return pid.get(); - } - private static class Something { private Process p; private final ProcessBuilder pb; @@ -434,7 +409,7 @@ public class JMXStartStopTest { private static final int port1 = 50234; private static final int port2 = 50235; - private static void test_01() throws Exception { + static void test_01() throws Exception { // Run an app with JMX enabled stop it and // restart on other port @@ -459,7 +434,7 @@ public class JMXStartStopTest { } } - private static void test_02() throws Exception { + static void test_02() throws Exception { // Run an app without JMX enabled // start JMX by jcmd @@ -478,7 +453,7 @@ public class JMXStartStopTest { } } - private static void test_03() throws Exception { + static void test_03() throws Exception { // Run an app without JMX enabled // start JMX by jcmd on one port than on other one @@ -507,7 +482,7 @@ public class JMXStartStopTest { } } - private static void test_04() throws Exception { + static void test_04() throws Exception { // Run an app without JMX enabled // start JMX by jcmd on one port, specify rmi port explicitly @@ -528,7 +503,7 @@ public class JMXStartStopTest { } } - private static void test_05() throws Exception { + static void test_05() throws Exception { // Run an app without JMX enabled, it will enable local server // but should leave remote server disabled @@ -545,7 +520,7 @@ public class JMXStartStopTest { } } - private static void test_06() throws Exception { + static void test_06() throws Exception { // Run an app without JMX enabled // start JMX by jcmd on one port, specify rmi port explicitly // attempt to start it again @@ -569,7 +544,7 @@ public class JMXStartStopTest { final boolean[] checks = new boolean[3]; jcmd( line -> { - if (line.equals("java.lang.RuntimeException: Invalid agent state")) { + if (line.contains("java.lang.RuntimeException: Invalid agent state")) { checks[0] = true; } }, @@ -580,7 +555,7 @@ public class JMXStartStopTest { jcmd( line -> { - if (line.equals("java.lang.RuntimeException: Invalid agent state")) { + if (line.contains("java.lang.RuntimeException: Invalid agent state")) { checks[1] = true; } }, @@ -648,7 +623,7 @@ public class JMXStartStopTest { } } - private static void test_08() throws Exception { + static void test_08() throws Exception { // Run an app with JMX enabled and with some properties set // in command line. // stop JMX agent and then start it again with different property values @@ -682,7 +657,7 @@ public class JMXStartStopTest { } } - private static void test_09() throws Exception { + static void test_09() throws Exception { // Run an app with JMX enabled and with some properties set // in command line. // stop JMX agent and then start it again with different property values @@ -718,7 +693,7 @@ public class JMXStartStopTest { } } - private static void test_10() throws Exception { + static void test_10() throws Exception { // Run an app with JMX enabled and with some properties set // in command line. // stop JMX agent and then start it again with different property values @@ -754,7 +729,7 @@ public class JMXStartStopTest { } } - private static void test_11() throws Exception { + static void test_11() throws Exception { // Run an app with JMX enabled // stop remote agent // make sure local agent is not affected @@ -775,7 +750,7 @@ public class JMXStartStopTest { } } - private static void test_12() throws Exception { + static void test_12() throws Exception { // Run an app with JMX disabled // start local agent only @@ -793,28 +768,4 @@ public class JMXStartStopTest { s.stop(); } } - - private static void test_13() throws Exception { - // Run an app with -javaagent make sure it works as expected - - // system properties are ignored - - System.out.println("**** Test thirteen ****"); - - String agent = TEST_JDK + "/jre/lib/management-agent.jar"; - if (!new File(agent).exists()) { - agent = TEST_JDK + "/lib/management-agent.jar"; - } - - Something s = doSomething("test_14", - "-javaagent:" + agent + "=com.sun.management.jmxremote.port=" + - port1 + ",com.sun.management.jmxremote.authenticate=false", - "-Dcom.sun.management.jmxremote.ssl=false" - ); - - try { - testNoConnect(port1); - } finally { - s.stop(); - } - } } diff --git a/test/sun/text/resources/LocaleData b/test/sun/text/resources/LocaleData index 9365989c27d1f0a91f6644254534e55c6fe478f3..9dca93b6e02b7d618950888ed963cbf797eb0c76 100644 --- a/test/sun/text/resources/LocaleData +++ b/test/sun/text/resources/LocaleData @@ -7699,3 +7699,6 @@ FormatData/es_EC/TimePatterns/3=H:mm # bug 8037343 FormatData/es_DO/DatePatterns/2=dd/MM/yyyy FormatData/es_DO/DatePatterns/3=dd/MM/yy + +# bug 8055222 +CurrencyNames/lt_LT/EUR=\u20AC diff --git a/test/sun/text/resources/LocaleDataTest.java b/test/sun/text/resources/LocaleDataTest.java index e7245e655f0a95ab478933531525ac00012a41f2..e2cea1ab153034af4246600a2d9ae116616e60a6 100644 --- a/test/sun/text/resources/LocaleDataTest.java +++ b/test/sun/text/resources/LocaleDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495 * 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509 * 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 7090826 - * 8017142 8037343 + * 8017142 8037343 8055222 * @summary Verify locale data * */ diff --git a/test/sun/tools/jrunscript/jrunscriptTest.sh b/test/sun/tools/jrunscript/jrunscriptTest.sh index 921524be9e0379cd1d193b19672a0c0fc97e4106..ab4cb16dc134ecf4c796faace6fe3e20b297cc12 100644 --- a/test/sun/tools/jrunscript/jrunscriptTest.sh +++ b/test/sun/tools/jrunscript/jrunscriptTest.sh @@ -42,7 +42,7 @@ fi rm -f jrunscriptTest.out 2>/dev/null ${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn > jrunscriptTest.out 2>&1 < # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. -# This data is by no means authoritative; if you think you know better, +# This file is by no means authoritative; if you think you know better, # go ahead and edit the file (and please send any changes to -# tz@iana.org for general use in the future). +# tz@iana.org for general use in the future). For more, please see +# the file CONTRIBUTING in the tz distribution. # From Paul Eggert (2013-02-21): # @@ -49,8 +49,8 @@ # I found in the UCLA library. # # For data circa 1899, a common source is: -# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94 -# . +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94. +# http://www.jstor.org/stable/1774359 # # A reliable and entertaining source about time zones is # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997). @@ -58,13 +58,13 @@ # Previous editions of this database used WAT, CAT, SAT, and EAT # for +0:00 through +3:00, respectively, # but Mark R V Murray reports that -# `SAST' is the official abbreviation for +2:00 in the country of South Africa, -# `CAT' is commonly used for +2:00 in countries north of South Africa, and -# `WAT' is probably the best name for +1:00, as the common phrase for -# the area that includes Nigeria is ``West Africa''. -# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference. +# 'SAST' is the official abbreviation for +2:00 in the country of South Africa, +# 'CAT' is commonly used for +2:00 in countries north of South Africa, and +# 'WAT' is probably the best name for +1:00, as the common phrase for +# the area that includes Nigeria is "West Africa". +# He has heard of "Western Sahara Time" for +0:00 but can find no reference. # -# To make things confusing, `WAT' seems to have been used for -1:00 long ago; +# To make things confusing, 'WAT' seems to have been used for -1:00 long ago; # I'd guess that this was because people needed _some_ name for -1:00, # and at the time, far west Africa was the only major land area in -1:00. # This usage is now obsolete, as the last use of -1:00 on the African @@ -77,7 +77,7 @@ # 2:00 SAST South Africa Standard Time # and Murray suggests the following abbreviation: # 1:00 WAT West Africa Time -# I realize that this leads to `WAT' being used for both -1:00 and 1:00 +# I realize that this leads to 'WAT' being used for both -1:00 and 1:00 # for times before 1976, but this is the best I can think of # until we get more information. # @@ -117,9 +117,9 @@ Rule Algeria 1980 only - Oct 31 2:00 0 - # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's # more precise 0:09:21. # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01 - 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time - 0:00 Algeria WE%sT 1940 Feb 25 2:00 +Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01 + 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time + 0:00 Algeria WE%sT 1940 Feb 25 2:00 1:00 Algeria CE%sT 1946 Oct 7 0:00 - WET 1956 Jan 29 1:00 - CET 1963 Apr 14 @@ -129,18 +129,8 @@ Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01 1:00 - CET # Angola -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Luanda 0:52:56 - LMT 1892 - 0:52:04 - AOT 1911 May 26 # Angola Time - 1:00 - WAT - # Benin -# Whitman says they switched to 1:00 in 1946, not 1934; -# go with Shanks & Pottenger. -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Porto-Novo 0:10:28 - LMT 1912 - 0:00 - GMT 1934 Feb 26 - 1:00 - WAT +# See Africa/Lagos. # Botswana # From Paul Eggert (2013-02-21): @@ -149,14 +139,12 @@ Zone Africa/Porto-Novo 0:10:28 - LMT 1912 # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Gaborone 1:43:40 - LMT 1885 1:30 - SAST 1903 Mar - 2:00 - CAT 1943 Sep 19 2:00 - 2:00 1:00 CAST 1944 Mar 19 2:00 + 2:00 - CAT 1943 Sep 19 2:00 + 2:00 1:00 CAST 1944 Mar 19 2:00 2:00 - CAT # Burkina Faso -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Ouagadougou -0:06:04 - LMT 1912 - 0:00 - GMT +# See Africa/Abidjan. # Burundi # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -164,52 +152,60 @@ Zone Africa/Bujumbura 1:57:28 - LMT 1890 2:00 - CAT # Cameroon -# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger. -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Douala 0:38:48 - LMT 1912 - 1:00 - WAT +# See Africa/Lagos. # Cape Verde +# +# Shanks gives 1907 for the transition to CVT. +# Perhaps the 1911-05-26 Portuguese decree +# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf +# merely made it official? +# # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Atlantic/Cape_Verde -1:34:04 - LMT 1907 # Praia +Zone Atlantic/Cape_Verde -1:34:04 - LMT 1907 # Praia -2:00 - CVT 1942 Sep -2:00 1:00 CVST 1945 Oct 15 - -2:00 - CVT 1975 Nov 25 2:00 + -2:00 - CVT 1975 Nov 25 2:00 -1:00 - CVT # Central African Republic -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Bangui 1:14:20 - LMT 1912 - 1:00 - WAT +# See Africa/Lagos. # Chad # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Ndjamena 1:00:12 - LMT 1912 +Zone Africa/Ndjamena 1:00:12 - LMT 1912 # N'Djamena 1:00 - WAT 1979 Oct 14 1:00 1:00 WAST 1980 Mar 8 1:00 - WAT # Comoros # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Indian/Comoro 2:53:04 - LMT 1911 Jul # Moroni, Gran Comoro +Zone Indian/Comoro 2:53:04 - LMT 1911 Jul # Moroni, Gran Comoro 3:00 - EAT -# Democratic Republic of Congo +# Democratic Republic of the Congo # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Kinshasa 1:01:12 - LMT 1897 Nov 9 - 1:00 - WAT Zone Africa/Lubumbashi 1:49:52 - LMT 1897 Nov 9 2:00 - CAT +# The above is for the eastern part; see Africa/Lagos for the western part. # Republic of the Congo -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Brazzaville 1:01:08 - LMT 1912 - 1:00 - WAT +# See Africa/Lagos. -# Cote D'Ivoire +# Côte d'Ivoire / Ivory Coast # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Abidjan -0:16:08 - LMT 1912 0:00 - GMT +Link Africa/Abidjan Africa/Bamako # Mali +Link Africa/Abidjan Africa/Banjul # Gambia +Link Africa/Abidjan Africa/Conakry # Guinea +Link Africa/Abidjan Africa/Dakar # Senegal +Link Africa/Abidjan Africa/Freetown # Sierra Leone +Link Africa/Abidjan Africa/Lome # Togo +Link Africa/Abidjan Africa/Nouakchott # Mauritania +Link Africa/Abidjan Africa/Ouagadougou # Burkina Faso +Link Africa/Abidjan Africa/Sao_Tome # São Tomé and Príncipe +Link Africa/Abidjan Atlantic/St_Helena # St Helena # Djibouti # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -254,30 +250,26 @@ Rule Egypt 1990 1994 - May 1 1:00 1:00 S # Egyptians would approve the cancellation." # # Egypt to cancel daylight saving time -# # http://www.almasryalyoum.com/en/node/407168 -# # or -# # http://www.worldtimezone.com/dst_news/dst_news_egypt04.html -# Rule Egypt 1995 2010 - Apr lastFri 0:00s 1:00 S -Rule Egypt 1995 2005 - Sep lastThu 23:00s 0 - +Rule Egypt 1995 2005 - Sep lastThu 24:00 0 - # From Steffen Thorsen (2006-09-19): # The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports: # Egypt will turn back clocks by one hour at the midnight of Thursday # after observing the daylight saving time since May. # http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf -Rule Egypt 2006 only - Sep 21 23:00s 0 - +Rule Egypt 2006 only - Sep 21 24:00 0 - # From Dirk Losch (2007-08-14): # I received a mail from an airline which says that the daylight # saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07. -# From Jesper Norgaard Welen (2007-08-15): [The following agree:] +# From Jesper Nørgaard Welen (2007-08-15): [The following agree:] # http://www.nentjes.info/Bill/bill5.htm # http://www.timeanddate.com/worldclock/city.html?n=53 # From Steffen Thorsen (2007-09-04): The official information...: # http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm -Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 - +Rule Egypt 2007 only - Sep Thu>=1 24:00 0 - # From Abdelrahman Hassan (2007-09-06): # Due to the Hijri (lunar Islamic calendar) year being 11 days shorter # than the year of the Gregorian calendar, Ramadan shifts earlier each @@ -311,15 +303,9 @@ Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 - # # timeanddate[2] and another site I've found[3] also support that. # -# [1] -# https://bugzilla.redhat.com/show_bug.cgi?id=492263 -# -# [2] -# http://www.timeanddate.com/worldclock/clockchange.html?n=53 -# -# [3] -# http://wwp.greenwichmeantime.com/time-zone/africa/egypt/ -# +# [1] https://bugzilla.redhat.com/show_bug.cgi?id=492263 +# [2] http://www.timeanddate.com/worldclock/clockchange.html?n=53 +# [3] http://wwp.greenwichmeantime.com/time-zone/africa/egypt/ # From Arthur David Olson (2009-04-20): # In 2009 (and for the next several years), Ramadan ends before the fourth @@ -329,14 +315,10 @@ Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 - # From Steffen Thorsen (2009-08-11): # We have been able to confirm the August change with the Egyptian Cabinet # Information and Decision Support Center: -# # http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html -# # # The Middle East News Agency -# # http://www.mena.org.eg/index.aspx -# # also reports "Egypt starts winter time on August 21" # today in article numbered "71, 11/08/2009 12:25 GMT." # Only the title above is available without a subscription to their service, @@ -344,19 +326,14 @@ Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 - # (at least today). # From Alexander Krivenyshev (2010-07-20): -# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has +# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has # decided that Daylight Saving Time will not be used in Egypt during # Ramadan. # # Arabic translation: -# "Clocks to go back during Ramadan--and then forward again" -# +# "Clocks to go back during Ramadan - and then forward again" # http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again -# -# or -# # http://www.worldtimezone.com/dst_news/dst_news_egypt02.html -# # From Ahmad El-Dardiry (2014-05-07): # Egypt is to change back to Daylight system on May 15 @@ -365,46 +342,77 @@ Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 - # From Gunther Vermier (2015-05-13): # our Egypt office confirms that the change will be at 15 May "midnight" (24:00) -# From Paul Eggert (2014-05-13): +# From Imed Chihi (2014-06-04): +# We have finally "located" a precise official reference about the DST changes +# in Egypt. The Ministers Cabinet decision is explained at +# http://www.cabinet.gov.eg/Media/CabinetMeetingsDetails.aspx?id=347 ... +# [T]his (Arabic) site is not accessible outside Egypt, but the page ... +# translates into: "With regard to daylight saving time, it is scheduled to +# take effect at exactly twelve o'clock this evening, Thursday, 15 MAY 2014, +# to be suspended by twelve o'clock on the evening of Thursday, 26 JUN 2014, +# and re-established again at the end of the month of Ramadan, at twelve +# o'clock on the evening of Thursday, 31 JUL 2014." This statement has been +# reproduced by other (more accessible) sites[, e.g.,]... +# http://elgornal.net/news/news.aspx?id=4699258 + +# From Paul Eggert (2014-06-04): # Sarah El Deeb and Lee Keath of AP report that the Egyptian government says # the change is because of blackouts in Cairo, even though Ahram Online (cited -# above) says DST had no affect on electricity consumption. The AP story says -# DST will not be observed during Ramadan. There is no information about when -# DST will end. See: +# above) says DST had no affect on electricity consumption. There is +# no information about when DST will end this fall. See: # http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833 # -# For now, guess that later transitions will use 2010's rules, and that -# Egypt will agree with Morocco (see below) about the date Ramadan starts and -# ends, though (unlike Morocco) it will switch at 00:00 standard time. In -# Egypt the spring-forward transitions are removed for 2020-2022, when the -# guessed spring-forward date falls during the estimated Ramadan, and all -# transitions removed for 2023-2038, where the estimated Ramadan falls entirely -# outside the guessed daylight-saving time. Ramadan intrudes on the guessed -# DST starting in 2039, but that's beyond our somewhat-arbitrary cutoff. - -Rule Egypt 2008 only - Aug lastThu 23:00s 0 - -Rule Egypt 2009 only - Aug 20 23:00s 0 - -Rule Egypt 2010 only - Aug 11 0:00 0 - -Rule Egypt 2010 only - Sep 10 0:00 1:00 S -Rule Egypt 2010 only - Sep lastThu 23:00s 0 - +# For now, guess that later spring and fall transitions will use +# 2010's rules, and guess that Egypt will switch to standard time at +# 24:00 the last Thursday before Ramadan, and back to DST at 00:00 the +# first Friday after Ramadan. To implement this, +# transition dates for 2015 through 2037 were determined by running +# the following program under GNU Emacs 24.3, with the results integrated +# by hand into the table below. Ramadan again intrudes on the guessed +# DST starting in 2038, but that's beyond our somewhat-arbitrary cutoff. +# (let ((islamic-year 1436)) +# (while (< islamic-year 1460) +# (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year))) +# (b (calendar-islamic-to-absolute (list 10 1 islamic-year))) +# (friday 5)) +# (while (/= friday (mod a 7)) +# (setq a (1- a))) +# (while (/= friday (mod b 7)) +# (setq b (1+ b))) +# (setq a (1- a)) +# (setq b (1- b)) +# (setq a (calendar-gregorian-from-absolute a)) +# (setq b (calendar-gregorian-from-absolute b)) +# (insert +# (format +# (concat "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t0\t-\n" +# "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t1:00\tS\n") +# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) +# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) +# (setq islamic-year (+ 1 islamic-year)))) +Rule Egypt 2008 only - Aug lastThu 24:00 0 - +Rule Egypt 2009 only - Aug 20 24:00 0 - +Rule Egypt 2010 only - Aug 10 24:00 0 - +Rule Egypt 2010 only - Sep 9 24:00 1:00 S +Rule Egypt 2010 only - Sep lastThu 24:00 0 - Rule Egypt 2014 only - May 15 24:00 1:00 S -Rule Egypt 2014 only - Jun 29 0:00s 0 - -Rule Egypt 2014 only - Jul 29 0:00s 1:00 S -Rule Egypt 2014 max - Sep lastThu 23:00s 0 - +Rule Egypt 2014 only - Jun 26 24:00 0 - +Rule Egypt 2014 only - Jul 31 24:00 1:00 S +Rule Egypt 2014 max - Sep lastThu 24:00 0 - Rule Egypt 2015 2019 - Apr lastFri 0:00s 1:00 S -Rule Egypt 2015 only - Jun 18 0:00s 0 - -Rule Egypt 2015 only - Jul 18 0:00s 1:00 S -Rule Egypt 2016 only - Jun 7 0:00s 0 - -Rule Egypt 2016 only - Jul 7 0:00s 1:00 S -Rule Egypt 2017 only - May 27 0:00s 0 - -Rule Egypt 2017 only - Jun 26 0:00s 1:00 S -Rule Egypt 2018 only - May 16 0:00s 0 - -Rule Egypt 2018 only - Jun 15 0:00s 1:00 S -Rule Egypt 2019 only - May 6 0:00s 0 - -Rule Egypt 2019 only - Jun 5 0:00s 1:00 S -Rule Egypt 2020 only - May 24 0:00s 1:00 S -Rule Egypt 2021 only - May 13 0:00s 1:00 S -Rule Egypt 2022 only - May 3 0:00s 1:00 S +Rule Egypt 2015 only - Jun 11 24:00 0 - +Rule Egypt 2015 only - Jul 23 24:00 1:00 S +Rule Egypt 2016 only - Jun 2 24:00 0 - +Rule Egypt 2016 only - Jul 7 24:00 1:00 S +Rule Egypt 2017 only - May 25 24:00 0 - +Rule Egypt 2017 only - Jun 29 24:00 1:00 S +Rule Egypt 2018 only - May 10 24:00 0 - +Rule Egypt 2018 only - Jun 14 24:00 1:00 S +Rule Egypt 2019 only - May 2 24:00 0 - +Rule Egypt 2019 only - Jun 6 24:00 1:00 S +Rule Egypt 2020 only - May 28 24:00 1:00 S +Rule Egypt 2021 only - May 13 24:00 1:00 S +Rule Egypt 2022 only - May 5 24:00 1:00 S Rule Egypt 2023 max - Apr lastFri 0:00s 1:00 S # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -412,60 +420,63 @@ Zone Africa/Cairo 2:05:09 - LMT 1900 Oct 2:00 Egypt EE%sT # Equatorial Guinea -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Malabo 0:35:08 - LMT 1912 - 0:00 - GMT 1963 Dec 15 - 1:00 - WAT +# See Africa/Lagos. # Eritrea # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Asmara 2:35:32 - LMT 1870 - 2:35:32 - AMT 1890 # Asmara Mean Time - 2:35:20 - ADMT 1936 May 5 # Adis Dera MT + 2:35:32 - AMT 1890 # Asmara Mean Time + 2:35:20 - ADMT 1936 May 5 # Adis Dera MT 3:00 - EAT # Ethiopia -# From Paul Eggert (2006-03-22): -# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones -# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890. -# We'll guess that 38E50 is for Adis Dera. +# From Paul Eggert (2014-07-31): +# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a +# 12-hour clock starting at our 06:00, so their "8 o'clock" is our +# 02:00 or 14:00. Keep this in mind when you ask the time in Amharic. +# +# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time +# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in +# 1890, and that they switched to 3:00 on 1936-05-05. Perhaps 38E50 +# was for Adis Dera. Quite likely the Shanks data entries are wrong +# anyway. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Addis_Ababa 2:34:48 - LMT 1870 - 2:35:20 - ADMT 1936 May 5 # Adis Dera MT + 2:35:20 - ADMT 1936 May 5 # Adis Dera MT 3:00 - EAT # Gabon -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Libreville 0:37:48 - LMT 1912 - 1:00 - WAT +# See Africa/Lagos. # Gambia -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Banjul -1:06:36 - LMT 1912 - -1:06:36 - BMT 1935 # Banjul Mean Time - -1:00 - WAT 1964 - 0:00 - GMT +# See Africa/Abidjan. # Ghana # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -# Whitman says DST was observed from 1931 to ``the present''; -# go with Shanks & Pottenger. -Rule Ghana 1936 1942 - Sep 1 0:00 0:20 GHST -Rule Ghana 1936 1942 - Dec 31 0:00 0 GMT +# Whitman says DST was observed from 1931 to "the present"; +# Shanks & Pottenger say 1936 to 1942; +# and September 1 to January 1 is given by: +# Scott Keltie J, Epstein M (eds), The Statesman's Year-Book, +# 57th ed. Macmillan, London (1920), OCLC 609408015, pp xxviii. +# For lack of better info, assume DST was observed from 1920 to 1942. +Rule Ghana 1920 1942 - Sep 1 0:00 0:20 GHST +Rule Ghana 1920 1942 - Dec 31 0:00 0 GMT # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Accra -0:00:52 - LMT 1918 0:00 Ghana %s # Guinea -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Conakry -0:54:52 - LMT 1912 - 0:00 - GMT 1934 Feb 26 - -1:00 - WAT 1960 - 0:00 - GMT +# See Africa/Abidjan. # Guinea-Bissau +# +# Shanks gives 1911-05-26 for the transition to WAT, +# evidently confusing the date of the Portuguese decree +# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf +# with the date that it took effect, namely 1912-01-01. +# # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Bissau -1:02:20 - LMT 1911 May 26 +Zone Africa/Bissau -1:02:20 - LMT 1912 Jan 1 -1:00 - WAT 1975 0:00 - GMT @@ -480,8 +491,8 @@ Zone Africa/Nairobi 2:27:16 - LMT 1928 Jul # Lesotho # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Maseru 1:50:00 - LMT 1903 Mar - 2:00 - SAST 1943 Sep 19 2:00 - 2:00 1:00 SAST 1944 Mar 19 2:00 + 2:00 - SAST 1943 Sep 19 2:00 + 2:00 1:00 SAST 1944 Mar 19 2:00 2:00 - SAST # Liberia @@ -549,11 +560,11 @@ Zone Africa/Tripoli 0:52:44 - LMT 1920 2:00 - EET 1982 1:00 Libya CE%sT 1990 May 4 # The 1996 and 1997 entries are from Shanks & Pottenger; -# the IATA SSIM data contain some obvious errors. +# the IATA SSIM data entries contain some obvious errors. 2:00 - EET 1996 Sep 30 1:00 Libya CE%sT 1997 Oct 4 - 2:00 - EET 2012 Nov 10 2:00 - 1:00 Libya CE%sT 2013 Oct 25 2:00 + 2:00 - EET 2012 Nov 10 2:00 + 1:00 Libya CE%sT 2013 Oct 25 2:00 2:00 - EET # Madagascar @@ -569,18 +580,8 @@ Zone Africa/Blantyre 2:20:00 - LMT 1903 Mar 2:00 - CAT # Mali -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Bamako -0:32:00 - LMT 1912 - 0:00 - GMT 1934 Feb 26 - -1:00 - WAT 1960 Jun 20 - 0:00 - GMT - # Mauritania -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Nouakchott -1:03:48 - LMT 1912 - 0:00 - GMT 1934 Feb 26 - -1:00 - WAT 1960 Nov 28 - 0:00 - GMT +# See Africa/Abidjan. # Mauritius @@ -604,9 +605,7 @@ Zone Africa/Nouakchott -1:03:48 - LMT 1912 # From Steffen Thorsen (2008-07-10): # According to -# # http://www.lexpress.mu/display_article.php?news_id=111216 -# # (in French), Mauritius will start and end their DST a few days earlier # than previously announced (2008-11-01 to 2009-03-31). The new start # date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time @@ -621,22 +620,17 @@ Zone Africa/Nouakchott -1:03:48 - LMT 1912 # From Alex Krivenyshev (2008-07-11): # Seems that English language article "The revival of daylight saving -# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally +# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally # published on Monday, June 30, 2008... # # I guess that article in French "Le gouvernement avance l'introduction -# de l'heure d'ete" stating that DST in Mauritius starting on October 26 -# and ending on March 27, 2009 is the most recent one. -# ... -# +# de l'heure d'été" stating that DST in Mauritius starting on October 26 +# and ending on March 27, 2009 is the most recent one.... # http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html -# # From Riad M. Hossen Ally (2008-08-03): # The Government of Mauritius weblink -# # http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD -# # Cabinet Decision of July 18th, 2008 states as follows: # # 4. ...Cabinet has agreed to the introduction into the National Assembly @@ -646,33 +640,25 @@ Zone Africa/Nouakchott -1:03:48 - LMT 1912 # States of America. It will start at two o'clock in the morning on the # last Sunday of October and will end at two o'clock in the morning on # the last Sunday of March the following year. The summer time for the -# year 2008 - 2009 will, therefore, be effective as from 26 October 2008 +# year 2008-2009 will, therefore, be effective as from 26 October 2008 # and end on 29 March 2009. # From Ed Maste (2008-10-07): # THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the # beginning / ending of summer time is 2 o'clock standard time in the # morning of the last Sunday of October / last Sunday of March. -# # http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf -# # From Steffen Thorsen (2009-06-05): # According to several sources, Mauritius will not continue to observe # DST the coming summer... # # Some sources, in French: -# # http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB -# -# # http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints- -# # # Our wrap-up: -# # http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html -# # From Arthur David Olson (2009-07-11): # The "mauritius-dst-will-not-repeat" wrapup includes this: @@ -685,18 +671,18 @@ Rule Mauritius 1983 only - Mar 21 0:00 0 - Rule Mauritius 2008 only - Oct lastSun 2:00 1:00 S Rule Mauritius 2009 only - Mar lastSun 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis +Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis 4:00 Mauritius MU%sT # Mauritius Time # Agalega Is, Rodriguez # no information; probably like Indian/Mauritius # Mayotte # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou +Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou 3:00 - EAT # Morocco -# See the `europe' file for Spanish Morocco (Africa/Ceuta). +# See the 'europe' file for Spanish Morocco (Africa/Ceuta). # From Alex Krivenyshev (2008-05-09): # Here is an article that Morocco plan to introduce Daylight Saving Time between @@ -704,60 +690,44 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # # "... Morocco is to save energy by adjusting its clock during summer so it will # be one hour ahead of GMT between 1 June and 27 September, according to -# Communication Minister and Gov ernment Spokesman, Khalid Naciri...." +# Communication Minister and Government Spokesman, Khalid Naciri...." # -# # http://www.worldtimezone.net/dst_news/dst_news_morocco01.html -# -# OR -# # http://en.afrik.com/news11892.html -# # From Alex Krivenyshev (2008-05-09): -# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse: -# +# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe +# Presse: # http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view -# # # Morocco shifts to daylight time on June 1st through September 27, Govt. # spokesman. # From Patrice Scattolin (2008-05-09): # According to this article: -# # http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html -# -# (and republished here: -# -# http://www.actu.ma/heure-dete-comment_i127896_0.html -# -# ) -# the changes occurs at midnight: -# -# saturday night may 31st at midnight (which in french is to be -# intrepreted as the night between saturday and sunday) -# sunday night the 28th at midnight -# -# Seeing that the 28th is monday, I am guessing that she intends to say -# the midnight of the 28th which is the midnight between sunday and -# monday, which jives with other sources that say that it's inclusive -# june1st to sept 27th. +# (and republished here: ) +# the changes occur at midnight: +# +# Saturday night May 31st at midnight (which in French is to be +# interpreted as the night between Saturday and Sunday) +# Sunday night the 28th at midnight +# +# Seeing that the 28th is Monday, I am guessing that she intends to say +# the midnight of the 28th which is the midnight between Sunday and +# Monday, which jives with other sources that say that it's inclusive +# June 1st to Sept 27th. # # The decision was taken by decree *2-08-224 *but I can't find the decree # published on the web. # # It's also confirmed here: -# # http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm -# -# on a government portal as being between june 1st and sept 27th (not yet -# posted in english). +# on a government portal as being between June 1st and Sept 27th (not yet +# posted in English). # -# The following google query will generate many relevant hits: -# +# The following Google query will generate many relevant hits: # http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search -# # From Steffen Thorsen (2008-08-27): # Morocco will change the clocks back on the midnight between August 31 @@ -765,47 +735,32 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # of September: # # One article about it (in French): -# # http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default -# # # We have some further details posted here: -# # http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html -# # From Steffen Thorsen (2009-03-17): # Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according # to many sources, such as -# # http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html -# -# # http://www.medi1sat.ma/fr/depeche.aspx?idp=2312 -# # (French) # # Our summary: -# # http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html -# # From Alexander Krivenyshev (2009-03-17): # Here is a link to official document from Royaume du Maroc Premier Ministre, -# Ministere de la Modernisation des Secteurs Publics +# Ministère de la Modernisation des Secteurs Publics # # Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967) # concerning the amendment of the legal time, the Ministry of Modernization of # Public Sectors announced that the official time in the Kingdom will be # advanced 60 minutes from Sunday 31 May 2009 at midnight. # -# # http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf -# -# -# # http://www.worldtimezone.com/dst_news/dst_news_morocco03.html -# # From Steffen Thorsen (2010-04-13): # Several news media in Morocco report that the Ministry of Modernization @@ -813,51 +768,33 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # 2010-05-02 to 2010-08-08. # # Example: -# # http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html -# # (French) # Our page: -# # http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html -# # From Dan Abitol (2011-03-30): # ...Rules for Africa/Casablanca are the following (24h format) -# The 3rd april 2011 at 00:00:00, [it] will be 3rd april 1:00:00 -# The 31th july 2011 at 00:59:59, [it] will be 31th July 00:00:00 +# The 3rd April 2011 at 00:00:00, [it] will be 3rd April 01:00:00 +# The 31st July 2011 at 00:59:59, [it] will be 31st July 00:00:00 # ...Official links of change in morocco # The change was broadcast on the FM Radio # I ve called ANRT (telecom regulations in Morocco) at # +212.537.71.84.00 -# # http://www.anrt.net.ma/fr/ -# # They said that -# # http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view -# # is the official publication to look at. # They said that the decision was already taken. # # More articles in the press -# -# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev -# -# e.html -# +# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-leve.html # http://www.lematin.ma/Actualite/Express/Article.asp?id=148923 -# -# # http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim -# anche-prochain-5538.html -# # From Petr Machata (2011-03-30): # They have it written in English here: -# # http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view -# # # It says there that "Morocco will resume its standard time on July 31, # 2011 at midnight." Now they don't say whether they mean midnight of @@ -865,20 +802,16 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # also been like that in the past. # From Alexander Krivenyshev (2012-03-09): -# According to Infomédiaire web site from Morocco (infomediaire.ma), -# on March 9, 2012, (in French) Heure légale: -# Le Maroc adopte officiellement l'heure d'été -# +# According to Infomédiaire web site from Morocco (infomediaire.ma), +# on March 9, 2012, (in French) Heure légale: +# Le Maroc adopte officiellement l'heure d'été # http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9 -# # Governing Council adopted draft decree, that Morocco DST starts on # the last Sunday of March (March 25, 2012) and ends on # last Sunday of September (September 30, 2012) # except the month of Ramadan. # or (brief) -# # http://www.worldtimezone.com/dst_news/dst_news_morocco06.html -# # From Arthur David Olson (2012-03-10): # The infomediaire.ma source indicates that the system is to be in @@ -889,17 +822,13 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # From Christophe Tropamer (2012-03-16): # Seen Morocco change again: -# # http://www.le2uminutes.com/actualite.php -# -# "...à partir du dernier dimance d'avril et non fins mars, -# comme annoncé précédemment." +# "...à partir du dernier dimanche d'avril et non fins mars, +# comme annoncé précédemment." # From Milamber Space Network (2012-07-17): # The official return to GMT is announced by the Moroccan government: -# # http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French] -# # # Google translation, lightly edited: # Back to the standard time of the Kingdom (GMT) @@ -917,7 +846,7 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # announced a bit in advance. On 2012-07-11 the Moroccan government # announced that year's Ramadan daylight-saving transitions would be # 2012-07-20 and 2012-08-20; see -# . +# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 # From Andrew Paprocki (2013-07-02): # Morocco announced that the year's Ramadan daylight-savings @@ -937,39 +866,36 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # From Sebastien Willemijns (2014-03-18): # http://www.afriquinfos.com/articles/2014/3/18/maroc-heure-dete-avancez-tous-horloges-247891.asp -# From Paul Eggert (2014-03-19): -# To estimate what the Moroccan government will do in future years, -# transition dates for 2014 through 2038 were determined by running -# the following program under GNU Emacs 24.3: -# -# (let ((islamic-year 1435)) -# (while (< islamic-year 1461) -# (let ((a -# (calendar-gregorian-from-absolute -# (calendar-islamic-to-absolute (list 9 1 islamic-year)))) -# (b -# (calendar-gregorian-from-absolute -# (calendar-islamic-to-absolute (list 10 1 islamic-year))))) -# (insert -# (format -# (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 3:00\t0\t-\n" -# "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 2:00\t1:00\tS\n") -# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) -# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) +# From Milamber Space Network (2014-06-05): +# The Moroccan government has recently announced that the country will return +# to standard time at 03:00 on Saturday, June 28, 2014 local time.... DST +# will resume again at 02:00 on Saturday, August 2, 2014.... +# http://www.mmsp.gov.ma/fr/actualites.aspx?id=586 + +# From Paul Eggert (2014-06-05): +# For now, guess that later spring and fall transitions will use 2014's rules, +# and guess that Morocco will switch to standard time at 03:00 the last +# Saturday before Ramadan, and back to DST at 02:00 the first Saturday after +# Ramadan. To implement this, transition dates for 2015 through 2037 were +# determined by running the following program under GNU Emacs 24.3, with the +# results integrated by hand into the table below. +# (let ((islamic-year 1436)) +# (while (< islamic-year 1460) +# (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year))) +# (b (calendar-islamic-to-absolute (list 10 1 islamic-year))) +# (saturday 6)) +# (while (/= saturday (mod (setq a (1- a)) 7))) +# (while (/= saturday (mod b 7)) +# (setq b (1+ b))) +# (setq a (calendar-gregorian-from-absolute a)) +# (setq b (calendar-gregorian-from-absolute b)) +# (insert +# (format +# (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t0\t-\n" +# "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t1:00\tS\n") +# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) +# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) # (setq islamic-year (+ 1 islamic-year)))) -# -# with spring-forward transitions removed for 2023-2025, when the -# normal spring-forward date falls during the estimated Ramadan; with -# all transitions removed for 2026-2035, where the estimated Ramadan -# falls entirely outside daylight-saving time; and with fall-back -# transitions removed for 2036-2037, where the normal fall-back -# date falls during the estimated Ramadan. Normally, the table would -# stop after 2037 because 32-bit time_t values roll around early in 2038, -# but that would imply a prediction of perpetual DST after March 2038 -# due to the year-2037 glitches. So, this table instead stops after -# 2038, the first non-glitchy year after the 32-bit rollover. -# An advantage of stopping after 2038 is that it lets zic guess -# TZ='WET0WEST,M3.5.0,M10.5.0/3' for time stamps far in the future. # RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -991,46 +917,44 @@ Rule Morocco 1978 only - Aug 4 0:00 0 - Rule Morocco 2008 only - Jun 1 0:00 1:00 S Rule Morocco 2008 only - Sep 1 0:00 0 - Rule Morocco 2009 only - Jun 1 0:00 1:00 S -Rule Morocco 2009 only - Aug 21 0:00 0 - +Rule Morocco 2009 only - Aug 21 0:00 0 - Rule Morocco 2010 only - May 2 0:00 1:00 S Rule Morocco 2010 only - Aug 8 0:00 0 - Rule Morocco 2011 only - Apr 3 0:00 1:00 S -Rule Morocco 2011 only - Jul 31 0 0 - -Rule Morocco 2012 2013 - Apr lastSun 2:00 1:00 S -Rule Morocco 2012 only - Sep 30 3:00 0 - -Rule Morocco 2012 only - Jul 20 3:00 0 - -Rule Morocco 2012 only - Aug 20 2:00 1:00 S -Rule Morocco 2013 only - Jul 7 3:00 0 - -Rule Morocco 2013 only - Aug 10 2:00 1:00 S -Rule Morocco 2013 2035 - Oct lastSun 3:00 0 - -Rule Morocco 2014 2022 - Mar lastSun 2:00 1:00 S -Rule Morocco 2014 only - Jun 29 3:00 0 - -Rule Morocco 2014 only - Jul 29 2:00 1:00 S -Rule Morocco 2015 only - Jun 18 3:00 0 - -Rule Morocco 2015 only - Jul 18 2:00 1:00 S -Rule Morocco 2016 only - Jun 7 3:00 0 - -Rule Morocco 2016 only - Jul 7 2:00 1:00 S -Rule Morocco 2017 only - May 27 3:00 0 - -Rule Morocco 2017 only - Jun 26 2:00 1:00 S -Rule Morocco 2018 only - May 16 3:00 0 - -Rule Morocco 2018 only - Jun 15 2:00 1:00 S -Rule Morocco 2019 only - May 6 3:00 0 - -Rule Morocco 2019 only - Jun 5 2:00 1:00 S -Rule Morocco 2020 only - Apr 24 3:00 0 - -Rule Morocco 2020 only - May 24 2:00 1:00 S -Rule Morocco 2021 only - Apr 13 3:00 0 - -Rule Morocco 2021 only - May 13 2:00 1:00 S -Rule Morocco 2022 only - Apr 3 3:00 0 - -Rule Morocco 2022 only - May 3 2:00 1:00 S -Rule Morocco 2023 only - Apr 22 2:00 1:00 S -Rule Morocco 2024 only - Apr 10 2:00 1:00 S -Rule Morocco 2025 only - Mar 31 2:00 1:00 S -Rule Morocco 2026 max - Mar lastSun 2:00 1:00 S -Rule Morocco 2036 only - Oct 21 3:00 0 - -Rule Morocco 2037 only - Oct 11 3:00 0 - -Rule Morocco 2038 only - Sep 30 3:00 0 - -Rule Morocco 2038 only - Oct 30 2:00 1:00 S -Rule Morocco 2038 max - Oct lastSun 3:00 0 - +Rule Morocco 2011 only - Jul 31 0 0 - +Rule Morocco 2012 2013 - Apr lastSun 2:00 1:00 S +Rule Morocco 2012 only - Sep 30 3:00 0 - +Rule Morocco 2012 only - Jul 20 3:00 0 - +Rule Morocco 2012 only - Aug 20 2:00 1:00 S +Rule Morocco 2013 only - Jul 7 3:00 0 - +Rule Morocco 2013 only - Aug 10 2:00 1:00 S +Rule Morocco 2013 max - Oct lastSun 3:00 0 - +Rule Morocco 2014 2022 - Mar lastSun 2:00 1:00 S +Rule Morocco 2014 only - Jun 28 3:00 0 - +Rule Morocco 2014 only - Aug 2 2:00 1:00 S +Rule Morocco 2015 only - Jun 13 3:00 0 - +Rule Morocco 2015 only - Jul 18 2:00 1:00 S +Rule Morocco 2016 only - Jun 4 3:00 0 - +Rule Morocco 2016 only - Jul 9 2:00 1:00 S +Rule Morocco 2017 only - May 20 3:00 0 - +Rule Morocco 2017 only - Jul 1 2:00 1:00 S +Rule Morocco 2018 only - May 12 3:00 0 - +Rule Morocco 2018 only - Jun 16 2:00 1:00 S +Rule Morocco 2019 only - May 4 3:00 0 - +Rule Morocco 2019 only - Jun 8 2:00 1:00 S +Rule Morocco 2020 only - Apr 18 3:00 0 - +Rule Morocco 2020 only - May 30 2:00 1:00 S +Rule Morocco 2021 only - Apr 10 3:00 0 - +Rule Morocco 2021 only - May 15 2:00 1:00 S +Rule Morocco 2022 only - Apr 2 3:00 0 - +Rule Morocco 2022 only - May 7 2:00 1:00 S +Rule Morocco 2023 only - Apr 22 2:00 1:00 S +Rule Morocco 2024 only - Apr 13 2:00 1:00 S +Rule Morocco 2025 only - Apr 5 2:00 1:00 S +Rule Morocco 2026 max - Mar lastSun 2:00 1:00 S +Rule Morocco 2035 only - Oct 27 3:00 0 - +Rule Morocco 2036 only - Oct 18 3:00 0 - +Rule Morocco 2037 only - Oct 10 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 @@ -1049,11 +973,17 @@ Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 # Assume that this has been true since Western Sahara switched to GMT, # since most of it was then controlled by Morocco. -Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan +Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún -1:00 - WAT 1976 Apr 14 0:00 Morocco WE%sT # Mozambique +# +# Shanks gives 1903-03-01 for the transition to CAT. +# Perhaps the 1911-05-26 Portuguese decree +# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf +# merely made it official? +# # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Maputo 2:10:20 - LMT 1903 Mar 2:00 - CAT @@ -1062,8 +992,8 @@ Zone Africa/Maputo 2:10:20 - LMT 1903 Mar # The 1994-04-03 transition is from Shanks & Pottenger. # Shanks & Pottenger report no DST after 1998-04; go with IATA. -# From Petronella Sibeene (2007-03-30) in -# : +# From Petronella Sibeene (2007-03-30): +# http://allafrica.com/stories/200703300178.html # While the entire country changes its time, Katima Mulilo and other # settlements in Caprivi unofficially will not because the sun there # rises and sets earlier compared to other regions. Chief of @@ -1080,34 +1010,41 @@ Rule Namibia 1994 max - Sep Sun>=1 2:00 1:00 S Rule Namibia 1995 max - Apr Sun>=1 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Windhoek 1:08:24 - LMT 1892 Feb 8 - 1:30 - SWAT 1903 Mar # SW Africa Time - 2:00 - SAST 1942 Sep 20 2:00 - 2:00 1:00 SAST 1943 Mar 21 2:00 + 1:30 - SWAT 1903 Mar # SW Africa Time + 2:00 - SAST 1942 Sep 20 2:00 + 2:00 1:00 SAST 1943 Mar 21 2:00 2:00 - SAST 1990 Mar 21 # independence 2:00 - CAT 1994 Apr 3 1:00 Namibia WA%sT # Niger -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Niamey 0:08:28 - LMT 1912 - -1:00 - WAT 1934 Feb 26 - 0:00 - GMT 1960 - 1:00 - WAT +# See Africa/Lagos. # Nigeria # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Lagos 0:13:36 - LMT 1919 Sep 1:00 - WAT - -# Reunion +Link Africa/Lagos Africa/Bangui # Central African Republic +Link Africa/Lagos Africa/Brazzaville # Rep. of the Congo +Link Africa/Lagos Africa/Douala # Cameroon +Link Africa/Lagos Africa/Kinshasa # Dem. Rep. of the Congo (west) +Link Africa/Lagos Africa/Libreville # Gabon +Link Africa/Lagos Africa/Luanda # Angola +Link Africa/Lagos Africa/Malabo # Equatorial Guinea +Link Africa/Lagos Africa/Niamey # Niger +Link Africa/Lagos Africa/Porto-Novo # Benin + +# Réunion # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis - 4:00 - RET # Reunion Time +Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis + 4:00 - RET # Réunion Time # -# Scattered Islands (Iles Eparses) administered from Reunion are as follows. +# Crozet Islands also observes Réunion time; see the 'antarctica' file. +# +# Scattered Islands (Îles Éparses) administered from Réunion are as follows. # The following information about them is taken from -# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French; -# no longer available as of 1999-08-17). +# Îles Éparses (, 1997-07-22, +# in French; no longer available as of 1999-08-17). # We have no info about their time zone histories. # # Bassas da India - uninhabited @@ -1122,32 +1059,21 @@ Zone Africa/Kigali 2:00:16 - LMT 1935 Jun 2:00 - CAT # St Helena -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Atlantic/St_Helena -0:22:48 - LMT 1890 # Jamestown - -0:22:48 - JMT 1951 # Jamestown Mean Time - 0:00 - GMT +# See Africa/Abidjan. # The other parts of the St Helena territory are similar: # Tristan da Cunha: on GMT, say Whitman and the CIA -# Ascension: on GMT, says usno1995 and the CIA +# Ascension: on GMT, say the USNO (1995-12-21) and the CIA # Gough (scientific station since 1955; sealers wintered previously): # on GMT, says the CIA -# Inaccessible, Nightingale: no information, but probably GMT - -# Sao Tome and Principe -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Sao_Tome 0:26:56 - LMT 1884 - -0:36:32 - LMT 1912 # Lisbon Mean Time - 0:00 - GMT +# Inaccessible, Nightingale: uninhabited +# São Tomé and Príncipe # Senegal -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Dakar -1:09:44 - LMT 1912 - -1:00 - WAT 1941 Jun - 0:00 - GMT +# See Africa/Abidjan. # Seychelles # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Indian/Mahe 3:41:48 - LMT 1906 Jun # Victoria +Zone Indian/Mahe 3:41:48 - LMT 1906 Jun # Victoria 4:00 - SCT # Seychelles Time # From Paul Eggert (2001-05-30): # Aldabra, Farquhar, and Desroches, originally dependencies of the @@ -1157,17 +1083,7 @@ Zone Indian/Mahe 3:41:48 - LMT 1906 Jun # Victoria # Possibly the islands were uninhabited. # Sierra Leone -# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger. -Rule SL 1935 1942 - Jun 1 0:00 0:40 SLST -Rule SL 1935 1942 - Oct 1 0:00 0 WAT -Rule SL 1957 1962 - Jun 1 0:00 1:00 SLST -Rule SL 1957 1962 - Sep 1 0:00 0 GMT -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Freetown -0:53:00 - LMT 1882 - -0:53:00 - FMT 1913 Jun # Freetown Mean Time - -1:00 SL %s 1957 - 0:00 SL %s +# See Africa/Abidjan. # Somalia # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -1190,9 +1106,9 @@ Zone Africa/Johannesburg 1:52:00 - LMT 1892 Feb 8 # Sudan # -# From -# Sudan News Agency (2000-01-13) -# , also reported by Michael De Beukelaer-Dossche via Steffen Thorsen: +# From +# Sudan News Agency (2000-01-13), +# also reported by Michaël De Beukelaer-Dossche via Steffen Thorsen: # Clocks will be moved ahead for 60 minutes all over the Sudan as of noon # Saturday.... This was announced Thursday by Caretaker State Minister for # Manpower Abdul-Rahman Nur-Eddin. @@ -1223,14 +1139,12 @@ Zone Africa/Dar_es_Salaam 2:37:08 - LMT 1931 3:00 - EAT # Togo -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Lome 0:04:52 - LMT 1893 - 0:00 - GMT +# See Africa/Abidjan. # Tunisia # From Gwillim Law (2005-04-30): -# My correspondent, Risto Nykanen, has alerted me to another adoption of DST, +# My correspondent, Risto Nykänen, has alerted me to another adoption of DST, # this time in Tunisia. According to Yahoo France News # , in a story attributed to AP # and dated 2005-04-26, "Tunisia has decided to advance its official time by @@ -1239,8 +1153,8 @@ Zone Africa/Lome 0:04:52 - LMT 1893 # Saturday." (My translation) # # From Oscar van Vlijmen (2005-05-02): -# LaPresse, the first national daily newspaper ... -# +# La Presse, the first national daily newspaper ... +# http://www.lapresse.tn/archives/archives280405/actualites/lheure.html # ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30, # 1h standard time. # @@ -1253,18 +1167,12 @@ Zone Africa/Lome 0:04:52 - LMT 1893 # From Steffen Thorsen (2009-03-16): # According to several news sources, Tunisia will not observe DST this year. # (Arabic) -# # http://www.elbashayer.com/?page=viewn&nid=42546 -# -# # http://www.babnet.net/kiwidetail-15295.asp -# # # We have also confirmed this with the US embassy in Tunisia. # We have a wrap-up about this on the following page: -# # http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html -# # From Alexander Krivenyshev (2009-03-17): # Here is a link to Tunis Afrique Presse News Agency @@ -1272,20 +1180,17 @@ Zone Africa/Lome 0:04:52 - LMT 1893 # Standard time to be kept the whole year long (tap.info.tn): # # (in English) -# # http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157 -# # # (in Arabic) -# # http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1 -# -# From Arthur David Olson (2009--3-18): -# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact -# that the fasting month of ramadan coincides with the period concerned by summer time. -# Therefore, the standard time will be kept unchanged the whole year long." -# So foregoing DST seems to be an exception (albeit one that may be repeated in the future). +# From Arthur David Olson (2009-03-18): +# The Tunis Afrique Presse News Agency notice contains this: "This measure is +# due to the fact that the fasting month of Ramadan coincides with the period +# concerned by summer time. Therefore, the standard time will be kept +# unchanged the whole year long." So foregoing DST seems to be an exception +# (albeit one that may be repeated in the future). # From Alexander Krivenyshev (2010-03-27): # According to some news reports Tunis confirmed not to use DST in 2010 @@ -1297,12 +1202,8 @@ Zone Africa/Lome 0:04:52 - LMT 1893 # coincided with the month of Ramadan..." # # (in Arabic) -# # http://www.moheet.com/show_news.aspx?nid=358861&pg=1 -# # http://www.almadenahnews.com/newss/news.php?c=118&id=38036 -# or -# # http://www.worldtimezone.com/dst_news/dst_news_tunis02.html # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -1337,7 +1238,7 @@ Rule Tunisia 2006 2008 - Oct lastSun 2:00s 0 - # Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Tunis 0:40:44 - LMT 1881 May 12 - 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time + 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time 1:00 Tunisia CE%sT # Uganda diff --git a/test/sun/util/calendar/zi/tzdata/antarctica b/test/sun/util/calendar/zi/tzdata/antarctica index e31bada94fb711b41f7bfba27d655c662d9b614e..0cdac27086160968d754b480ea825831be348b6b 100644 --- a/test/sun/util/calendar/zi/tzdata/antarctica +++ b/test/sun/util/calendar/zi/tzdata/antarctica @@ -21,19 +21,16 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -#
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
     # From Paul Eggert (1999-11-15):
     # To keep things manageable, we list only locations occupied year-round; see
    -# 
     # COMNAP - Stations and Bases
    -# 
    +# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/
     # and
    -# 
     # Summary of the Peri-Antarctic Islands (1998-07-23)
    -# 
    +# http://www.spri.cam.ac.uk/bob/periant.htm
     # for information.
     # Unless otherwise specified, we have no time zone information.
     #
    @@ -78,19 +75,19 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
     
     # Argentina - year-round bases
     # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
    -# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
    -# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
    -# Marambio, Seymour I, -6414-05637, since 1969-10-29
    +# Carlini, Potter Cove, King George Island, -6414-0602320, since 1982-01
    +# Esperanza, Hope Bay, -6323-05659, since 1952-12-17
    +# Marambio, -6414-05637, since 1969-10-29
     # Orcadas, Laurie I, -6016-04444, since 1904-02-22
    -# San Martin, Debenham I, -6807-06708, since 1951-03-21
    +# San Martín, Barry I, -6808-06706, since 1951-03-21
     #	(except 1960-03 / 1976-03-21)
     
     # Australia - territories
     # Heard Island, McDonald Islands (uninhabited)
     #	previously sealers and scientific personnel wintered
    -#	
     #	Margaret Turner reports
    -#	 (1999-09-30) that they're UTC+5, with no DST;
    +#	http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
    +#	(1999-09-30) that they're UTC+5, with no DST;
     #	presumably this is when they have visitors.
     #
     # year-round bases
    @@ -107,14 +104,10 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
     # The changes occurred on 2009-10-18 at 02:00 (local times).
     #
     # Government source: (Australian Antarctic Division)
    -# 
     # http://www.aad.gov.au/default.asp?casid=37079
    -# 
     #
     # We have more background information here:
    -# 
     # http://www.timeanddate.com/news/time/antarctica-new-times.html
    -# 
     
     # From Steffen Thorsen (2010-03-10):
     # We got these changes from the Australian Antarctic Division: ...
    @@ -129,50 +122,49 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
     # - Mawson station stays on UTC+5.
     #
     # Background:
    -# 
     # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
    -# 
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Antarctica/Casey	0	-	zzz	1969
    -			8:00	-	WST	2009 Oct 18 2:00
    -						# Western (Aus) Standard Time
    -			11:00	-	CAST	2010 Mar 5 2:00
    -						# Casey Time
    -			8:00	-	WST	2011 Oct 28 2:00
    +			8:00	-	AWST	2009 Oct 18  2:00
    +						# Australian Western Std Time
    +			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
    +			8:00	-	AWST	2011 Oct 28  2:00
     			11:00	-	CAST	2012 Feb 21 17:00u
    -			8:00	-	WST
    +			8:00	-	AWST
     Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
    -			7:00	-	DAVT	1964 Nov # Davis Time
    +			7:00	-	DAVT	1964 Nov    # Davis Time
     			0	-	zzz	1969 Feb
    -			7:00	-	DAVT	2009 Oct 18 2:00
    +			7:00	-	DAVT	2009 Oct 18  2:00
     			5:00	-	DAVT	2010 Mar 10 20:00u
    -			7:00	-	DAVT	2011 Oct 28 2:00
    +			7:00	-	DAVT	2011 Oct 28  2:00
     			5:00	-	DAVT	2012 Feb 21 20:00u
     			7:00	-	DAVT
     Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
    -			6:00	-	MAWT	2009 Oct 18 2:00
    -						# Mawson Time
    +			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
     			5:00	-	MAWT
     # References:
    -# 
     # Casey Weather (1998-02-26)
    -# 
    -# 
    +# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
     # Davis Station, Antarctica (1998-02-26)
    -# 
    -# 
    +# http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html
     # Mawson Station, Antarctica (1998-02-25)
    -# 
    +# http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html
    +
    +# Belgium - year-round base
    +# Princess Elisabeth, Queen Maud Land, -713412+0231200, since 2007
     
     # Brazil - year-round base
    -# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
    +# Ferraz, King George Island, -6205+05824, since 1983/4
    +
    +# Bulgaria - year-round base
    +# St. Kliment Ohridski, Livingston Island, -623829-0602153, since 1988
     
     # Chile - year-round bases and towns
     # Escudero, South Shetland Is, -621157-0585735, since 1994
    -# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
    -# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
    -# Capitan Arturo Prat, -6230-05941
    +# Frei Montalva, King George Island, -6214-05848, since 1969-03-07
    +# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
    +# Prat, -6230-05941
     # Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
     # These locations have always used Santiago time; use TZ='America/Santiago'.
     
    @@ -180,31 +172,35 @@ Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
     # Great Wall, King George Island, -6213-05858, since 1985-02-20
     # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
     
    -# France - year-round bases
    +# France - year-round bases (also see "France & Italy")
     #
     # From Antoine Leca (1997-01-20):
    -# Time data are from Nicole Pailleau at the IFRTP
    +# Time data entries are from Nicole Pailleau at the IFRTP
     # (French Institute for Polar Research and Technology).
    -# She confirms that French Southern Territories and Terre Adelie bases
    -# don't observe daylight saving time, even if Terre Adelie supplies came
    +# She confirms that French Southern Territories and Terre Adélie bases
    +# don't observe daylight saving time, even if Terre Adélie supplies came
     # from Tasmania.
     #
     # French Southern Territories with year-round inhabitants
     #
    -# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
    -# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
    -# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
    +# Alfred Faure, Possession Island, Crozet Islands, -462551+0515152, since 1964;
    +#	sealing & whaling stations operated variously 1802/1911+;
    +#	see Indian/Reunion.
    +#
    +# Martin-de-Viviès, Amsterdam Island, -374105+0773155, since 1950
    +# Port-aux-Français, Kerguelen Islands, -492110+0701303, since 1951;
     #	whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
     #
     # St Paul Island - near Amsterdam, uninhabited
     #	fishing stations operated variously 1819/1931
     #
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Indian/Kerguelen	0	-	zzz	1950	# Port-aux-Francais
    +Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
     			5:00	-	TFT	# ISO code TF Time
     #
     # year-round base in the main continent
    -# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
    +# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
    +#  (2005-12-05)
     #
     # Another base at Port-Martin, 50km east, began operation in 1947.
     # It was destroyed by fire on 1952-01-14.
    @@ -214,20 +210,22 @@ Zone Antarctica/DumontDUrville 0 -	zzz	1947
     			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
     			0	-	zzz	1956 Nov
     			10:00	-	DDUT	# Dumont-d'Urville Time
    -# Reference:
    -# 
    -# Dumont d'Urville Station (2005-12-05)
    -# 
    +
    +# France & Italy - year-round base
    +# Concordia, -750600+1232000, since 2005
     
     # Germany - year-round base
    -# Georg von Neumayer, -7039-00815
    +# Neumayer III, -704080-0081602, since 2009
     
    -# India - year-round base
    -# Dakshin Gangotri, -7005+01200
    +# India - year-round bases
    +# Bharati, -692428+0761114, since 2012
    +# Maitri, -704558+0114356, since 1989
    +
    +# Italy - year-round base (also see "France & Italy")
    +# Zuchelli, Terra Nova Bay, -744140+1640647, since 1986
     
     # Japan - year-round bases
    -# Dome Fuji, -7719+03942
    -# Syowa, -690022+0393524
    +# Syowa (also known as Showa), -690022+0393524, since 1957
     #
     # From Hideyuki Suzuki (1999-02-06):
     # In all Japanese stations, +0300 is used as the standard time.
    @@ -239,11 +237,11 @@ Zone Antarctica/DumontDUrville 0 -	zzz	1947
     Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
     			3:00	-	SYOT	# Syowa Time
     # See:
    -# 
     # NIPR Antarctic Research Activities (1999-08-17)
    -# 
    +# http://www.nipr.ac.jp/english/ara01.html
     
     # S Korea - year-round base
    +# Jang Bogo, Terra Nova Bay, -743700+1641205 since 2014
     # King Sejong, King George Island, -6213-05847, since 1988
     
     # New Zealand - claims
    @@ -287,11 +285,14 @@ Rule	Troll	2005	max	-	Mar	lastSun	1:00u	2:00	CEST
     Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
    -     			0:00	Troll	%s
    +			0:00	Troll	%s
     
     # Poland - year-round base
     # Arctowski, King George Island, -620945-0582745, since 1977
     
    +# Romania - year-bound base
    +# Law-Racoviță, Larsemann Hills, -692319+0762251, since 1986
    +
     # Russia - year-round bases
     # Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
     # Mirny, Davis coast, -6633+09301, since 1956-02
    @@ -301,8 +302,8 @@ Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
     #	year-round from 1960/61 to 1992
     
     # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
    -# 
    -# From Craig Mundell (1994-12-15):
    +# From Craig Mundell (1994-12-15):
    +# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
     # Vostok, which is one of the Russian stations, is set on the same
     # time as Moscow, Russia.
     #
    @@ -317,7 +318,7 @@ Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
     #
     # From Paul Eggert (2001-05-04):
     # This seems to be hopelessly confusing, so I asked Lee Hotz about it
    -# in person.  He said that some Antartic locations set their local
    +# in person.  He said that some Antarctic locations set their local
     # time so that noon is the warmest part of the day, and that this
     # changes during the year and does not necessarily correspond to mean
     # solar noon.  So the Vostok time might have been whatever the clocks
    @@ -329,9 +330,12 @@ Zone Antarctica/Vostok	0	-	zzz	1957 Dec 16
     
     # S Africa - year-round bases
     # Marion Island, -4653+03752
    -# Sanae, -7141-00250
    +# SANAE IV, Vesleskarvet, Queen Maud Land, -714022-0025026, since 1997
    +
    +# Ukraine - year-round base
    +# Vernadsky (formerly Faraday), Galindez Island, -651445-0641526, since 1954
     
    -# UK
    +# United Kingdom
     #
     # British Antarctic Territories (BAT) claims
     # South Orkney Islands
    @@ -387,7 +391,7 @@ Zone Antarctica/Palmer	0	-	zzz	1965
     # but that he found it more convenient to keep GMT+12
     # as supplies for the station were coming from McMurdo Sound,
     # which was on GMT+12 because New Zealand was on GMT+12 all year
    -# at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
    +# at that time (1957).  (Source: Siple's book 90 Degrees South.)
     #
     # From Susan Smith
     # http://www.cybertours.com/whs/pole10.html
    diff --git a/test/sun/util/calendar/zi/tzdata/asia b/test/sun/util/calendar/zi/tzdata/asia
    index 595c8ed7245b4a96440a84e356070d2a246e18f1..906c0a97cda61696d2efcf3e1224cd92fc727c09 100644
    --- a/test/sun/util/calendar/zi/tzdata/asia
    +++ b/test/sun/util/calendar/zi/tzdata/asia
    @@ -21,13 +21,13 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    -# This data is by no means authoritative; if you think you know better,
    +# This file is by no means authoritative; if you think you know better,
     # go ahead and edit the file (and please send any changes to
    -# tz@iana.org for general use in the future).
    +# tz@iana.org for general use in the future).  For more, please see
    +# the file CONTRIBUTING in the tz distribution.
     
     # From Paul Eggert (2013-08-11):
     #
    @@ -49,13 +49,17 @@
     # I found in the UCLA library.
     #
     # For data circa 1899, a common source is:
    -# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
    -# .
    +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
    +# http://www.jstor.org/stable/1774359
    +#
    +# For Russian data circa 1919, a source is:
    +# Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
    +# (See the 'europe' file for a fuller citation.)
     #
     # A reliable and entertaining source about time zones is
     # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
     #
    -# I invented the abbreviations marked `*' in the following table;
    +# I invented the abbreviations marked '*' in the following table;
     # the rest are from earlier versions of this file, or from other sources.
     # Corrections are welcome!
     #	     std  dst
    @@ -70,13 +74,14 @@
     #	7:00 WIB	west Indonesia (Waktu Indonesia Barat)
     #	8:00 WITA	central Indonesia (Waktu Indonesia Tengah)
     #	8:00 CST	China
    -#	9:00 CJT	Central Japanese Time (1896/1937)*
    +#	8:00 JWST	Western Standard Time (Japan, 1896/1937)*
    +#	9:00 JCST	Central Standard Time (Japan, 1896/1937)
     #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
     #	9:00 JST  JDT	Japan
     #	9:00 KST  KDT	Korea
    -#	9:30 CST	(Australian) Central Standard Time
    +#	9:30 ACST	Australian Central Standard Time
     #
    -# See the `europe' file for Russia and Turkey in Asia.
    +# See the 'europe' file for Russia and Turkey in Asia.
     
     # From Guy Harris:
     # Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
    @@ -86,7 +91,7 @@
     
     ###############################################################################
     
    -# These rules are stolen from the `europe' file.
    +# These rules are stolen from the 'europe' file.
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	EUAsia	1981	max	-	Mar	lastSun	 1:00u	1:00	S
     Rule	EUAsia	1979	1995	-	Sep	lastSun	 1:00u	0	-
    @@ -138,11 +143,11 @@ Zone	Asia/Kabul	4:36:48 -	LMT	1890
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
     			3:00	-	YERT	1957 Mar    # Yerevan Time
    -			4:00 RussiaAsia YER%sT	1991 Mar 31 2:00s
    +			4:00 RussiaAsia YER%sT	1991 Mar 31  2:00s
     			3:00	1:00	YERST	1991 Sep 23 # independence
    -			3:00 RussiaAsia	AM%sT	1995 Sep 24 2:00s
    +			3:00 RussiaAsia	AM%sT	1995 Sep 24  2:00s
     			4:00	-	AMT	1997
    -			4:00 RussiaAsia	AM%sT	2012 Mar 25 2:00s
    +			4:00 RussiaAsia	AM%sT	2012 Mar 25  2:00s
     			4:00	-	AMT
     
     # Azerbaijan
    @@ -155,16 +160,16 @@ Rule	Azer	1997	max	-	Oct	lastSun	 5:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
     			3:00	-	BAKT	1957 Mar    # Baku Time
    -			4:00 RussiaAsia BAK%sT	1991 Mar 31 2:00s
    +			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
     			3:00	1:00	BAKST	1991 Aug 30 # independence
     			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
    -			4:00	-	AZT	1996 # Azerbaijan time
    +			4:00	-	AZT	1996     # Azerbaijan Time
     			4:00	EUAsia	AZ%sT	1997
     			4:00	Azer	AZ%sT
     
     # Bahrain
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
    +Zone	Asia/Bahrain	3:22:20 -	LMT	1920     # Manamah
     			4:00	-	GST	1972 Jun
     			3:00	-	AST
     
    @@ -174,13 +179,8 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
     # Daylight Saving Time from June 16 to Sept 30
     #
     # Bangladesh to introduce daylight saving time likely from June 16
    -# 
     # http://www.asiantribune.com/?q=node/17288
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
    -# 
     #
     # "... Bangladesh government has decided to switch daylight saving time from
     # June
    @@ -195,17 +195,11 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
     # the 19th and 20th, and they have not set the end date yet.
     #
     # Some sources:
    -# 
     # http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
    -# 
    -# 
     # http://bdnews24.com/details.php?id=85889&cid=2
    -# 
     #
     # Our wrap-up:
    -# 
     # http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
    -# 
     
     # From A. N. M. Kamrus Saadat (2009-06-15):
     # Finally we've got the official mail regarding DST start time where DST start
    @@ -220,13 +214,8 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
     #
     # Following report by same newspaper-"The Daily Star Friday":
     # "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
    -# 
     # http://www.thedailystar.net/newDesign/news-details.php?nid=107021
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
    -# 
     
     # From Steffen Thorsen (2009-10-13):
     # IANS (Indo-Asian News Service) now reports:
    @@ -235,22 +224,15 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
     # "continue for an indefinite period."
     #
     # One of many places where it is published:
    -# 
     # http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
    -# 
     
     # From Alexander Krivenyshev (2009-12-24):
     # According to Bangladesh newspaper "The Daily Star,"
     # Bangladesh will change its clock back to Standard Time on Dec 31, 2009.
     #
     # Clock goes back 1-hr on Dec 31 night.
    -# 
     # http://www.thedailystar.net/newDesign/news-details.php?nid=119228
    -# 
    -# and
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html
    -# 
     #
     # "...The government yesterday decided to put the clock back by one hour
     # on December 31 midnight and the new time will continue until March 31,
    @@ -260,17 +242,12 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
     # From Alexander Krivenyshev (2010-03-22):
     # According to Bangladesh newspaper "The Daily Star,"
     # Cabinet cancels Daylight Saving Time
    -# 
     # http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html
    -# 
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	S
    -Rule	Dhaka	2009	only	-	Dec	31	23:59	0	-
    +Rule	Dhaka	2009	only	-	Dec	31	24:00	0	-
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Dhaka	6:01:40 -	LMT	1890
    @@ -301,7 +278,7 @@ Zone	Indian/Chagos	4:49:40	-	LMT	1907
     
     # Brunei
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
    +Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar # Bandar Seri Begawan
     			7:30	-	BNT	1933
     			8:00	-	BNT
     
    @@ -310,16 +287,16 @@ Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
     # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Rangoon	6:24:40 -	LMT	1880		# or Yangon
    -			6:24:40	-	RMT	1920	   # Rangoon Mean Time?
    -			6:30	-	BURT	1942 May   # Burma Time
    -			9:00	-	JST	1945 May 3
    -			6:30	-	MMT		   # Myanmar Time
    +Zone	Asia/Rangoon	6:24:40 -	LMT	1880        # or Yangon
    +			6:24:40	-	RMT	1920        # Rangoon Mean Time?
    +			6:30	-	BURT	1942 May    # Burma Time
    +			9:00	-	JST	1945 May  3
    +			6:30	-	MMT	# Myanmar Time
     
     # Cambodia
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
    -			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
    +			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
     			7:00	-	ICT	1912 May
     			8:00	-	ICT	1931 May
     			7:00	-	ICT
    @@ -332,12 +309,12 @@ Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
     # From Bob Devine (1988-01-28):
     # No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
     # China is across 4 physical time zones, before Feb 1, 1986 only the
    -# Peking (Bejing) time zone was recognized.  Since that date, China
    -# has two of 'em -- Peking's and Urumqi (named after the capital of
    +# Peking (Beijing) time zone was recognized.  Since that date, China
    +# has two of 'em - Peking's and Ürümqi (named after the capital of
     # the Xinjiang Uyghur Autonomous Region).  I don't know about DST for it.
     #
     # . . .I just deleted the DST table and this editor makes it too
    -# painful to suck in another copy..  So, here is what I have for
    +# painful to suck in another copy.  So, here is what I have for
     # DST start/end dates for Peking's time zone (info from AP):
     #
     #     1986 May 4 - Sept 14
    @@ -347,15 +324,16 @@ Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
     # CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
     # CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
     
    -# From Paul Eggert (2006-03-22):
    -# Shanks & Pottenger write that China (except for Hong Kong and Macau)
    -# has had a single time zone since 1980 May 1, observing summer DST
    -# from 1986 through 1991; this contradicts Devine's
    -# note about Time magazine, though apparently _something_ happened in 1986.
    -# Go with Shanks & Pottenger for now.  I made up names for the other
    -# pre-1980 time zones.
    +# From Paul Eggert (2008-02-11):
    +# Jim Mann, "A clumsy embrace for another western custom: China on daylight
    +# time - sort of", Los Angeles Times, 1986-05-05 ... [says] that China began
    +# observing daylight saving time in 1986.
     
    -# From Shanks & Pottenger:
    +# From Paul Eggert (2014-06-30):
    +# Shanks & Pottenger have China switching to a single time zone in 1980, but
    +# this doesn't seem to be correct.  They also write that China observed summer
    +# DST from 1986 through 1991, which seems to match the above commentary, so
    +# go with them for DST rules as follows:
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Shang	1940	only	-	Jun	 3	0:00	1:00	D
     Rule	Shang	1940	1941	-	Oct	 1	0:00	0	S
    @@ -369,7 +347,7 @@ Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
     # historic timezones from some Taiwan websites.  And yes, there are official
     # Chinese names for these locales (before 1949).
     #
    -# From Jesper Norgaard Welen (2006-07-14):
    +# From Jesper Nørgaard Welen (2006-07-14):
     # I have investigated the timezones around 1970 on the
     # http://www.astro.com/atlas site [with provinces and county
     # boundaries summarized below]....  A few other exceptions were two
    @@ -380,65 +358,97 @@ Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
     # (could be true), for the moment I am assuming that those two
     # counties are mistakes in the astro.com data.
     
    -# From Paul Eggert (2008-02-11):
    -# I just now checked Google News for western news sources that talk
    -# about China's single time zone, and couldn't find anything before 1986
    -# talking about China being in one time zone.  (That article was: Jim
    -# Mann, "A clumsy embrace for another western custom: China on daylight
    -# time--sort of", Los Angeles Times, 1986-05-05.  By the way, this
    -# article confirms the tz database's data claiming that China began
    -# observing daylight saving time in 1986.
    -#
    -# From Thomas S. Mullaney (2008-02-11):
    -# I think you're combining two subjects that need to treated
    -# separately: daylight savings (which, you're correct, wasn't
    -# implemented until the 1980s) and the unified time zone centered near
    -# Beijing (which was implemented in 1949). Briefly, there was also a
    -# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
    -# ceased, and the second eventually recognized (again, in the 1980s).
    -#
    -# From Paul Eggert (2008-06-30):
    -# There seems to be a good chance China switched to a single time zone in 1949
    -# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
    -# reliable documentary source saying so yet, so for now we still go with
    -# Shanks & Pottenger.
    -
    -# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
    +# From Paul Eggert (2014-06-30):
    +# Alois Treindl kindly sent me translations of the following two sources:
    +#
    +# (1)
    +# Guo Qingsheng (National Time-Service Center, CAS, Xi'an 710600, China)
    +# Beijing Time at the Beginning of the PRC
    +# China Historical Materials of Science and Technology
    +# (Zhongguo ke ji shi liao, 中国科技史料), Vol. 24, No. 1 (2003)
    +# It gives evidence that at the beginning of the PRC, Beijing time was
    +# officially apparent solar time!  However, Guo also says that the
    +# evidence is dubious, as the relevant institute of astronomy had not
    +# been taken over by the PRC yet.  It's plausible that apparent solar
    +# time was announced but never implemented, and that people continued
    +# to use UT+8.  As the Shanghai radio station (and I presume the
    +# observatory) was still under control of French missionaries, it
    +# could well have ignored any such mandate.
    +#
    +# (2)
    +# Guo Qing-sheng (Shaanxi Astronomical Observatory, CAS, Xi'an 710600, China)
    +# A Study on the Standard Time Changes for the Past 100 Years in China
    +# [undated and unknown publication location]
    +# It says several things:
    +#   * The Qing dynasty used local apparent solar time throughout China.
    +#   * The Republic of China instituted Beijing mean solar time effective
    +#     the official calendar book of 1914.
    +#   * The French Concession in Shanghai set up signal stations in
    +#     French docks in the 1890s, controlled by Xujiahui (Zikawei)
    +#     Observatory and set to local mean time.
    +#   * "From the end of the 19th century" it changed to UT+8.
    +#   * Chinese Customs (by then reduced to a tool of foreign powers)
    +#     eventually standardized on this time for all ports, and it
    +#     became used by railways as well.
    +#   * In 1918 the Central Observatory proposed dividing China into
    +#     five time zones (see below for details).  This caught on
    +#     at first only in coastal areas observing UT+8.
    +#   * During WWII all of China was in theory was at UT+7.  In practice
    +#     this was ignored in the west, and I presume was ignored in
    +#     Japanese-occupied territory.
    +#   * Japanese-occupied Manchuria was at UT+9, i.e., Japan time.
    +#   * The five-zone plan was resurrected after WWII and officially put into
    +#     place (with some modifications) in March 1948.  It's not clear
    +#     how well it was observed in areas under Nationalist control.
    +#   * The People's Liberation Army used UT+8 during the civil war.
    +#
    +# An AP article "Shanghai Internat'l Area Little Changed" in the
    +# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
    +# different - the occupied districts going by Tokyo time, an hour
    +# ahead of that prevailing in the rest of Shanghai."  Guess that the
    +# Xujiahui Observatory was under French control and stuck with UT+8.
    +#
    +# In earlier versions of this file, China had many separate Zone entries, but
    +# this was based on what were apparently incorrect data in Shanks & Pottenger.
    +# This has now been simplified to the two entries Asia/Shanghai and
    +# Asia/Urumqi, with the others being links for backward compatibility.
    +# Proposed in 1918 and theoretically in effect until 1949 (although in practice
    +# mainly observed in coastal areas), the five zones were:
    +#
    +# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
    +# Asia/Harbin (currently a link to Asia/Shanghai)
     # Heilongjiang (except Mohe county), Jilin
    -Zone	Asia/Harbin	8:26:44	-	LMT	1928 # or Haerbin
    -			8:30	-	CHAT	1932 Mar # Changbai Time
    -			8:00	-	CST	1940
    -			9:00	-	CHAT	1966 May
    -			8:30	-	CHAT	1980 May
    -			8:00	PRC	C%sT
    -# Zhongyuan Time ("Central plain Time")
    +#
    +# Zhongyuan Time ("Central plain Time") UT+8
    +# Asia/Shanghai
     # most of China
    -# Milne gives 8:05:56.7; round to nearest.
    -Zone	Asia/Shanghai	8:05:57	-	LMT	1928
    -			8:00	Shang	C%sT	1949
    -			8:00	PRC	C%sT
    -# Long-shu Time (probably due to Long and Shu being two names of that area)
    +# This currently represents most other zones as well,
    +# as apparently these regions have been the same since 1970.
    +# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
    +# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
    +#
    +# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
    +# Asia/Chongqing (currently a link to Asia/Shanghai)
     # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
     # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
     # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
     # Yangchun, Yangjiang, Yu'nan, and Yunfu.
    -Zone	Asia/Chongqing	7:06:20	-	LMT	1928 # or Chungking
    -			7:00	-	LONT	1980 May # Long-shu Time
    -			8:00	PRC	C%sT
    -# Xin-zang Time ("Xinjiang-Tibet Time")
    +#
    +# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
    +# Asia/Urumqi
    +# This currently represents Kunlun Time as well,
    +# as apparently the two regions have been the same since 1970.
     # The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
     # the Guangdong counties  Xuwen, Haikang, Suixi, Lianjiang,
     # Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
     # east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
    -# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
    +# east Xinjiang, including Ürümqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
     # Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
     # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
     # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
    -Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
    -			6:00	-	URUT	1980 May # Urumqi Time
    -			8:00	PRC	C%sT
    -# Kunlun Time
    +#
    +# Kunlun Time UT+5.5
    +# Asia/Kashgar (currently a link to Asia/Urumqi)
     # West Tibet, including Pulan, Aheqi, Shufu, Shule;
     # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
     # Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
    @@ -455,9 +465,9 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
     # population of Xinjiang, typically use "Xinjiang time" which is two
     # hours behind Beijing time, or UTC +0600. The government of the Xinjiang
     # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
    -# local governments such as the Urumqi city government use both times in
    +# local governments such as the Ürümqi city government use both times in
     # publications, referring to what is popularly called Xinjiang time as
    -# "Urumqi time." When Uyghurs make an appointment in the Uyghur language
    +# "Ürümqi time." When Uyghurs make an appointment in the Uyghur language
     # they almost invariably use Xinjiang time.
     #
     # (Their ethnic Han compatriots would typically have no clue of its
    @@ -469,21 +479,6 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
     # the province not having dual times but four times in use at the same
     # time. Some areas remained on standard Xinjiang time or Beijing time and
     # others moving their clocks ahead.)
    -#
    -# ...an example of an official website using of Urumqi time.
    -#
    -# The first few lines of the Google translation of
    -# 
    -# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39
    -# 
    -# (retrieved 2009-10-13)
    -# > Urumqi fire seven people are missing the alleged losses of at least
    -# > 500 million yuan
    -# >
    -# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20),
    -# > Urumqi City Department of International Plaza Luther Qiantang River
    -# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men
    -# > have worked continuously for 22 hours...
     
     # From Luther Ma (2009-11-19):
     # With the risk of being redundant to previous answers these are the most common
    @@ -494,7 +489,7 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
     # 3. Urumqi...
     # 4. Kashgar...
     # ...
    -# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the
    +# 5. It seems that Uyghurs in Ürümqi has been using Xinjiang since at least the
     # 1960's. I know of one Han, now over 50, who grew up in the surrounding
     # countryside and used Xinjiang time as a child.
     #
    @@ -506,10 +501,55 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
     # Autonomous Region under the PRC. (Before that Uyghurs, of course, would also
     # not be using Beijing time, but some local time.)
     
    -Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
    -			5:30	-	KAST	1940	 # Kashgar Time
    -			5:00	-	KAST	1980 May
    +# From David Cochrane (2014-03-26):
    +# Just a confirmation that Ürümqi time was implemented in Ürümqi on 1 Feb 1986:
    +# http://content.time.com/time/magazine/article/0,9171,960684,00.html
    +
    +# From Luther Ma (2014-04-22):
    +# I have interviewed numerous people of various nationalities and from
    +# different localities in Xinjiang and can confirm the information in Guo's
    +# report regarding Xinjiang, as well as the Time article reference by David
    +# Cochrane.  Whether officially recognized or not (and both are officially
    +# recognized), two separate times have been in use in Xinjiang since at least
    +# the Cultural Revolution: Xinjiang Time (XJT), aka Ürümqi Time or local time;
    +# and Beijing Time.  There is no confusion in Xinjiang as to which name refers
    +# to which time. Both are widely used in the province, although in some
    +# population groups might be use one to the exclusion of the other.  The only
    +# problem is that computers and smart phones list Ürümqi (or Kashgar) as
    +# having the same time as Beijing.
    +
    +# From Paul Eggert (2014-06-30):
    +# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
    +# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
    +# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
    +# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
    +# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
    +#
    +# Xinjiang Time is well-documented as being officially recognized.  E.g., see
    +# "The Working-Calendar for The Xinjiang Uygur Autonomous Region Government"
    +#  (2014-04-22).
    +# Unfortunately, we have no good records of time in Xinjiang before 1986.
    +# During the 20th century parts of Xinjiang were ruled by the Qing dynasty,
    +# the Republic of China, various warlords, the First and Second East Turkestan
    +# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
    +# China, and tracking down all these organizations' timekeeping rules would be
    +# quite a trick.  Approximate this lost history by a transition from LMT to
    +# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
    +# which happens to be the date given by Shanks & Pottenger (no doubt as a
    +# guess) as the transition from LMT.  Ignore the usage of UT+8 before
    +# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
    +# that the sort of users who prefer Asia/Urumqi now typically ignored the
    +# UT+8 mandate back then.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Beijing time, used throughout China; represented by Shanghai.
    +Zone	Asia/Shanghai	8:05:43	-	LMT	1901
    +			8:00	Shang	C%sT	1949
     			8:00	PRC	C%sT
    +# Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi
    +# / Wulumuqi.  (Please use Asia/Shanghai if you prefer Beijing time.)
    +Zone	Asia/Urumqi	5:50:20	-	LMT	1928
    +			6:00	-	XJT
     
     
     # Hong Kong (Xianggang)
    @@ -524,15 +564,11 @@ Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
     # and incorrect rules. Although the exact switch over time is missing, I
     # think 3:30 is correct. The official DST record for Hong Kong can be
     # obtained from
    -# 
     # http://www.hko.gov.hk/gts/time/Summertime.htm
    -# .
     
     # From Arthur David Olson (2009-10-28):
     # Here are the dates given at
    -# 
     # http://www.hko.gov.hk/gts/time/Summertime.htm
    -# 
     # as of 2009-10-28:
     # Year        Period
     # 1941        1 Apr to 30 Sep
    @@ -612,35 +648,113 @@ Zone	Asia/Hong_Kong	7:36:42 -	LMT	1904 Oct 30
     
     # Taiwan
     
    -# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
    -# was still controlled by Japan.  This is hard to believe, but we don't
    -# have any other information.
    -
     # From smallufo (2010-04-03):
    -# According to Taiwan's CWB,
    -# 
    +# According to Taiwan's CWB [Central Weather Bureau],
     # http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm
    -# 
     # Taipei has DST in 1979 between July 1st and Sep 30.
     
    -# From Arthur David Olson (2010-04-07):
    -# Here's Google's translation of the table at the bottom of the "summert.htm" page:
    -# Decade 	                                                    Name                      Start and end date
    -# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time               May 1 to September 30
    -# 41 years of the Republic of China (AD 1952)                 Daylight Saving Time      March 1 to October 31
    -# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time      April 1 to October 31
    -# In the 44 years to 45 years (AD 1955-1956 years)            Daylight Saving Time      April 1 to September 30
    -# Republic of China 46 years to 48 years (AD 1957-1959)       Summer Time               April 1 to September 30
    -# Republic of China 49 years to 50 years (AD 1960-1961)       Summer Time               June 1 to September 30
    -# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
    -# Republic of China 63 years to 64 years (1974-1975 AD)       Daylight Saving Time      April 1 to September 30
    -# Republic of China 65 years to 67 years (1976-1978 AD)       Stop Daylight Saving Time
    -# Republic of China 68 years (AD 1979)                        Daylight Saving Time      July 1 to September 30
    -# Republic of China since 69 years (AD 1980)                  Stop Daylight Saving Time
    +# From Yu-Cheng Chuang (2013-07-12):
    +# On Dec 28, 1895, the Meiji Emperor announced Ordinance No. 167 of
    +# Meiji Year 28 "The clause about standard time", mentioned that
    +# Taiwan and Penghu Islands, as well as Yaeyama and Miyako Islands
    +# (both in Okinawa) adopt the Western Standard Time which is based on
    +# 120E. The adoption began from Jan 1, 1896. The original text can be
    +# found on Wikisource:
    +# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
    +# ... This could be the first adoption of time zone in Taiwan, because
    +# during the Qing Dynasty, it seems that there was no time zone
    +# declared officially.
    +#
    +# Later, in the beginning of World War II, on Sep 25, 1937, the Showa
    +# Emperor announced Ordinance No. 529 of Showa Year 12 "The clause of
    +# revision in the ordinance No. 167 of Meiji year 28 about standard
    +# time", in which abolished the adoption of Western Standard Time in
    +# western islands (listed above), which means the whole Japan
    +# territory, including later occupations, adopt Japan Central Time
    +# (UTC+9). The adoption began on Oct 1, 1937. The original text can
    +# be found on Wikisource:
    +# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
    +#
    +# That is, the time zone of Taipei switched to UTC+9 on Oct 1, 1937.
    +
    +# From Yu-Cheng Chuang (2014-07-02):
    +# I've found more evidence about when the time zone was switched from UTC+9
    +# back to UTC+8 after WW2.  I believe it was on Sep 21, 1945.  In a document
    +# during Japanese era [1] in which the officer told the staff to change time
    +# zone back to Western Standard Time (UTC+8) on Sep 21.  And in another
    +# history page of National Cheng Kung University [2], on Sep 21 there is a
    +# note "from today, switch back to Western Standard Time".  From these two
    +# materials, I believe that the time zone change happened on Sep 21.  And
    +# today I have found another monthly journal called "The Astronomical Herald"
    +# from The Astronomical Society of Japan [3] in which it mentioned the fact
    +# that:
    +#
    +# 1. Standard Time of the Country (Japan) was adopted on Jan 1, 1888, using
    +# the time at 135E (GMT+9)
    +#
    +# 2. Standard Time of the Country was renamed to Central Standard Time, on Jan
    +# 1, 1898, and on the same day, the new territories Taiwan and Penghu islands,
    +# as well as Yaeyama and Miyako islands, adopted a new time zone called
    +# Western Standard Time, which is in GMT+8.
    +#
    +# 3. Western Standard Time was deprecated on Sep 30, 1937. From then all the
    +# territories of Japan adopted the same time zone, which is Central Standard
    +# Time.
    +#
    +# [1] Academica Historica, Taiwan:
    +# http://163.29.208.22:8080/govsaleShowImage/connect_img.php?s=00101738900090036&e=00101738900090037
    +# [2] Nat'l Cheng Kung University 70th Anniversary Special Site:
    +# http://www.ncku.edu.tw/~ncku70/menu/001/01_01.htm
    +# [3] Yukio Niimi, The Standard Time in Japan (1997), p.475:
    +# http://www.asj.or.jp/geppou/archive_open/1997/pdf/19971001c.pdf
    +
    +# Yu-Cheng Chuang (2014-07-03):
    +# I finally have found the real official gazette about changing back to
    +# Western Standard Time on Sep 21 in Taiwan.  It's Taiwan Governor-General
    +# Bulletin No. 386 in Showa 20 years (1945), published on Sep 19, 1945. [1] ...
    +# [It] abolishes Bulletin No. 207 in Showa 12 years (1937), which is a local
    +# bulletin in Taiwan for that Ordinance No. 529. It also mentioned that 1am on
    +# Sep 21, 1945 will be 12am on Sep 21.  I think this bulletin is much more
    +# official than the one I mentioned in my first mail, because it's from the
    +# top-level government in Taiwan. If you're going to quote any resource, this
    +# would be a good one.
    +# [1] Taiwan Governor-General Gazette, No. 1018, Sep 19, 1945:
    +# http://db2.th.gov.tw/db2/view/viewImg.php?imgcode=0072031018a&num=19&bgn=019&end=019&otherImg=&type=gener
    +
    +# From Yu-Cheng Chuang (2014-07-02):
    +# In 1946, DST in Taiwan was from May 15 and ended on Sep 30. The info from
    +# Central Weather Bureau website was not correct.
    +#
    +# Original Bulletin:
    +# http://subtpg.tpg.gov.tw/og/image2.asp?f=03502F0AKM1AF
    +# http://subtpg.tpg.gov.tw/og/image2.asp?f=0350300AKM1B0 (cont.)
    +#
    +# In 1947, DST in Taiwan was expanded to Oct 31. There is a backup of that
    +# telegram announcement from Taiwan Province Government:
    +#
    +# http://subtpg.tpg.gov.tw/og/image2.asp?f=0360310AKZ431
    +#
    +# Here is a brief translation:
    +#
    +#   The Summer Time this year is adopted from midnight Apr 15 until Sep 20
    +#   midnight. To save (energy?) consumption, we're expanding Summer Time
    +#   adoption till Oct 31 midnight.
    +#
    +# The Central Weather Bureau website didn't mention that, however it can
    +# be found from historical government announcement database.
    +
    +# From Paul Eggert (2014-07-03):
    +# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
    +# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
    +# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	Taiwan	1945	1951	-	May	1	0:00	1:00	D
    -Rule	Taiwan	1945	1951	-	Oct	1	0:00	0	S
    +Rule	Taiwan	1946	only	-	May	15	0:00	1:00	D
    +Rule	Taiwan	1946	only	-	Oct	1	0:00	0	S
    +Rule	Taiwan	1947	only	-	Apr	15	0:00	1:00	D
    +Rule	Taiwan	1947	only	-	Nov	1	0:00	0	S
    +Rule	Taiwan	1948	1951	-	May	1	0:00	1:00	D
    +Rule	Taiwan	1948	1951	-	Oct	1	0:00	0	S
     Rule	Taiwan	1952	only	-	Mar	1	0:00	1:00	D
     Rule	Taiwan	1952	1954	-	Nov	1	0:00	0	S
     Rule	Taiwan	1953	1959	-	Apr	1	0:00	1:00	D
    @@ -648,11 +762,14 @@ Rule	Taiwan	1955	1961	-	Oct	1	0:00	0	S
     Rule	Taiwan	1960	1961	-	Jun	1	0:00	1:00	D
     Rule	Taiwan	1974	1975	-	Apr	1	0:00	1:00	D
     Rule	Taiwan	1974	1975	-	Oct	1	0:00	0	S
    -Rule	Taiwan	1979	only	-	Jun	30	0:00	1:00	D
    -Rule	Taiwan	1979	only	-	Sep	30	0:00	0	S
    +Rule	Taiwan	1979	only	-	Jul	1	0:00	1:00	D
    +Rule	Taiwan	1979	only	-	Oct	1	0:00	0	S
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Taipei	8:06:00 -	LMT	1896 # or Taibei or T'ai-pei
    +# Taipei or Taibei or T'ai-pei
    +Zone	Asia/Taipei	8:06:00 -	LMT	1896 Jan  1
    +			8:00	-	JWST	1937 Oct  1
    +			9:00	-	JST	1945 Sep 21  1:00
     			8:00	Taiwan	C%sT
     
     # Macau (Macao, Aomen)
    @@ -672,7 +789,7 @@ Rule	Macau	1975	1977	-	Apr	Sun>=15	3:30	1:00	S
     Rule	Macau	1978	1980	-	Apr	Sun>=15	0:00	1:00	S
     Rule	Macau	1978	1980	-	Oct	Sun>=15	0:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Macau	7:34:20 -	LMT	1912
    +Zone	Asia/Macau	7:34:20 -	LMT	1912 Jan  1
     			8:00	Macau	MO%sT	1999 Dec 20 # return to China
     			8:00	PRC	C%sT
     
    @@ -721,7 +838,7 @@ Link	Asia/Nicosia	Europe/Nicosia
     # republic has changed its time zone back to that of Moscow.  As a result it
     # is now just four hours ahead of Greenwich Mean Time, rather than five hours
     # ahead.  The switch was decreed by the pro-Western president of Georgia,
    -# Mikhail Saakashvili, who said the change was partly prompted by the process
    +# Mikheil Saakashvili, who said the change was partly prompted by the process
     # of integration into Europe.
     
     # From Teimuraz Abashidze (2005-11-07):
    @@ -734,29 +851,31 @@ Link	Asia/Nicosia	Europe/Nicosia
     # I don't know what can be done, especially knowing that some years ago our
     # DST rules where changed THREE TIMES during one month.
     
    +# Milne 1899 says Tbilisi (Tiflis) time was 2:59:05.7.
    +# Byalokoz 1919 says Georgia was 2:59:11.
    +# Go with Byalokoz.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
    -			2:59:16	-	TBMT	1924 May  2 # Tbilisi Mean Time
    +Zone	Asia/Tbilisi	2:59:11 -	LMT	1880
    +			2:59:11	-	TBMT	1924 May  2 # Tbilisi Mean Time
     			3:00	-	TBIT	1957 Mar    # Tbilisi Time
    -			4:00 RussiaAsia TBI%sT	1991 Mar 31 2:00s
    +			4:00 RussiaAsia TBI%sT	1991 Mar 31  2:00s
     			3:00	1:00	TBIST	1991 Apr  9 # independence
    -			3:00 RussiaAsia GE%sT	1992 # Georgia Time
    +			3:00 RussiaAsia GE%sT	1992        # Georgia Time
     			3:00 E-EurAsia	GE%sT	1994 Sep lastSun
     			4:00 E-EurAsia	GE%sT	1996 Oct lastSun
     			4:00	1:00	GEST	1997 Mar lastSun
     			4:00 E-EurAsia	GE%sT	2004 Jun 27
    -			3:00 RussiaAsia	GE%sT	2005 Mar lastSun 2:00
    +			3:00 RussiaAsia	GE%sT	2005 Mar lastSun  2:00
     			4:00	-	GET
     
     # East Timor
     
     # See Indonesia for the 1945 transition.
     
    -# From Joao Carrascalao, brother of the former governor of East Timor, in
    -# 
    +# From João Carrascalão, brother of the former governor of East Timor, in
     # East Timor may be late for its millennium
    -#  (1999-12-26/31):
    +#  (1999-12-26/31):
     # Portugal tried to change the time forward in 1974 because the sun
     # rises too early but the suggestion raised a lot of problems with the
     # Timorese and I still don't think it would work today because it
    @@ -766,25 +885,25 @@ Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
     # We don't have any record of the above attempt.
     # Most likely our records are incomplete, but we have no better data.
     
    -# 
     # From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
    -# (2000-08-16):
    +# http://www.hri.org/news/world/undh/2000/00-08-16.undh.html
    +# (2000-08-16):
     # The Cabinet of the East Timor Transition Administration decided
     # today to advance East Timor's time by one hour.  The time change,
     # which will be permanent, with no seasonal adjustment, will happen at
     # midnight on Saturday, September 16.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Dili	8:22:20 -	LMT	1912
    +Zone	Asia/Dili	8:22:20 -	LMT	1912 Jan  1
     			8:00	-	TLT	1942 Feb 21 23:00 # E Timor Time
     			9:00	-	JST	1945 Sep 23
     			9:00	-	TLT	1976 May  3
    -			8:00	-	WITA	2000 Sep 17 00:00
    +			8:00	-	WITA	2000 Sep 17  0:00
     			9:00	-	TLT
     
     # India
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
    +Zone	Asia/Kolkata	5:53:28 -	LMT	1880        # Kolkata
     			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
     			6:30	-	BURT	1942 May 15 # Burma Time
     			5:30	-	IST	1942 Sep
    @@ -798,7 +917,7 @@ Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
     # Indonesia
     #
     # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
    -# 
    +# http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime
     # says that Indonesia's time zones changed on 1988-01-01.  Looking at some
     # time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
     # and Kalimantan Tengah) switching from UTC+8 to UTC+7.
    @@ -810,7 +929,7 @@ Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
     # other formal surrender ceremonies were September 9, 11, and 13, plus
     # September 12 for the regional surrender to Mountbatten in Singapore.
     # These would be the earliest possible times for a change.
    -# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
    +# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
     # Traditionnelles, 1987, Paris) says that Java and Madura switched
     # from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
     # (Hollandia).  For now, assume all Indonesian locations other than Jayapura
    @@ -835,7 +954,7 @@ Zone Asia/Jakarta	7:07:12 -	LMT	1867 Aug 10
     # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
     # but this must be a typo.
     			7:07:12	-	BMT	1923 Dec 31 23:47:12 # Batavia
    -			7:20	-	JAVT	1932 Nov	 # Java Time
    +			7:20	-	JAVT	1932 Nov    # Java Time
     			7:30	-	WIB	1942 Mar 23
     			9:00	-	JST	1945 Sep 23
     			7:30	-	WIB	1948 May
    @@ -861,7 +980,7 @@ Zone Asia/Makassar	7:57:36 -	LMT	1920
     # Maluku Islands, West Papua, Papua
     Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
     			9:00	-	WIT	1944 Sep  1
    -			9:30	-	CST	1964
    +			9:30	-	ACST	1964
     			9:00	-	WIT
     
     # Iran
    @@ -927,7 +1046,7 @@ Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
     # Several of my users have reported that Iran will not observe DST anymore:
     # http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
     #
    -# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
    +# From Reuters (2007-09-16), with a heads-up from Jesper Nørgaard Welen:
     # ... the Guardian Council ... approved a law on Sunday to re-introduce
     # daylight saving time ...
     # http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
    @@ -993,7 +1112,7 @@ Rule	Iran	2036	2037	-	Mar	21	0:00	1:00	D
     Rule	Iran	2036	2037	-	Sep	21	0:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Tehran	3:25:44	-	LMT	1916
    -			3:25:44	-	TMT	1946	# Tehran Mean Time
    +			3:25:44	-	TMT	1946     # Tehran Mean Time
     			3:30	-	IRST	1977 Nov
     			4:00	Iran	IR%sT	1979
     			3:30	Iran	IR%sT
    @@ -1018,17 +1137,11 @@ Zone	Asia/Tehran	3:25:44	-	LMT	1916
     # From Steffen Thorsen (2008-03-10):
     # The cabinet in Iraq abolished DST last week, according to the following
     # news sources (in Arabic):
    -# 
     # http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
    -# 
    -# 
     # http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
    -# 
     #
     # We have published a short article in English about the change:
    -# 
     # http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
    -# 
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Iraq	1982	only	-	May	1	0:00	1:00	D
    @@ -1037,14 +1150,14 @@ Rule	Iraq	1983	only	-	Mar	31	0:00	1:00	D
     Rule	Iraq	1984	1985	-	Apr	1	0:00	1:00	D
     Rule	Iraq	1985	1990	-	Sep	lastSun	1:00s	0	S
     Rule	Iraq	1986	1990	-	Mar	lastSun	1:00s	1:00	D
    -# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
    +# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the ':01' is a typo.
     # Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
     #
     Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	D
     Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Baghdad	2:57:40	-	LMT	1890
    -			2:57:36	-	BMT	1918	    # Baghdad Mean Time?
    +			2:57:36	-	BMT	1918     # Baghdad Mean Time?
     			3:00	-	AST	1982 May
     			3:00	Iraq	A%sT
     
    @@ -1272,7 +1385,7 @@ Rule	Zion	2013	max	-	Oct	lastSun	2:00	0	S
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
    -			2:20:40	-	JMT	1918	# Jerusalem Mean Time?
    +			2:20:40	-	JMT	1918 # Jerusalem Mean Time?
     			2:00	Zion	I%sT
     
     
    @@ -1281,15 +1394,15 @@ Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
     
     # Japan
     
    -# `9:00' and `JST' is from Guy Harris.
    +# '9:00' and 'JST' is from Guy Harris.
     
     # From Paul Eggert (1995-03-06):
     # Today's _Asahi Evening News_ (page 4) reports that Japan had
    -# daylight saving between 1948 and 1951, but ``the system was discontinued
    -# because the public believed it would lead to longer working hours.''
    +# daylight saving between 1948 and 1951, but "the system was discontinued
    +# because the public believed it would lead to longer working hours."
     
    -# From Mayumi Negishi in the 2005-08-10 Japan Times
    -# :
    +# From Mayumi Negishi in the 2005-08-10 Japan Times:
    +# http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm
     # Occupation authorities imposed daylight-saving time on Japan on
     # [1948-05-01]....  But lack of prior debate and the execution of
     # daylight-saving time just three days after the bill was passed generated
    @@ -1313,7 +1426,8 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
     
     # From Hideyuki Suzuki (1998-11-09):
     # 'Tokyo' usually stands for the former location of Tokyo Astronomical
    -# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
    +# Observatory: 139 degrees 44' 40.90" E (9h 18m 58.727s),
    +# 35 degrees 39' 16.0" N.
     # This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
     # edited by National Astronomical Observatory of Japan....
     # JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
    @@ -1321,10 +1435,10 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
     
     # From Hideyuki Suzuki (1998-11-16):
     # The ordinance No. 51 (1886) established "standard time" in Japan,
    -# which stands for the time on E 135 degree.
    +# which stands for the time on 135 degrees E.
     # In the ordinance No. 167 (1895), "standard time" was renamed to "central
     # standard time".  And the same ordinance also established "western standard
    -# time", which stands for the time on E 120 degree....  But "western standard
    +# time", which stands for the time on 120 degrees E....  But "western standard
     # time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
     # 167, there is no mention regarding for what place western standard time is
     # standard....
    @@ -1332,27 +1446,33 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
     # I wrote "ordinance" above, but I don't know how to translate.
     # In Japanese it's "chokurei", which means ordinance from emperor.
     
    -# Shanks & Pottenger claim JST in use since 1896, and that a few
    -# places (e.g. Ishigaki) use +0800; go with Suzuki.  Guess that all
    -# ordinances took effect on Jan 1.
    +# From Yu-Cheng Chuang (2013-07-12):
    +# ...the Meiji Emperor announced Ordinance No. 167 of Meiji Year 28 "The clause
    +# about standard time" ... The adoption began from Jan 1, 1896.
    +# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
    +#
    +# ...the Showa Emperor announced Ordinance No. 529 of Showa Year 12 ... which
    +# means the whole Japan territory, including later occupations, adopt Japan
    +# Central Time (UTC+9). The adoption began on Oct 1, 1937.
    +# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
    -			9:00	-	JST	1896
    -			9:00	-	CJT	1938
    +			9:00	-	JST	1896 Jan  1
    +			9:00	-	JCST	1937 Oct  1
     			9:00	Japan	J%sT
     # Since 1938, all Japanese possessions have been like Asia/Tokyo.
     
     # Jordan
     #
    -# From 
    -# Jordan Week (1999-07-01)  via Steffen Thorsen (1999-09-09):
    +# From 
    +# Jordan Week (1999-07-01) via Steffen Thorsen (1999-09-09):
     # Clocks in Jordan were forwarded one hour on Wednesday at midnight,
     # in accordance with the government's decision to implement summer time
     # all year round.
     #
    -# From 
    -# Jordan Week (1999-09-30)  via Steffen Thorsen (1999-11-09):
    +# From 
    +# Jordan Week (1999-09-30) via Steffen Thorsen (1999-11-09):
     # Winter time starts today Thursday, 30 September. Clocks will be turned back
     # by one hour.  This is the latest government decision and it's final!
     # The decision was taken because of the increase in working hours in
    @@ -1372,9 +1492,7 @@ Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
     
     # From Steffen Thorsen (2009-04-02):
     # This single one might be good enough, (2009-03-24, Arabic):
    -# 
     # http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279
    -# 
     #
     # Google's translation:
     #
    @@ -1465,9 +1583,8 @@ Zone	Asia/Amman	2:23:44 -	LMT	1931
     # - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
     # - Oral switched from +5:00 to +4:00 in spring 1989.
     
    -# 
    -# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
    -# 
    +# From Kazakhstan Embassy's News Bulletin #11
    +#  (2005-03-21):
     # The Government of Kazakhstan passed a resolution March 15 abolishing
     # daylight saving time citing lack of economic benefits and health
     # complications coupled with a decrease in productivity.
    @@ -1500,10 +1617,10 @@ Zone	Asia/Qyzylorda	4:21:52 -	LMT	1924 May  2
     			6:00	-	KIZT	1982 Apr  1
     			5:00 RussiaAsia	KIZ%sT	1991
     			5:00	-	KIZT	1991 Dec 16 # independence
    -			5:00	-	QYZT	1992 Jan 19 2:00
    +			5:00	-	QYZT	1992 Jan 19  2:00
     			6:00 RussiaAsia	QYZ%sT	2005 Mar 15
     			6:00	-	QYZT
    -# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
    +# Aqtobe (aka Aktobe, formerly Aktyubinsk)
     Zone	Asia/Aqtobe	3:48:40	-	LMT	1924 May  2
     			4:00	-	AKTT	1930 Jun 21 # Aktyubinsk Time
     			5:00	-	AKTT	1981 Apr  1
    @@ -1523,7 +1640,7 @@ Zone	Asia/Aqtau	3:21:04	-	LMT	1924 May  2
     			6:00	-	SHET	1982 Apr  1
     			5:00 RussiaAsia	SHE%sT	1991
     			5:00	-	SHET	1991 Dec 16 # independence
    -			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun 2:00 # Aqtau Time
    +			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun  2:00 # Aqtau Time
     			4:00 RussiaAsia	AQT%sT	2005 Mar 15
     			5:00	-	AQTT
     # West Kazakhstan
    @@ -1532,7 +1649,7 @@ Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
     			5:00	-	URAT	1981 Apr  1
     			5:00	1:00	URAST	1981 Oct  1
     			6:00	-	URAT	1982 Apr  1
    -			5:00 RussiaAsia	URA%sT	1989 Mar 26 2:00
    +			5:00 RussiaAsia	URA%sT	1989 Mar 26  2:00
     			4:00 RussiaAsia	URA%sT	1991
     			4:00	-	URAT	1991 Dec 16 # independence
     			4:00 RussiaAsia	ORA%sT	2005 Mar 15 # Oral Time
    @@ -1543,7 +1660,7 @@ Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
     
     # From Paul Eggert (2005-08-15):
     # According to an article dated today in the Kyrgyzstan Development Gateway
    -# 
    +# http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml
     # Kyrgyzstan is canceling the daylight saving time system.  I take the article
     # to mean that they will leave their clocks at 6 hours ahead of UTC.
     # From Malik Abdugaliev (2005-09-21):
    @@ -1558,17 +1675,17 @@ Rule	Kyrgyz	1997	2004	-	Oct	lastSun	2:30	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
     			5:00	-	FRUT	1930 Jun 21 # Frunze Time
    -			6:00 RussiaAsia FRU%sT	1991 Mar 31 2:00s
    -			5:00	1:00	FRUST	1991 Aug 31 2:00 # independence
    -			5:00	Kyrgyz	KG%sT	2005 Aug 12    # Kyrgyzstan Time
    +			6:00 RussiaAsia FRU%sT	1991 Mar 31  2:00s
    +			5:00	1:00	FRUST	1991 Aug 31  2:00 # independence
    +			5:00	Kyrgyz	KG%sT	2005 Aug 12 # Kyrgyzstan Time
     			6:00	-	KGT
     
     ###############################################################################
     
     # Korea (North and South)
     
    -# From Annie I. Bang (2006-07-10) in
    -# :
    +# From Annie I. Bang (2006-07-10):
    +# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
     # The Ministry of Commerce, Industry and Energy has already
     # commissioned a research project [to reintroduce DST] and has said
     # the system may begin as early as 2008....  Korea ran a daylight
    @@ -1581,19 +1698,29 @@ Rule	ROK	1960	only	-	Sep	13	0:00	0	S
     Rule	ROK	1987	1988	-	May	Sun>=8	0:00	1:00	D
     Rule	ROK	1987	1988	-	Oct	Sun>=8	0:00	0	S
     
    +# From Paul Eggert (2014-07-01):
    +# The following entries are from Shanks & Pottenger, except that I
    +# guessed that time zone abbreviations through 1945 followed the same
    +# rules as discussed under Taiwan, with nominal switches from JST to KST
    +# when the respective cities were taken over by the Allies after WWII.
    +
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Seoul	8:27:52	-	LMT	1890
     			8:30	-	KST	1904 Dec
    -			9:00	-	KST	1928
    +			9:00	-	JCST	1928
     			8:30	-	KST	1932
    +			9:00	-	JCST	1937 Oct  1
    +			9:00	-	JST	1945 Sep  8
     			9:00	-	KST	1954 Mar 21
     			8:00	ROK	K%sT	1961 Aug 10
     			8:30	-	KST	1968 Oct
     			9:00	ROK	K%sT
     Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
     			8:30	-	KST	1904 Dec
    -			9:00	-	KST	1928
    +			9:00	-	JCST	1928
     			8:30	-	KST	1932
    +			9:00	-	JCST	1937 Oct  1
    +			9:00	-	JST	1945 Aug 24
     			9:00	-	KST	1954 Mar 21
     			8:00	-	KST	1961 Aug 10
     			9:00	-	KST
    @@ -1602,21 +1729,13 @@ Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
     
     # Kuwait
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -# From the Arab Times (2007-03-14):
    -# The Civil Service Commission (CSC) has approved a proposal forwarded
    -# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
    -# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
    -# .
    -# From Paul Eggert (2007-03-29):
    -# We don't know the details, or whether the approval means it'll happen,
    -# so for now we assume no DST.
     Zone	Asia/Kuwait	3:11:56 -	LMT	1950
     			3:00	-	AST
     
     # Laos
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9 # or Viangchan
    -			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
    +Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9       # or Viangchan
    +			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
     			7:00	-	ICT	1912 May
     			8:00	-	ICT	1931 May
     			7:00	-	ICT
    @@ -1657,8 +1776,8 @@ Rule	NBorneo	1935	1941	-	Sep	14	0:00	0:20	TS # one-Third Summer
     Rule	NBorneo	1935	1941	-	Dec	14	0:00	0	-
     #
     # peninsular Malaysia
    -# The data here are taken from Mok Ly Yng (2003-10-30)
    -# .
    +# taken from Mok Ly Yng (2003-10-30)
    +# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
     			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
    @@ -1670,12 +1789,12 @@ Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
     			7:30	-	MALT	1982 Jan  1
     			8:00	-	MYT	# Malaysia Time
     # Sabah & Sarawak
    -# From Paul Eggert (2006-03-22):
    -# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
    -# transition dates are from Mok Ly Yng.
    +# From Paul Eggert (2014-08-12):
    +# The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
    +# and 1982 transition dates are from Mok Ly Yng.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
    -			7:30	-	BORT	1933	# Borneo Time
    +			7:30	-	BORT	1933        # Borneo Time
     			8:00	NBorneo	BOR%sT	1942 Feb 16
     			9:00	-	JST	1945 Sep 12
     			8:00	-	BORT	1982 Jan  1
    @@ -1683,22 +1802,21 @@ Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
     
     # Maldives
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
    -			4:54:00	-	MMT	1960	# Male Mean Time
    -			5:00	-	MVT		# Maldives Time
    +Zone	Indian/Maldives	4:54:00 -	LMT	1880 # Male
    +			4:54:00	-	MMT	1960 # Male Mean Time
    +			5:00	-	MVT	# Maldives Time
     
     # Mongolia
     
     # Shanks & Pottenger say that Mongolia has three time zones, but
    -# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
    -# both say that it has just one.
    +# The USNO (1995-12-21) and the CIA map Standard Time Zones of the World
    +# (2005-03) both say that it has just one.
     
     # From Oscar van Vlijmen (1999-12-11):
    -# 
     # General Information Mongolia
    -#  (1999-09)
    +#  (1999-09)
     # "Time: Mongolia has two time zones. Three westernmost provinces of
    -# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
    +# Bayan-Ölgii, Uvs, and Hovd are one hour earlier than the capital city, and
     # the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
     # eight hours."
     
    @@ -1709,7 +1827,7 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
     # of implementation may have been different....
     # Some maps in the past have indicated that there was an additional time
     # zone in the eastern part of Mongolia, including the provinces of Dornod,
    -# Suhbaatar, and possibly Khentij.
    +# Sükhbaatar, and possibly Khentii.
     
     # From Paul Eggert (1999-12-15):
     # Naming and spelling is tricky in Mongolia.
    @@ -1723,10 +1841,10 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
     # (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
     # there are three time zones.
     #
    -# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
    -# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
    -#	Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
    -# Provinces [at 9:00]: Dornod, Sukhbaatar
    +# Provinces [at 7:00]: Bayan-Ölgii, Uvs, Khovd, Zavkhan, Govi-Altai
    +# Provinces [at 8:00]: Khövsgöl, Bulgan, Arkhangai, Khentii, Töv,
    +#	Bayankhongor, Övörkhangai, Dundgovi, Dornogovi, Ömnögovi
    +# Provinces [at 9:00]: Dornod, Sükhbaatar
     #
     # [The province of Selenge is omitted from the above lists.]
     
    @@ -1743,16 +1861,16 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
     # We have wildly conflicting information about Mongolia's time zones.
     # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
     # there is only one time zone and that DST is observed, citing Microsoft
    -# Windows XP as the source.  Risto Nykanen (2005-05-16) reports that
    +# Windows XP as the source.  Risto Nykänen (2005-05-16) reports that
     # travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
     # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
     # Washington, DC says there are two time zones, with DST observed.
     # He also found
    -# 
    +# http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&
     # which also says that there is DST, and which has a comment by "Toddius"
     # (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
     # The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
    -# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
    +# and some Eastern provinces are +9 GMT but Sükhbaatar Aimag is SUHK +8.5 GMT.
     # The SUKH timezone is new this year, it is one of the few things the
     # parliament passed during the tumultuous winter session."
     # For now, let's ignore this information, until we have more confirmation.
    @@ -1768,29 +1886,23 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
     # +08:00 instead. Different sources appear to disagree with the tz
     # database on this, e.g.:
     #
    -# 
     # http://www.timeanddate.com/worldclock/city.html?n=1026
    -# 
    -# 
     # http://www.worldtimeserver.com/current_time_in_MN.aspx
    -# 
     #
     # both say GMT+08:00.
     
     # From Steffen Thorsen (2008-03-31):
     # eznis airways, which operates several domestic flights, has a flight
     # schedule here:
    -# 
     # http://www.eznis.com/Container.jsp?id=112
    -# 
     # (click the English flag for English)
     #
    -# There it appears that flights between Choibalsan and Ulaanbatar arrive
    +# There it appears that flights between Choibalsan and Ulaanbaatar arrive
     # about 1:35 - 1:50 hours later in local clock time, no matter the
    -# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
    -# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
    +# direction, while Ulaanbaatar-Khovd takes 2 hours in the Eastern
    +# direction and 3:35 back, which indicates that Ulaanbaatar and Khovd are
     # in different time zones (like we know about), while Choibalsan and
    -# Ulaanbatar are in the same time zone (correction needed).
    +# Ulaanbaatar are in the same time zone (correction needed).
     
     # From Arthur David Olson (2008-05-19):
     # Assume that Choibalsan is indeed offset by 8:00.
    @@ -1806,7 +1918,7 @@ Rule	Mongol	1983	only	-	Oct	1	0:00	0	-
     # (1996-09) says 1996-10-25.  Go with Shanks & Pottenger through 1998.
     #
     # Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
    -# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
    +# in Choibalsan (more precisely, in Dornod and Sükhbaatar) took place
     # at 02:00 standard time, not at 00:00 local time as in the rest of
     # the country.  That would be odd, and possibly is a result of their
     # correction of 02:00 (in the previous edition) not being done correctly
    @@ -1822,13 +1934,13 @@ Rule	Mongol	2002	2006	-	Mar	lastSat	2:00	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
     Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
    -			6:00	-	HOVT	1978	# Hovd Time
    +			6:00	-	HOVT	1978     # Hovd Time
     			7:00	Mongol	HOV%sT
     # Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
     Zone	Asia/Ulaanbaatar 7:07:32 -	LMT	1905 Aug
    -			7:00	-	ULAT	1978	# Ulaanbaatar Time
    +			7:00	-	ULAT	1978     # Ulaanbaatar Time
     			8:00	Mongol	ULA%sT
    -# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
    +# Choibalsan, a.k.a. Bajan Tümen, Bajan Tumen, Chojbalsan,
     # Choybalsan, Sanbejse, Tchoibalsan
     Zone	Asia/Choibalsan	7:38:00 -	LMT	1905 Aug
     			7:00	-	ULAT	1978
    @@ -1860,7 +1972,7 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
     # 00:01 was to make it clear which day it was on.
     
     # From Paul Eggert (2002-03-15):
    -# Jesper Norgaard found this URL:
    +# Jesper Nørgaard found this URL:
     # http://www.pak.gov.pk/public/news/app/app06_dec.htm
     # (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
     # advance the clocks by one hour on the night between the first
    @@ -1892,43 +2004,30 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
     # Here is an article that Pakistan plan to introduce Daylight Saving Time
     # on June 1, 2008 for 3 months.
     #
    -# "... The federal cabinet on Wednesday announced a new conservation plan to help
    -# reduce load shedding by approving the closure of commercial centres at 9pm and
    -# moving clocks forward by one hour for the next three months.
    -# ...."
    +# "... The federal cabinet on Wednesday announced a new conservation plan to
    +# help reduce load shedding by approving the closure of commercial centres at
    +# 9pm and moving clocks forward by one hour for the next three months. ...."
     #
    -# 
     # http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
    -# 
    -# OR
    -# 
     # http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
    -# 
     
     # From Arthur David Olson (2008-05-19):
     # XXX--midnight transitions is a guess; 2008 only is a guess.
     
     # From Alexander Krivenyshev (2008-08-28):
     # Pakistan government has decided to keep the watches one-hour advanced
    -# for another 2 months--plan to return to Standard Time on October 31
    +# for another 2 months - plan to return to Standard Time on October 31
     # instead of August 31.
     #
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
    -# 
    -# OR
    -# 
     # http://dailymailnews.com/200808/28/news/dmbrn03.html
    -# 
     
     # From Alexander Krivenyshev (2009-04-08):
     # Based on previous media reports that "... proposed plan to
     # advance clocks by one hour from May 1 will cause disturbance
     # to the working schedules rather than bringing discipline in
     # official working."
    -# 
     # http://www.thenews.com.pk/daily_detail.asp?id=171280
    -# 
     #
     # recent news that instead of May 2009 - Pakistan plan to
     # introduce DST from April 15, 2009
    @@ -1936,15 +2035,8 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
     # FYI: Associated Press Of Pakistan
     # April 08, 2009
     # Cabinet okays proposal to advance clocks by one hour from April 15
    -# 
     # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1
    -# 
    -#
    -# or
    -#
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html
    -# 
     #
     # ....
     # The Federal Cabinet on Wednesday approved the proposal to
    @@ -1957,34 +2049,20 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
     # clocks backward by one hour from October 1. A formal announcement to
     # this effect will be made after the Prime Minister grants approval in
     # this regard."
    -# 
     # http://www.thenews.com.pk/updates.asp?id=87168
    -# 
     
     # From Alexander Krivenyshev (2009-09-28):
     # According to Associated Press Of Pakistan, it is confirmed that
    -# Pakistan clocks across the country would be turned back by an hour from October
    -# 1, 2009.
    +# Pakistan clocks across the country would be turned back by an hour from
    +# October 1, 2009.
     #
     # "Clocks to go back one hour from 1 Oct"
    -# 
     # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
    -# 
    -
    -# From Steffen Thorsen (2009-09-29):
    -# Alexander Krivenyshev wrote:
    -# > According to Associated Press Of Pakistan, it is confirmed that
    -# > Pakistan clocks across the country would be turned back by an hour from October
    -# > 1, 2009.
     #
    +# From Steffen Thorsen (2009-09-29):
     # Now they seem to have changed their mind, November 1 is the new date:
    -# 
     # http://www.thenews.com.pk/top_story_detail.asp?Id=24742
    -# 
     # "The country's clocks will be reversed by one hour on November 1.
     # Officials of Federal Ministry for Interior told this to Geo News on
     # Monday."
    @@ -1996,11 +2074,9 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
     #
     # We have confirmed this year's end date with both with the Ministry of
     # Water and Power and the Pakistan Electric Power Company:
    -# 
     # http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
    -# 
     
    -# From Christoph Goehre (2009-10-01):
    +# From Christoph Göhre (2009-10-01):
     # [T]he German Consulate General in Karachi reported me today that Pakistan
     # will go back to standard time on 1st of November.
     
    @@ -2016,22 +2092,17 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
     # Now, it seems that the decision to not observe DST in final:
     #
     # "Govt Withdraws Plan To Advance Clocks"
    -# 
     # http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041
    -# 
     #
     # "People laud PM's announcement to end DST"
    -# 
     # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2
    -# 
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
     Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
     Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
    -Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
    +Rule Pakistan	2008	2009	-	Nov	1	0:00	0	-
     Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
    -Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Karachi	4:28:12 -	LMT	1907
    @@ -2105,10 +2176,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # the PA has decided to implement DST in April.
     
     # From Paul Eggert (1999-09-20):
    -# Daoud Kuttab writes in
    -# 
    -# Holiday havoc
    -#  (Jerusalem Post, 1999-04-22) that
    +# Daoud Kuttab writes in Holiday havoc
    +# http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html
    +# (Jerusalem Post, 1999-04-22) that
     # the Palestinian National Authority changed to DST on 1999-04-15.
     # I vaguely recall that they switch back in October (sorry, forgot the source).
     # For now, let's assume that the spring switch was at 24:00,
    @@ -2121,7 +2191,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # A user from Gaza reported that Gaza made the change early because of
     # the Ramadan.  Next year Ramadan will be even earlier, so I think
     # there is a good chance next year's end date will be around two weeks
    -# earlier--the same goes for Jordan.
    +# earlier - the same goes for Jordan.
     
     # From Steffen Thorsen (2006-08-17):
     # I was informed by a user in Bethlehem that in Bethlehem it started the
    @@ -2140,7 +2210,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # I guess it is likely that next year's date will be moved as well,
     # because of the Ramadan.
     
    -# From Jesper Norgaard Welen (2007-09-18):
    +# From Jesper Nørgaard Welen (2007-09-18):
     # According to Steffen Thorsen's web site the Gaza Strip and the rest of the
     # Palestinian territories left DST early on 13.th. of September at 2:00.
     
    @@ -2157,16 +2227,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
     # the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
     #
    -# 
     # http://www.guardian.co.uk/world/feedarticle/7759001
    -# 
    -# 
     # http://www.abcnews.go.com/International/wireStory?id=5676087
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
    -# 
     
     # From Alexander Krivenyshev (2009-03-26):
     # According to the Palestine News Network (arabic.pnn.ps), Palestinian
    @@ -2174,24 +2237,17 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # 26 and continue until the night of 27 September 2009.
     #
     # (in Arabic)
    -# 
     # http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850
    -# 
     #
    -# or
     # (English translation)
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
    -# 
     
     # From Steffen Thorsen (2009-08-31):
     # Palestine's Council of Ministers announced that they will revert back to
     # winter time on Friday, 2009-09-04.
     #
     # One news source:
    -# 
     # http://www.safa.ps/ara/?action=showdetail&seid=4158
    -# 
     # (Palestinian press agency, Arabic),
     # Google translate: "Decided that the Palestinian government in Ramallah
     # headed by Salam Fayyad, the start of work in time for the winter of
    @@ -2200,9 +2256,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     #
     # We are not sure if Gaza will do the same, last year they had a different
     # end date, we will keep this page updated:
    -# 
     # http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
    -# 
     
     # From Alexander Krivenyshev (2009-09-02):
     # Seems that Gaza Strip will go back to Winter Time same date as West Bank.
    @@ -2212,51 +2266,35 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     #
     # "Winter time unite the West Bank and Gaza"
     # (from Palestinian National Authority):
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
    -# 
     
     # From Alexander Krivenyshev (2010-03-19):
     # According to Voice of Palestine DST will last for 191 days, from March
     # 26, 2010 till "the last Sunday before the tenth day of Tishri
     # (October), each year" (October 03, 2010?)
     #
    -# 
     # http://palvoice.org/forums/showthread.php?t=245697
    -# 
     # (in Arabic)
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_westbank03.html
    -# 
     
     # From Steffen Thorsen (2010-03-24):
     # ...Ma'an News Agency reports that Hamas cabinet has decided it will
     # start one day later, at 12:01am. Not sure if they really mean 12:01am or
     # noon though:
     #
    -# 
     # http://www.maannews.net/eng/ViewDetails.aspx?ID=271178
    -# 
     # (Ma'an News Agency)
     # "At 12:01am Friday, clocks in Israel and the West Bank will change to
     # 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
     
     # From Steffen Thorsen (2010-08-11):
     # According to several sources, including
    -# 
     # http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
    -# 
     # the clocks were set back one hour at 2010-08-11 00:00:00 local time in
     # Gaza and the West Bank.
     # Some more background info:
    -# 
     # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
    -# 
     
     # From Steffen Thorsen (2011-08-26):
     # Gaza and the West Bank did go back to standard time in the beginning of
    @@ -2264,13 +2302,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # 00:00 (so two periods of DST in 2011). The pause was because of
     # Ramadan.
     #
    -# 
     # http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
    -# 
     # Additional info:
    -# 
     # http://www.timeanddate.com/news/time/palestine-dst-2011.html
    -# 
     
     # From Alexander Krivenyshev (2011-08-27):
     # According to the article in The Jerusalem Post:
    @@ -2280,14 +2314,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # The Hamas government said on Saturday that it won't observe summertime after
     # the Muslim feast of Id al-Fitr, which begins on Tuesday..."
     # ...
    -# 
     # http://www.jpost.com/MiddleEast/Article.aspx?id=235650
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
    -# 
    -# The rules for Egypt are stolen from the `africa' file.
    +# The rules for Egypt are stolen from the 'africa' file.
     
     # From Steffen Thorsen (2011-09-30):
     # West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
    @@ -2295,26 +2324,18 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
     # So West Bank and Gaza now have the same time again.
     #
     # Many sources, including:
    -# 
     # http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
    -# 
     
     # From Steffen Thorsen (2012-03-26):
     # Palestinian news sources tell that both Gaza and West Bank will start DST
     # on Friday (Thursday midnight, 2012-03-29 24:00).
     # Some of many sources in Arabic:
    -# 
     # http://www.samanews.com/index.php?act=Show&id=122638
    -# 
     #
    -# 
     # http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html
    -# 
     #
     # Our brief summary:
    -# 
     # http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
    -# 
     
     # From Steffen Thorsen (2013-03-26):
     # The following news sources tells that Palestine will "start daylight saving
    @@ -2374,10 +2395,10 @@ Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
     			2:00 EgyptAsia	EE%sT	1967 Jun  5
     			2:00	Zion	I%sT	1996
     			2:00	Jordan	EE%sT	1999
    -			2:00 Palestine	EE%sT	2008 Aug 29 0:00
    +			2:00 Palestine	EE%sT	2008 Aug 29  0:00
     			2:00	-	EET	2008 Sep
     			2:00 Palestine	EE%sT	2010
    -			2:00	-	EET	2010 Mar 27 0:01
    +			2:00	-	EET	2010 Mar 27  0:01
     			2:00 Palestine	EE%sT	2011 Aug  1
     			2:00	-	EET	2012
     			2:00 Palestine	EE%sT
    @@ -2393,25 +2414,27 @@ Zone	Asia/Hebron	2:20:23	-	LMT	1900 Oct
     # no information
     
     # Philippines
    -# On 1844-08-16, Narciso Claveria, governor-general of the
    +# On 1844-08-16, Narciso Clavería, governor-general of the
     # Philippines, issued a proclamation announcing that 1844-12-30 was to
    -# be immediately followed by 1845-01-01.  Robert H. van Gent has a
    -# transcript of the decree in .
    -# The rest of the data are from Shanks & Pottenger.
    +# be immediately followed by 1845-01-01; see R.H. van Gent's
    +# History of the International Date Line
    +# http://www.staff.science.uu.nl/~gent0113/idl/idl_philippines.htm
    +# The rest of the data entries are from Shanks & Pottenger.
     
    -# From Paul Eggert (2006-04-25):
    -# Tomorrow's Manila Standard reports that the Philippines Department of
    -# Trade and Industry is considering adopting DST this June when the
    -# rainy season begins.  See
    -# .
    -# For now, we'll ignore this, since it's not definite and we lack details.
    -#
    -# From Jesper Norgaard Welen (2006-04-26):
    +# From Jesper Nørgaard Welen (2006-04-26):
     # ... claims that Philippines had DST last time in 1990:
     # http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
     # [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
     # but no details]
     
    +# From Paul Eggert (2014-08-14):
    +# The following source says DST may be instituted November-January and again
    +# March-June, but this is not definite.  It also says DST was last proclaimed
    +# during the Ramos administration (1992-1998); but again, no details.
    +# Carcamo D. PNoy urged to declare use of daylight saving time.
    +# Philippine Star 2014-08-05
    +# http://www.philstar.com/headlines/2014/08/05/1354152/pnoy-urged-declare-use-daylight-saving-time
    +
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Phil	1936	only	-	Nov	1	0:00	1:00	S
     Rule	Phil	1937	only	-	Feb	1	0:00	0	-
    @@ -2428,18 +2451,39 @@ Zone	Asia/Manila	-15:56:00 -	LMT	1844 Dec 31
     
     # Qatar
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Qatar	3:26:08 -	LMT	1920	# Al Dawhah / Doha
    +Zone	Asia/Qatar	3:26:08 -	LMT	1920     # Al Dawhah / Doha
     			4:00	-	GST	1972 Jun
     			3:00	-	AST
     
     # Saudi Arabia
    +#
    +# From Paul Eggert (2014-07-15):
    +# Time in Saudi Arabia and other countries in the Arabian peninsula was not
    +# standardized until relatively recently; we don't know when, and possibly it
    +# has never been made official.  Richard P Hunt, in "Islam city yielding to
    +# modern times", New York Times (1961-04-09), p 20, wrote that only airlines
    +# observed standard time, and that people in Jeddah mostly observed quasi-solar
    +# time, doing so by setting their watches at sunrise to 6 o'clock (or to 12
    +# o'clock for "Arab" time).
    +#
    +# The TZ database cannot represent quasi-solar time; airline time is the best
    +# we can do.  The 1946 foreign air news digest of the U.S. Civil Aeronautics
    +# Board (OCLC 42299995) reported that the "... Arabian Government, inaugurated
    +# a weekly Dhahran-Cairo service, via the Saudi Arabian cities of Riyadh and
    +# Jidda, on March 14, 1947".  Shanks & Pottenger guessed 1950; go with the
    +# earlier date.
    +#
    +# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
    +# time zones; the other zone, at UTC+4, was in the far eastern part of
    +# the country.  Ignore this, as it's before our 1970 cutoff.
    +#
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Riyadh	3:06:52 -	LMT	1950
    +Zone	Asia/Riyadh	3:06:52 -	LMT	1947 Mar 14
     			3:00	-	AST
     
     # Singapore
    -# The data here are taken from Mok Ly Yng (2003-10-30)
    -# .
    +# taken from Mok Ly Yng (2003-10-30)
    +# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
     			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
    @@ -2465,26 +2509,24 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
     
     # From Paul Eggert (1996-09-03):
     # "Sri Lanka advances clock by an hour to avoid blackout"
    -# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
    +# (, 1996-05-24,
     # no longer available as of 1999-08-17)
    -# reported ``the country's standard time will be put forward by one hour at
    -# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
    +# reported "the country's standard time will be put forward by one hour at
    +# midnight Friday (1830 GMT) 'in the light of the present power crisis'."
     #
     # From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
    -# by Shamindra in
    -# 
    -# Daily News - Hot News Section (1996-10-26)
    -# :
    +# by Shamindra in Daily News - Hot News Section
    +#  (1996-10-26):
     # With effect from 12.30 a.m. on 26th October 1996
     # Sri Lanka will be six (06) hours ahead of GMT.
     
    -# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
    +# From Jesper Nørgaard Welen (2006-04-14), quoting Sri Lanka News Online
     #  (2006-04-13):
     # 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
     # at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
     
     # From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
    -# 
    +# http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML
     # [The Tamil Tigers] never accepted the original 1996 time change and simply
     # kept their clocks set five and a half hours ahead of Greenwich Mean
     # Time (GMT), in line with neighbor India.
    @@ -2498,7 +2540,7 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
     # twice in 1996 and probably SL Government or its standardization
     # agencies never declared an abbreviation as a national standard.
     #
    -# I recollect before the recent change the government annoucemments
    +# I recollect before the recent change the government announcements
     # mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
     # Time and no mention was made about the abbreviation.
     #
    @@ -2508,7 +2550,7 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
     # item....
     #
     # Within Sri Lanka I think LKT is well known among computer users and
    -# adminsitrators.  In my opinion SLT may not be a good choice because the
    +# administrators.  In my opinion SLT may not be a good choice because the
     # nation's largest telcom / internet operator Sri Lanka Telcom is well
     # known by that abbreviation - simply as SLT (there IP domains are
     # slt.lk and sltnet.lk).
    @@ -2523,13 +2565,13 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Colombo	5:19:24 -	LMT	1880
    -			5:19:32	-	MMT	1906	# Moratuwa Mean Time
    +			5:19:32	-	MMT	1906        # Moratuwa Mean Time
     			5:30	-	IST	1942 Jan  5
     			5:30	0:30	IHST	1942 Sep
    -			5:30	1:00	IST	1945 Oct 16 2:00
    -			5:30	-	IST	1996 May 25 0:00
    -			6:30	-	LKT	1996 Oct 26 0:30
    -			6:00	-	LKT	2006 Apr 15 0:30
    +			5:30	1:00	IST	1945 Oct 16  2:00
    +			5:30	-	IST	1996 May 25  0:00
    +			6:30	-	LKT	1996 Oct 26  0:30
    +			6:00	-	LKT	2006 Apr 15  0:30
     			5:30	-	IST
     
     # Syria
    @@ -2580,7 +2622,7 @@ Rule	Syria	2006	only	-	Sep	22	0:00	0	-
     # Today the AP reported "Syria will switch to summertime at midnight Thursday."
     # http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
     Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
    -# From Jesper Norgard (2007-10-27):
    +# From Jesper Nørgaard (2007-10-27):
     # The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
     # not take place 1st November at 0:00 o'clock but 1st November at 24:00 or
     # rather Midnight between Thursday and Friday. This does make more sense than
    @@ -2589,7 +2631,7 @@ Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
     # it is implemented at midnight of the last workday before weekend...
     #
     # From Steffen Thorsen (2007-10-27):
    -# Jesper Norgaard Welen wrote:
    +# Jesper Nørgaard Welen wrote:
     #
     # > "Winter local time in Syria will be observed at midnight of Thursday 1
     # > November 2007, and the clock will be put back 1 hour."
    @@ -2605,8 +2647,7 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
     
     # From Stephen Colebourne (2008-03-17):
     # For everyone's info, I saw an IATA time zone change for [Syria] for
    -# this month (March 2008) in the last day or so...This is the data IATA
    -# are now using:
    +# this month (March 2008) in the last day or so....
     # Country     Time Standard   --- DST Start ---   --- DST End ---  DST
     # Name        Zone Variation   Time    Date        Time    Date
     # Variation
    @@ -2618,16 +2659,15 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
     # From Arthur David Olson (2008-03-17):
     # Here's a link to English-language coverage by the Syrian Arab News
     # Agency (SANA)...
    -# 
     # http://www.sana.sy/eng/21/2008/03/11/165173.htm
    -# ...which reads (in part) "The Cabinet approved the suggestion of the
    +# ...which reads (in part) "The Cabinet approved the suggestion of the
     # Ministry of Electricity to begin daylight savings time on Friday April
     # 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
     # Since Syria is two hours east of UTC, the 2200 and 2100 transition times
     # shown above match up with midnight in Syria.
     
     # From Arthur David Olson (2008-03-18):
    -# My buest guess at a Syrian rule is "the Friday nearest April 1";
    +# My best guess at a Syrian rule is "the Friday nearest April 1";
     # coding that involves either using a "Mar Fri>=29" construct that old time zone
     # compilers can't handle  or having multiple Rules (a la Israel).
     # For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
    @@ -2640,37 +2680,27 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
     # winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
     # clocks back 60 minutes).
     #
    -# 
     # http://sana.sy/ara/2/2008/10/07/195459.htm
    -# 
     
     # From Steffen Thorsen (2009-03-19):
     # Syria will start DST on 2009-03-27 00:00 this year according to many sources,
     # two examples:
     #
    -# 
     # http://www.sana.sy/eng/21/2009/03/17/217563.htm
    -# 
     # (English, Syrian Arab News # Agency)
    -# 
     # http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
    -# 
     # (Arabic, gov-site)
     #
     # We have not found any sources saying anything about when DST ends this year.
     #
     # Our summary
    -# 
     # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
    -# 
     
     # From Steffen Thorsen (2009-10-27):
     # The Syrian Arab News Network on 2009-09-29 reported that Syria will
     # revert back to winter (standard) time on midnight between Thursday
     # 2009-10-29 and Friday 2009-10-30:
    -# 
     # http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
    -# 
     
     # From Arthur David Olson (2009-10-28):
     # We'll see if future DST switching times turn out to be end of the last
    @@ -2681,23 +2711,17 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
     # The "Syrian News Station" reported on 2010-03-16 that the Council of
     # Ministers has decided that Syria will start DST on midnight Thursday
     # 2010-04-01: (midnight between Thursday and Friday):
    -# 
     # http://sns.sy/sns/?path=news/read/11421 (Arabic)
    -# 
     
     # From Steffen Thorsen (2012-03-26):
     # Today, Syria's government announced that they will start DST early on Friday
     # (00:00). This is a bit earlier than the past two years.
     #
     # From Syrian Arab News Agency, in Arabic:
    -# 
     # http://www.sana.sy/ara/2/2012/03/26/408215.htm
    -# 
     #
     # Our brief summary:
    -# 
     # http://www.timeanddate.com/news/time/syria-dst-2012.html
    -# 
     
     # From Arthur David Olson (2012-03-27):
     # Assume last Friday in March going forward XXX.
    @@ -2710,7 +2734,7 @@ Rule	Syria	2012	max	-	Mar	lastFri	0:00	1:00	S
     Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
    +Zone	Asia/Damascus	2:25:12 -	LMT	1920 # Dimashq
     			2:00	Syria	EE%sT
     
     # Tajikistan
    @@ -2718,9 +2742,9 @@ Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
     			5:00	-	DUST	1930 Jun 21 # Dushanbe Time
    -			6:00 RussiaAsia DUS%sT	1991 Mar 31 2:00s
    -			5:00	1:00	DUSST	1991 Sep  9 2:00s
    -			5:00	-	TJT		    # Tajikistan Time
    +			6:00 RussiaAsia DUS%sT	1991 Mar 31  2:00s
    +			5:00	1:00	DUSST	1991 Sep  9  2:00s
    +			5:00	-	TJT	# Tajikistan Time
     
     # Thailand
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    @@ -2733,9 +2757,9 @@ Zone	Asia/Bangkok	6:42:04	-	LMT	1880
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
     			4:00	-	ASHT	1930 Jun 21 # Ashkhabad Time
    -			5:00 RussiaAsia	ASH%sT	1991 Mar 31 2:00
    +			5:00 RussiaAsia	ASH%sT	1991 Mar 31  2:00
     			4:00 RussiaAsia	ASH%sT	1991 Oct 27 # independence
    -			4:00 RussiaAsia	TM%sT	1992 Jan 19 2:00
    +			4:00 RussiaAsia	TM%sT	1992 Jan 19  2:00
     			5:00	-	TMT
     
     # United Arab Emirates
    @@ -2744,8 +2768,9 @@ Zone	Asia/Dubai	3:41:12 -	LMT	1920
     			4:00	-	GST
     
     # Uzbekistan
    +# Byalokoz 1919 says Uzbekistan was 4:27:53.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
    +Zone	Asia/Samarkand	4:27:53 -	LMT	1924 May  2
     			4:00	-	SAMT	1930 Jun 21 # Samarkand Time
     			5:00	-	SAMT	1981 Apr  1
     			5:00	1:00	SAMST	1981 Oct  1
    @@ -2753,9 +2778,10 @@ Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
     			5:00 RussiaAsia	SAM%sT	1991 Sep  1 # independence
     			5:00 RussiaAsia	UZ%sT	1992
     			5:00	-	UZT
    -Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
    +# Milne says Tashkent was 4:37:10.8; round to nearest.
    +Zone	Asia/Tashkent	4:37:11 -	LMT	1924 May  2
     			5:00	-	TAST	1930 Jun 21 # Tashkent Time
    -			6:00 RussiaAsia	TAS%sT	1991 Mar 31 2:00
    +			6:00 RussiaAsia	TAS%sT	1991 Mar 31  2:00
     			5:00 RussiaAsia	TAS%sT	1991 Sep  1 # independence
     			5:00 RussiaAsia	UZ%sT	1992
     			5:00	-	UZT
    @@ -2769,13 +2795,13 @@ Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
     # and Pottenger.
     
     # From Arthur David Olson (2008-03-18):
    -# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
    -# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
    +# The English-language name of Vietnam's most populous city is "Ho Chi Minh
    +# City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters.
     
     # From Shanks & Pottenger:
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jun  9
    -			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
    +			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
     			7:00	-	ICT	1912 May
     			8:00	-	ICT	1931 May
     			7:00	-	ICT
    diff --git a/test/sun/util/calendar/zi/tzdata/australasia b/test/sun/util/calendar/zi/tzdata/australasia
    index 94c9adb912c599e62ad8c29e7f4422135bec1a05..52d329041786baa5eddfe7273936d2a199c384f3 100644
    --- a/test/sun/util/calendar/zi/tzdata/australasia
    +++ b/test/sun/util/calendar/zi/tzdata/australasia
    @@ -21,7 +21,6 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    @@ -36,13 +35,13 @@
     # Please see the notes below for the controversy about "EST" versus "AEST" etc.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	-
    -Rule	Aus	1917	only	-	Mar	25	2:00	0	-
    -Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	-
    -Rule	Aus	1942	only	-	Mar	29	2:00	0	-
    -Rule	Aus	1942	only	-	Sep	27	2:00	1:00	-
    -Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	-
    -Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
    +Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	D
    +Rule	Aus	1917	only	-	Mar	25	2:00	0	S
    +Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	D
    +Rule	Aus	1942	only	-	Mar	29	2:00	0	S
    +Rule	Aus	1942	only	-	Sep	27	2:00	1:00	D
    +Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	S
    +Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	D
     # Go with Whitman and the Australian National Standards Commission, which
     # says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
     # 1944/1945 was just like 1943/1944.
    @@ -50,26 +49,26 @@ Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     # Northern Territory
     Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
    -			 9:00	-	CST	1899 May
    -			 9:30	Aus	CST
    +			 9:00	-	ACST	1899 May
    +			 9:30	Aus	AC%sT
     # Western Australia
     #
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AW	1991	only	-	Nov	17	2:00s	1:00	-
    -Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	-
    -Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	-
    -Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AW	1991	only	-	Nov	17	2:00s	1:00	D
    +Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	D
    +Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	S
    +Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	D
     Zone Australia/Perth	 7:43:24 -	LMT	1895 Dec
    -			 8:00	Aus	WST	1943 Jul
    -			 8:00	AW	WST
    +			 8:00	Aus	AW%sT	1943 Jul
    +			 8:00	AW	AW%sT
     Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
    -			 8:45	Aus	CWST	1943 Jul
    -			 8:45	AW	CWST
    +			 8:45	Aus	ACW%sT	1943 Jul
    +			 8:45	AW	ACW%sT
     
     # Queensland
     #
    @@ -85,150 +84,150 @@ Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
     # so use Lindeman.
     #
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	-
    -Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	-
    -Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	-
    -Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	S
    +Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	S
    +Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	D
    +Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	S
     Zone Australia/Brisbane	10:12:08 -	LMT	1895
    -			10:00	Aus	EST	1971
    -			10:00	AQ	EST
    +			10:00	Aus	AE%sT	1971
    +			10:00	AQ	AE%sT
     Zone Australia/Lindeman  9:55:56 -	LMT	1895
    -			10:00	Aus	EST	1971
    -			10:00	AQ	EST	1992 Jul
    -			10:00	Holiday	EST
    +			10:00	Aus	AE%sT	1971
    +			10:00	AQ	AE%sT	1992 Jul
    +			10:00	Holiday	AE%sT
     
     # South Australia
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AS	1986	only	-	Oct	19	2:00s	1:00	-
    -Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AS	1972	only	-	Feb	27	2:00s	0	-
    -Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	-
    -Rule	AS	1991	only	-	Mar	3	2:00s	0	-
    -Rule	AS	1992	only	-	Mar	22	2:00s	0	-
    -Rule	AS	1993	only	-	Mar	7	2:00s	0	-
    -Rule	AS	1994	only	-	Mar	20	2:00s	0	-
    -Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	-
    -Rule	AS	2006	only	-	Apr	2	2:00s	0	-
    -Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	-
    -Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AS	1986	only	-	Oct	19	2:00s	1:00	D
    +Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AS	1972	only	-	Feb	27	2:00s	0	S
    +Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	S
    +Rule	AS	1991	only	-	Mar	3	2:00s	0	S
    +Rule	AS	1992	only	-	Mar	22	2:00s	0	S
    +Rule	AS	1993	only	-	Mar	7	2:00s	0	S
    +Rule	AS	1994	only	-	Mar	20	2:00s	0	S
    +Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	S
    +Rule	AS	2006	only	-	Apr	2	2:00s	0	S
    +Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	S
    +Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
    -			9:00	-	CST	1899 May
    -			9:30	Aus	CST	1971
    -			9:30	AS	CST
    +			9:00	-	ACST	1899 May
    +			9:30	Aus	AC%sT	1971
    +			9:30	AS	AC%sT
     
     # Tasmania
     #
     # From Paul Eggert (2005-08-16):
    -# 
    +# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
     # says King Island didn't observe DST from WWII until late 1971.
     #
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
    -Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	-
    -Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	-
    -Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	-
    -Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	-
    -Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
    -Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	-
    -Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
    -Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
    -Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	-
    -Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	-
    -Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
    -Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	-
    -Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	D
    +Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	S
    +Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	S
    +Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	S
    +Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	S
    +Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	D
    +Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	S
    +Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	D
    +Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	D
    +Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	S
    +Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	D
    +Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	D
    +Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	S
    +Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
    -			10:00	-	EST	1916 Oct 1 2:00
    -			10:00	1:00	EST	1917 Feb
    -			10:00	Aus	EST	1967
    -			10:00	AT	EST
    +			10:00	-	AEST	1916 Oct  1  2:00
    +			10:00	1:00	AEDT	1917 Feb
    +			10:00	Aus	AE%sT	1967
    +			10:00	AT	AE%sT
     Zone Australia/Currie	9:35:28	-	LMT	1895 Sep
    -			10:00	-	EST	1916 Oct 1 2:00
    -			10:00	1:00	EST	1917 Feb
    -			10:00	Aus	EST	1971 Jul
    -			10:00	AT	EST
    +			10:00	-	AEST	1916 Oct  1  2:00
    +			10:00	1:00	AEDT	1917 Feb
    +			10:00	Aus	AE%sT	1971 Jul
    +			10:00	AT	AE%sT
     
     # Victoria
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	-
    -Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	-
    -Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	-
    -Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	-
    -Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	-
    -Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	-
    -Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	S
    +Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	S
    +Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	D
    +Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	S
    +Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	D
    +Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	S
    +Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
    -			10:00	Aus	EST	1971
    -			10:00	AV	EST
    +			10:00	Aus	AE%sT	1971
    +			10:00	AV	AE%sT
     
     # New South Wales
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AN	1972	only	-	Feb	27	2:00s	0	-
    -Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	-
    -Rule	AN	1986	only	-	Oct	19	2:00s	1:00	-
    -Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	-
    -Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	-
    -Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	-
    -Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	-
    -Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	-
    -Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	-
    -Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AN	1972	only	-	Feb	27	2:00s	0	S
    +Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	S
    +Rule	AN	1986	only	-	Oct	19	2:00s	1:00	D
    +Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	S
    +Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	S
    +Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	D
    +Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	D
    +Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	S
    +Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	S
    +Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
    -			10:00	Aus	EST	1971
    -			10:00	AN	EST
    +			10:00	Aus	AE%sT	1971
    +			10:00	AN	AE%sT
     Zone Australia/Broken_Hill 9:25:48 -	LMT	1895 Feb
    -			10:00	-	EST	1896 Aug 23
    -			9:00	-	CST	1899 May
    -			9:30	Aus	CST	1971
    -			9:30	AN	CST	2000
    -			9:30	AS	CST
    +			10:00	-	AEST	1896 Aug 23
    +			9:00	-	ACST	1899 May
    +			9:30	Aus	AC%sT	1971
    +			9:30	AN	AC%sT	2000
    +			9:30	AS	AC%sT
     
     # Lord Howe Island
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	-
    -Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	-
    -Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	-
    -Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	-
    -Rule	LH	1986	only	-	Oct	19	2:00	0:30	-
    -Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	-
    -Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	-
    -Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	-
    -Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	-
    -Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	-
    -Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	-
    -Rule	LH	2007	only	-	Mar	lastSun	2:00	0	-
    -Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	-
    -Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	-
    +Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	D
    +Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	S
    +Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	D
    +Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	S
    +Rule	LH	1986	only	-	Oct	19	2:00	0:30	D
    +Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	D
    +Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	S
    +Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	S
    +Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	D
    +Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	D
    +Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	S
    +Rule	LH	2007	only	-	Mar	lastSun	2:00	0	S
    +Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	S
    +Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	D
     Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
    -			10:00	-	EST	1981 Mar
    -			10:30	LH	LHST
    +			10:00	-	AEST	1981 Mar
    +			10:30	LH	LH%sT
     
     # Australian miscellany
     #
    @@ -244,8 +243,8 @@ Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
     # Permanent occupation (scientific station) 1911-1915 and since 25 March 1948;
     # sealing and penguin oil station operated Nov 1899 to Apr 1919.  See the
     # Tasmania Parks & Wildlife Service history of sealing at Macquarie Island
    -# 
    -# .
    +# http://www.parks.tas.gov.au/index.aspx?base=1828
    +# http://www.parks.tas.gov.au/index.aspx?base=1831
     # Guess that it was like Australia/Hobart while inhabited before 2010.
     #
     # From Steffen Thorsen (2010-03-10):
    @@ -256,16 +255,16 @@ Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
     #
     # From Arthur David Olson (2013-05-23):
     # The 1919 transition is overspecified below so pre-2013 zics
    -# will produce a binary file with an EST-type as the first 32-bit type;
    +# will produce a binary file with an [A]EST-type as the first 32-bit type;
     # this is required for correct handling of times before 1916 by
     # pre-2013 versions of localtime.
     Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
    -			10:00	-	EST	1916 Oct 1 2:00
    -			10:00	1:00	EST	1917 Feb
    -			10:00	Aus	EST	1919 Apr 1 0:00s
    +			10:00	-	AEST	1916 Oct  1  2:00
    +			10:00	1:00	AEDT	1917 Feb
    +			10:00	Aus	AE%sT	1919 Apr  1  0:00s
     			0	-	zzz	1948 Mar 25
    -			10:00	Aus	EST	1967
    -			10:00	AT	EST	2010 Apr 4 3:00
    +			10:00	Aus	AE%sT	1967
    +			10:00	AT	AE%sT	2010 Apr  4  3:00
     			11:00	-	MIST	# Macquarie I Standard Time
     
     # Christmas
    @@ -273,24 +272,14 @@ Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
     Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
     			7:00	-	CXT	# Christmas Island Time
     
    -# Cook Is
    -# From Shanks & Pottenger:
    -# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
    -Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
    -Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
    -# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901		# Avarua
    -			-10:30	-	CKT	1978 Nov 12	# Cook Is Time
    -			-10:00	Cook	CK%sT
    -
    -# Cocos
    +# Cocos (Keeling) Is
     # These islands were ruled by the Ross family from about 1830 to 1978.
     # We don't know when standard time was introduced; for now, we guess 1900.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Indian/Cocos	6:27:40	-	LMT	1900
     			6:30	-	CCT	# Cocos Islands Time
     
    +
     # Fiji
     
     # Milne gives 11:55:44 for Suva.
    @@ -300,20 +289,13 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
     # from November 29th 2009  to April 25th 2010.
     #
     # "Daylight savings to commence this month"
    -# 
     # http://www.radiofiji.com.fj/fullstory.php?id=23719
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_fiji01.html
    -# 
     
     # From Steffen Thorsen (2009-11-10):
     # The Fiji Government has posted some more details about the approved
     # amendments:
    -# 
     # http://www.fiji.gov.fj/publish/page_16198.shtml
    -# 
     
     # From Steffen Thorsen (2010-03-03):
     # The Cabinet in Fiji has decided to end DST about a month early, on
    @@ -322,35 +304,24 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
     # 2011 (last Sunday a good guess?).
     #
     # Official source:
    -# 
     # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166
    -# 
     #
     # A bit more background info here:
    -# 
     # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
    -# 
     
     # From Alexander Krivenyshev (2010-10-24):
     # According to Radio Fiji and Fiji Times online, Fiji will end DST 3
     # weeks earlier than expected - on March 6, 2011, not March 27, 2011...
     # Here is confirmation from Government of the Republic of the Fiji Islands,
     # Ministry of Information (fiji.gov.fj) web site:
    -# 
     # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
    -# 
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
    -# 
     
     # From Steffen Thorsen (2011-10-03):
     # Now the dates have been confirmed, and at least our start date
     # assumption was correct (end date was one week wrong).
     #
    -# 
    -# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
    -# 
    +# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
     # which says
     # Members of the public are reminded to change their time to one hour in
     # advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
    @@ -360,9 +331,7 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
     # Another change to the Fiji DST end date. In the TZ database the end date for
     # Fiji DST 2012, is currently Feb 26. This has been changed to Jan 22.
     #
    -# 
     # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155
    -# 
     # states:
     #
     # The end of daylight saving scheduled initially for the 26th of February 2012
    @@ -400,16 +369,16 @@ Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
     Rule	Fiji	2012	2013	-	Jan	Sun>=18	3:00	0	-
     Rule	Fiji	2014	max	-	Jan	Sun>=18	2:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26	# Suva
    +Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26 # Suva
     			12:00	Fiji	FJ%sT	# Fiji Time
     
     # French Polynesia
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct	# Rikitea
    +Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct # Rikitea
     			 -9:00	-	GAMT	# Gambier Time
     Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
     			 -9:30	-	MART	# Marquesas Time
    -Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
    +Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct # Papeete
     			-10:00	-	TAHT	# Tahiti Time
     # Clipperton (near North America) is administered from French Polynesia;
     # it is uninhabited.
    @@ -417,14 +386,14 @@ Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
     # Guam
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
    -			 9:39:00 -	LMT	1901		# Agana
    -			10:00	-	GST	2000 Dec 23	# Guam
    +			 9:39:00 -	LMT	1901        # Agana
    +			10:00	-	GST	2000 Dec 23 # Guam
     			10:00	-	ChST	# Chamorro Standard Time
     
     # Kiribati
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Pacific/Tarawa	 11:32:04 -	LMT	1901		# Bairiki
    -			 12:00	-	GILT		 # Gilbert Is Time
    +Zone Pacific/Tarawa	 11:32:04 -	LMT	1901 # Bairiki
    +			 12:00	-	GILT	# Gilbert Is Time
     Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
     			-12:00	-	PHOT	1979 Oct # Phoenix Is Time
     			-11:00	-	PHOT	1995
    @@ -438,7 +407,7 @@ Zone Pacific/Kiritimati	-10:29:20 -	LMT	1901
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
     			 9:43:00 -	LMT	1901
    -			 9:00	-	MPT	1969 Oct # N Mariana Is Time
    +			 9:00	-	MPT	1969 Oct    # N Mariana Is Time
     			10:00	-	MPT	2000 Dec 23
     			10:00	-	ChST	# Chamorro Standard Time
     
    @@ -449,24 +418,24 @@ Zone Pacific/Majuro	11:24:48 -	LMT	1901
     			12:00	-	MHT
     Zone Pacific/Kwajalein	11:09:20 -	LMT	1901
     			11:00	-	MHT	1969 Oct
    -			-12:00	-	KWAT	1993 Aug 20	# Kwajalein Time
    +			-12:00	-	KWAT	1993 Aug 20 # Kwajalein Time
     			12:00	-	MHT
     
     # Micronesia
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Pacific/Chuuk	10:07:08 -	LMT	1901
    -			10:00	-	CHUT			# Chuuk Time
    -Zone Pacific/Pohnpei	10:32:52 -	LMT	1901		# Kolonia
    -			11:00	-	PONT			# Pohnpei Time
    +			10:00	-	CHUT	# Chuuk Time
    +Zone Pacific/Pohnpei	10:32:52 -	LMT	1901 # Kolonia
    +			11:00	-	PONT	# Pohnpei Time
     Zone Pacific/Kosrae	10:51:56 -	LMT	1901
    -			11:00	-	KOST	1969 Oct	# Kosrae Time
    +			11:00	-	KOST	1969 Oct # Kosrae Time
     			12:00	-	KOST	1999
     			11:00	-	KOST
     
     # Nauru
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15	# Uaobe
    -			11:30	-	NRT	1942 Mar 15	# Nauru Time
    +Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15 # Uaobe
    +			11:30	-	NRT	1942 Mar 15 # Nauru Time
     			9:00	-	JST	1944 Aug 15
     			11:30	-	NRT	1979 May
     			12:00	-	NRT
    @@ -479,7 +448,7 @@ Rule	NC	1996	only	-	Dec	 1	2:00s	1:00	S
     # Shanks & Pottenger say the following was at 2:00; go with IATA.
     Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13
    +Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13 # Nouméa
     			11:00	NC	NC%sT
     
     
    @@ -496,7 +465,8 @@ Rule	NZ	1934	1940	-	Apr	lastSun	2:00	0	M
     Rule	NZ	1934	1940	-	Sep	lastSun	2:00	0:30	S
     Rule	NZ	1946	only	-	Jan	 1	0:00	0	S
     # Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
    -# convenient notation for this so we must duplicate the Rule lines.
    +# convenient single notation for the date and time of this transition
    +# so we must duplicate the Rule lines.
     Rule	NZ	1974	only	-	Nov	Sun>=1	2:00s	1:00	D
     Rule	Chatham	1974	only	-	Nov	Sun>=1	2:45s	1:00	D
     Rule	NZ	1975	only	-	Feb	lastSun	2:00s	0	S
    @@ -519,13 +489,14 @@ Rule	Chatham	2008	max	-	Apr	Sun>=1	2:45s	0	S
     Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
     			11:30	NZ	NZ%sT	1946 Jan  1
     			12:00	NZ	NZ%sT
    -Zone Pacific/Chatham	12:13:48 -	LMT	1957 Jan  1
    +Zone Pacific/Chatham	12:13:48 -	LMT	1868 Nov  2
    +			12:15	-	CHAST	1946 Jan  1
     			12:45	Chatham	CHA%sT
     
     Link Pacific/Auckland Antarctica/McMurdo
     
     # Auckland Is
    -# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
    +# uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers,
     # and scientific personnel have wintered
     
     # Campbell I
    @@ -534,48 +505,58 @@ Link Pacific/Auckland Antarctica/McMurdo
     # previously whalers, sealers, pastoralists, and scientific personnel wintered
     # was probably like Pacific/Auckland
     
    +# Cook Is
    +# From Shanks & Pottenger:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
    +Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
    +Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901        # Avarua
    +			-10:30	-	CKT	1978 Nov 12 # Cook Is Time
    +			-10:00	Cook	CK%sT
    +
     ###############################################################################
     
     
     # Niue
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Niue	-11:19:40 -	LMT	1901		# Alofi
    -			-11:20	-	NUT	1951	# Niue Time
    -			-11:30	-	NUT	1978 Oct 1
    +Zone	Pacific/Niue	-11:19:40 -	LMT	1901        # Alofi
    +			-11:20	-	NUT	1951        # Niue Time
    +			-11:30	-	NUT	1978 Oct  1
     			-11:00	-	NUT
     
     # Norfolk
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Norfolk	11:11:52 -	LMT	1901		# Kingston
    -			11:12	-	NMT	1951	# Norfolk Mean Time
    -			11:30	-	NFT		# Norfolk Time
    +Zone	Pacific/Norfolk	11:11:52 -	LMT	1901 # Kingston
    +			11:12	-	NMT	1951 # Norfolk Mean Time
    +			11:30	-	NFT	# Norfolk Time
     
     # Palau (Belau)
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Pacific/Palau	8:57:56 -	LMT	1901		# Koror
    +Zone Pacific/Palau	8:57:56 -	LMT	1901 # Koror
     			9:00	-	PWT	# Palau Time
     
     # Papua New Guinea
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
    -			9:48:32	-	PMMT	1895	# Port Moresby Mean Time
    -			10:00	-	PGT		# Papua New Guinea Time
    +			9:48:32	-	PMMT	1895 # Port Moresby Mean Time
    +			10:00	-	PGT	# Papua New Guinea Time
     
     # Pitcairn
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901		# Adamstown
    -			-8:30	-	PNT	1998 Apr 27 00:00
    +Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901        # Adamstown
    +			-8:30	-	PNT	1998 Apr 27  0:00
     			-8:00	-	PST	# Pitcairn Standard Time
     
     # American Samoa
     Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
     			-11:22:48 -	LMT	1911
    -			-11:30	-	SAMT	1950		# Samoa Time
    -			-11:00	-	NST	1967 Apr	# N=Nome
    -			-11:00	-	BST	1983 Nov 30	# B=Bering
    -			-11:00	-	SST			# S=Samoa
    +			-11:00	-	NST	1967 Apr    # N=Nome
    +			-11:00	-	BST	1983 Nov 30 # B=Bering
    +			-11:00	-	SST	            # S=Samoa
     
    -# Samoa
    +# Samoa (formerly and also known as Western Samoa)
     
     # From Steffen Thorsen (2009-10-16):
     # We have been in contact with the government of Samoa again, and received
    @@ -586,141 +567,80 @@ Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
     # Sunday of April 2011."
     #
     # Background info:
    -# 
     # http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
    -# 
     #
     # Samoa's Daylight Saving Time Act 2009 is available here, but does not
     # contain any dates:
    -# 
     # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
    -# 
     
     # From Laupue Raymond Hughes (2010-10-07):
     # Please see
    -# 
     # http://www.mcil.gov.ws
    -# ,
     # the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
     # September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
     # to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
     # backwards from 1:00am to 12:00am"
     
     # From Laupue Raymond Hughes (2011-03-07):
    -# I believe this will be posted shortly on the website
    -# 
    -# www.mcil.gov.ws
    -# 
    -#
    -# PUBLIC NOTICE ON DAYLIGHT SAVING TIME
    +# [http://www.mcil.gov.ws/ftcd/daylight_saving_2011.pdf]
     #
    -# Pursuant to the Daylight Saving Act 2009 and Cabinets decision,
    -# businesses and the general public are hereby advised that daylight
    -# saving time is on the first Saturday of April 2011 (02/04/11).
    -#
    -# The public is therefore advised that when the standard time strikes
    -# the hour of four oclock (4.00am or 0400 Hours) on the 2nd April 2011,
    -# then all instruments used to measure standard time are to be
    -# adjusted/changed to three oclock (3:00am or 0300Hrs).
    -#
    -# Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE,
    -# INDUSTRY AND LABOUR 28th February 2011
    +# ... when the standard time strikes the hour of four o'clock (4.00am
    +# or 0400 Hours) on the 2nd April 2011, then all instruments used to
    +# measure standard time are to be adjusted/changed to three o'clock
    +# (3:00am or 0300Hrs).
     
    -# From David Zuelke (2011-05-09):
    +# From David Zülke (2011-05-09):
     # Subject: Samoa to move timezone from east to west of international date line
     #
    -# 
     # http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
    -# 
     
    -# From Mark Sim-Smith (2011-08-17):
    -# I have been in contact with Leilani Tuala Warren from the Samoa Law
    -# Reform Commission, and she has sent me a copy of the Bill that she
    -# confirmed has been passed...Most of the sections are about maps rather
    -# than the time zone change, but I'll paste the relevant bits below. But
    -# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa
    -# changes from UTC-11 to UTC+13:
    -#
    -# International Date Line Bill 2011
    -#
    -# AN ACT to provide for the change to standard time in Samoa and to make
    -# consequential amendments to the position of the International Date
    -# Line, and for related purposes.
    -#
    -# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament
    -# assembled as follows:
    -#
    -# 1. Short title and commencement-(1) This Act may be cited as the
    -# International Date Line Act 2011. (2) Except for section 5(3) this Act
    -# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3)
    -# Section 5(3) commences on the date of assent by the Head of State.
    -#
    -# [snip]
    -#
    -# 3. Interpretation - [snip] "Samoa standard time" in this Act and any
    -# other statute of Samoa which refers to 'Samoa standard time' means the
    -# time 13 hours in advance of Co-ordinated Universal Time.
    -#
    -# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa
    -# standard time shall be set at 13 hours in advance of Co-ordinated
    -# Universal Time for the whole of Samoa. (2) All references to Samoa's
    -# time zone and to Samoa standard time in Samoa in all legislation and
    -# instruments after the commencement of this Act shall be references to
    -# Samoa standard time as provided for in this Act. (3) Nothing in this
    -# Act affects the provisions of the Daylight Saving Act 2009, except that
    -# it defines Samoa standard time....
    +# From Paul Eggert (2014-06-27):
    +# The International Date Line Act 2011
    +# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
    +# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
    +# Thursday 29th December 2011".  The International Date Line was adjusted
    +# accordingly.
     
     # From Laupue Raymond Hughes (2011-09-02):
    -# 
     # http://www.mcil.gov.ws/mcil_publications.html
    -# 
     #
     # here is the official website publication for Samoa DST and dateline change
     #
     # DST
    -# Year	End	Time	Start	Time
    -# 2011	- - -	- - -	24 September	3:00am to 4:00am
    -# 2012	01 April	4:00am to 3:00am	- - -	- - -
    +# Year  End      Time              Start        Time
    +# 2011  - - -    - - -             24 September 3:00am to 4:00am
    +# 2012  01 April 4:00am to 3:00am  - - -        - - -
     #
     # Dateline Change skip Friday 30th Dec 2011
     # Thursday 29th December 2011	23:59:59 Hours
     # Saturday 31st December 2011	00:00:00 Hours
     #
    -# Clarification by Tim Parenti (2012-01-03):
    -# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
    -# seasons, there is not yet any indication that this trend will continue on
    -# a regular basis. For now, we have explicitly listed the transitions below.
    -#
    -# From Nicky (2012-09-10):
    +# From Nicholas Pereira (2012-09-10):
     # Daylight Saving Time commences on Sunday 30th September 2012 and
    -# ends on Sunday 7th of April 2013.
    -#
    -# Please find link below for more information.
    +# ends on Sunday 7th of April 2013....
     # http://www.mcil.gov.ws/mcil_publications.html
     #
    -# That publication also includes dates for Summer of 2013/4 as well
    -# which give the impression of a pattern in selecting dates for the
    -# future, so for now, we will guess this will continue.
    +# From Paul Eggert (2014-07-08):
    +# That web page currently lists transitions for 2012/3 and 2013/4.
    +# Assume the pattern instituted in 2012 will continue indefinitely.
     
    -# Western Samoa
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	WS	2010	only	-	Sep	lastSun	0:00	1	D
    +Rule	WS	2011	only	-	Apr	Sat>=1	4:00	0	S
    +Rule	WS	2011	only	-	Sep	lastSat	3:00	1	D
    +Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	S
     Rule	WS	2012	max	-	Sep	lastSun	3:00	1	D
    -Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
     			-11:26:56 -	LMT	1911
    -			-11:30	-	SAMT	1950		# Samoa Time
    -			-11:00	-	WST	2010 Sep 26
    -			-11:00	1:00	WSDT	2011 Apr 2 4:00
    -			-11:00	-	WST	2011 Sep 24 3:00
    -			-11:00	1:00	WSDT	2011 Dec 30
    -			 13:00	1:00	WSDT	2012 Apr Sun>=1 4:00
    +			-11:30	-	WSST	1950
    +			-11:00	WS	S%sT	2011 Dec 29 24:00 # S=Samoa
     			 13:00	WS	WS%sT
     
     # Solomon Is
     # excludes Bougainville, for which see Papua New Guinea
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
    +Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct # Honiara
     			11:00	-	SBT	# Solomon Is Time
     
     # Tokelau Is
    @@ -744,7 +664,7 @@ Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
    -			-11:00	-	TKT 2011 Dec 30	# Tokelau Time
    +			-11:00	-	TKT	2011 Dec 30 # Tokelau Time
     			13:00	-	TKT
     
     # Tonga
    @@ -804,8 +724,8 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
     # time from Operation Newsreel (Hardtack I/Teak shot, 1958-08-01) to the last
     # Operation Fishbowl shot (Tightrope, 1962-11-04).... [See] Herman Hoerlin,
     # "The United States High-Altitude Test Experience: A Review Emphasizing the
    -# Impact on the Environment", Los Alamos LA-6405, Oct 1976
    -# .
    +# Impact on the Environment", Los Alamos LA-6405, Oct 1976.
    +# http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf
     # See the table on page 4 where he lists GMT and local times for the tests; a
     # footnote for the JI tests reads that local time is "JI time = Hawaii Time
     # Minus One Hour".
    @@ -820,7 +740,7 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
     # From Mark Brader (2005-01-23):
     # [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
     # published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
    -# reproduced a Pan American Airways timeables from 1936, for their weekly
    +# reproduced a Pan American Airways timetable from 1936, for their weekly
     # "Orient Express" flights between San Francisco and Manila, and connecting
     # flights to Chicago and the US East Coast.  As it uses some time zone
     # designations that I've never seen before:....
    @@ -830,9 +750,9 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
     Zone Pacific/Midway	-11:49:28 -	LMT	1901
     			-11:00	-	NST	1956 Jun  3
     			-11:00	1:00	NDT	1956 Sep  2
    -			-11:00	-	NST	1967 Apr	# N=Nome
    -			-11:00	-	BST	1983 Nov 30	# B=Bering
    -			-11:00	-	SST			# S=Samoa
    +			-11:00	-	NST	1967 Apr    # N=Nome
    +			-11:00	-	BST	1983 Nov 30 # B=Bering
    +			-11:00	-	SST	            # S=Samoa
     
     # Palmyra
     # uninhabited since World War II; was probably like Pacific/Kiritimati
    @@ -852,7 +772,7 @@ Rule	Vanuatu	1985	1991	-	Sep	Sun>=23	0:00	1:00	S
     Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
     Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13		# Vila
    +Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13 # Vila
     			11:00	Vanuatu	VU%sT	# Vanuatu Time
     
     # Wallis and Futuna
    @@ -864,9 +784,10 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     
     # NOTES
     
    -# This data is by no means authoritative; if you think you know better,
    +# This file is by no means authoritative; if you think you know better,
     # go ahead and edit the file (and please send any changes to
    -# tz@iana.org for general use in the future).
    +# tz@iana.org for general use in the future).  For more, please see
    +# the file CONTRIBUTING in the tz distribution.
     
     # From Paul Eggert (2013-02-21):
     # A good source for time zone historical data outside the U.S. is
    @@ -887,165 +808,188 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # I found in the UCLA library.
     #
     # For data circa 1899, a common source is:
    -# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
    -# .
    +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
    +# http://www.jstor.org/stable/1774359
     #
     # A reliable and entertaining source about time zones is
     # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
     #
    -# I invented the abbreviations marked `*' in the following table;
    +# I invented the abbreviations marked '*' in the following table;
     # the rest are from earlier versions of this file, or from other sources.
     # Corrections are welcome!
    -#		std dst
    -#		LMT	Local Mean Time
    -#	  8:00	WST WST	Western Australia
    -#	  8:45	CWST CWST Central Western Australia*
    -#	  9:00	JST	Japan
    -#	  9:30	CST CST	Central Australia
    -#	 10:00	EST EST	Eastern Australia
    -#	 10:00	ChST	Chamorro
    -#	 10:30	LHST LHST Lord Howe*
    -#	 11:30	NZMT NZST New Zealand through 1945
    -#	 12:00	NZST NZDT New Zealand 1946-present
    -#	 12:45	CHAST CHADT Chatham*
    -#	-11:00	SST	Samoa
    -#	-10:00	HST	Hawaii
    -#	- 8:00	PST	Pitcairn*
    -#
    -# See the `northamerica' file for Hawaii.
    -# See the `southamerica' file for Easter I and the Galapagos Is.
    +#		std	dst
    +#		LMT		Local Mean Time
    +#	  8:00	AWST	AWDT	Western Australia
    +#	  8:45	ACWST	ACWDT	Central Western Australia*
    +#	  9:00	JST		Japan
    +#	  9:30	ACST	ACDT	Central Australia
    +#	 10:00	AEST	AEDT	Eastern Australia
    +#	 10:00	ChST		Chamorro
    +#	 10:30	LHST	LHDT	Lord Howe*
    +#	 11:30	NZMT	NZST	New Zealand through 1945
    +#	 12:00	NZST	NZDT	New Zealand 1946-present
    +#	 12:15	CHAST		Chatham through 1945*
    +#	 12:45	CHAST	CHADT	Chatham 1946-present*
    +#	 13:00	WSST	WSDT	(western) Samoa 2011-present*
    +#	-11:30	WSST		Western Samoa through 1950*
    +#	-11:00	SST		Samoa
    +#	-10:00	HST		Hawaii
    +#	- 8:00	PST		Pitcairn*
    +#
    +# See the 'northamerica' file for Hawaii.
    +# See the 'southamerica' file for Easter I and the Galápagos Is.
     
     ###############################################################################
     
     # Australia
     
    +# From Paul Eggert (2014-06-30):
    +# Daylight saving time has long been controversial in Australia, pitting
    +# region against region, rural against urban, and local against global.
    +# For example, in her review of Graeme Davison's _The Unforgiving
    +# Minute: how Australians learned to tell the time_ (1993), Perth native
    +# Phillipa J Martyr wrote, "The section entitled 'Saving Daylight' was
    +# very informative, but was (as can, sadly, only be expected from a
    +# Melbourne-based study) replete with the usual chuckleheaded
    +# Queenslanders and straw-chewing yokels from the West prattling fables
    +# about fading curtains and crazed farm animals."
    +# Electronic Journal of Australian and New Zealand History (1997-03-03)
    +# http://www.jcu.edu.au/aff/history/reviews/davison.htm
    +
     # From Paul Eggert (2005-12-08):
    -# 
     # Implementation Dates of Daylight Saving Time within Australia
    -#  summarizes daylight saving issues in Australia.
    +# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
    +# summarizes daylight saving issues in Australia.
     
     # From Arthur David Olson (2005-12-12):
    -# 
     # Lawlink NSW:Daylight Saving in New South Wales
    -#  covers New South Wales in particular.
    +# http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving
    +# covers New South Wales in particular.
     
     # From John Mackin (1991-03-06):
    -# We in Australia have _never_ referred to DST as `daylight' time.
    -# It is called `summer' time.  Now by a happy coincidence, `summer'
    -# and `standard' happen to start with the same letter; hence, the
    +# We in Australia have _never_ referred to DST as 'daylight' time.
    +# It is called 'summer' time.  Now by a happy coincidence, 'summer'
    +# and 'standard' happen to start with the same letter; hence, the
     # abbreviation does _not_ change...
     # The legislation does not actually define abbreviations, at least
     # in this State, but the abbreviation is just commonly taken to be the
     # initials of the phrase, and the legislation here uniformly uses
    -# the phrase `summer time' and does not use the phrase `daylight
    +# the phrase 'summer time' and does not use the phrase 'daylight
     # time'.
     # Announcers on the Commonwealth radio network, the ABC (for Australian
    -# Broadcasting Commission), use the phrases `Eastern Standard Time'
    -# or `Eastern Summer Time'.  (Note, though, that as I say in the
    +# Broadcasting Commission), use the phrases 'Eastern Standard Time'
    +# or 'Eastern Summer Time'.  (Note, though, that as I say in the
     # current australasia file, there is really no such thing.)  Announcers
     # on its overseas service, Radio Australia, use the same phrases
    -# prefixed by the word `Australian' when referring to local times;
    +# prefixed by the word 'Australian' when referring to local times;
     # time announcements on that service, naturally enough, are made in UTC.
     
    -# From Arthur David Olson (1992-03-08):
    -# Given the above, what's chosen for year-round use is:
    -#	CST	for any place operating at a GMTOFF of 9:30
    -#	WST	for any place operating at a GMTOFF of 8:00
    -#	EST	for any place operating at a GMTOFF of 10:00
    -
    -# From Chuck Soper (2006-06-01):
    -# I recently found this Australian government web page on time zones:
    -# 
    -# And this government web page lists time zone names and abbreviations:
    -# 
    -
    -# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
    -# versus "AEST" etc.:
    -#
    -# I see the following points of dispute:
    -#
    -# * How important are unique time zone abbreviations?
    -#
    -#   Here I tend to agree with the point (most recently made by Chris
    -#   Newman) that unique abbreviations should not be essential for proper
    -#   operation of software.  We have other instances of ambiguity
    -#   (e.g. "IST" denoting both "Israel Standard Time" and "Indian
    -#   Standard Time"), and they are not likely to go away any time soon.
    -#   In the old days, some software mistakenly relied on unique
    -#   abbreviations, but this is becoming less true with time, and I don't
    -#   think it's that important to cater to such software these days.
    -#
    -#   On the other hand, there is another motivation for unambiguous
    -#   abbreviations: it cuts down on human confusion.  This is
    -#   particularly true for Australia, where "EST" can mean one thing for
    -#   time T and a different thing for time T plus 1 second.
    -#
    -# * Does the relevant legislation indicate which abbreviations should be used?
    -#
    -#   Here I tend to think that things are a mess, just as they are in
    -#   many other countries.  We Americans are currently disagreeing about
    -#   which abbreviation to use for the newly legislated Chamorro Standard
    -#   Time, for example.
    -#
    -#   Personally, I would prefer to use common practice; I would like to
    -#   refer to legislation only for examples of common practice, or as a
    -#   tiebreaker.
    -#
    -# * Do Australians more often use "Eastern Daylight Time" or "Eastern
    -#   Summer Time"?  Do they typically prefix the time zone names with
    -#   the word "Australian"?
    -#
    -#   My own impression is that both "Daylight Time" and "Summer Time" are
    -#   common and are widely understood, but that "Summer Time" is more
    -#   popular; and that the leading "A" is also common but is omitted more
    -#   often than not.  I just used AltaVista advanced search and got the
    -#   following count of page hits:
    -#
    -#     1,103 "Eastern Summer Time" AND domain:au
    -#       971 "Australian Eastern Summer Time" AND domain:au
    -#       613 "Eastern Daylight Time" AND domain:au
    -#       127 "Australian Eastern Daylight Time" AND domain:au
    -#
    -#   Here "Summer" seems quite a bit more popular than "Daylight",
    -#   particularly when we know the time zone is Australian and not US,
    -#   say.  The "Australian" prefix seems to be popular for Eastern Summer
    -#   Time, but unpopular for Eastern Daylight Time.
    -#
    -#   For abbreviations, tools like AltaVista are less useful because of
    -#   ambiguity.  Many hits are not really time zones, unfortunately, and
    -#   many hits denote US time zones and not Australian ones.  But here
    -#   are the hit counts anyway:
    -#
    -#     161,304 "EST" and domain:au
    -#      25,156 "EDT" and domain:au
    -#      18,263 "AEST" and domain:au
    -#      10,416 "AEDT" and domain:au
    -#
    -#      14,538 "CST" and domain:au
    -#       5,728 "CDT" and domain:au
    -#         176 "ACST" and domain:au
    -#          29 "ACDT" and domain:au
    -#
    -#       7,539 "WST" and domain:au
    -#          68 "AWST" and domain:au
    -#
    -#   This data suggest that Australians tend to omit the "A" prefix in
    -#   practice.  The situation for "ST" versus "DT" is less clear, given
    -#   the ambiguities involved.
    -#
    -# * How do Australians feel about the abbreviations in the tz database?
    -#
    -#   If you just count Australians on this list, I count 2 in favor and 3
    -#   against.  One of the "against" votes (David Keegel) counseled delay,
    -#   saying that both AEST/AEDT and EST/EST are widely used and
    -#   understood in Australia.
    +# From Paul Eggert (2014-06-30):
    +#
    +# Inspired by Mackin's remarks quoted above, earlier versions of this
    +# file used "EST" for both Eastern Standard Time and Eastern Summer
    +# Time in Australia, and similarly for "CST", "CWST", and "WST".
    +# However, these abbreviations were confusing and were not common
    +# practice among Australians, and there were justifiable complaints
    +# about them, so I attempted to survey current Australian usage.
    +# For the tz database, the full English phrase is not that important;
    +# what matters is the abbreviation.  It's difficult to survey the web
    +# directly for abbreviation usage, as there are so many false hits for
    +# strings like "EST" and "EDT", so I looked for pages that defined an
    +# abbreviation for eastern or central DST in Australia, and got the
    +# following numbers of unique hits for the listed Google queries:
    +#
    +#   10 "Eastern Daylight Time AEST" site:au [some are false hits]
    +#   10 "Eastern Summer Time AEST" site:au
    +#   10 "Summer Time AEDT" site:au
    +#   13 "EDST Eastern Daylight Saving Time" site:au
    +#   18 "Summer Time ESST" site:au
    +#   28 "Eastern Daylight Saving Time EDST" site:au
    +#   39 "EDT Eastern Daylight Time" site:au [some are false hits]
    +#   53 "Eastern Daylight Time EDT" site:au [some are false hits]
    +#   54 "AEDT Australian Eastern Daylight Time" site:au
    +#  182 "Eastern Daylight Time AEDT" site:au
    +#
    +#   17 "Central Daylight Time CDT" site:au [some are false hits]
    +#   46 "Central Daylight Time ACDT" site:au
    +#
    +# I tried several other variants (e.g., "Eastern Summer Time EST") but
    +# they all returned fewer than 10 unique hits.  I also looked for pages
    +# mentioning both "western standard time" and an abbreviation, since
    +# there is no WST in the US to generate false hits, and found:
    +#
    +#  156 "western standard time" AWST site:au
    +#  226 "western standard time" WST site:au
    +#
    +# I then surveyed the top ten newspapers in Australia by circulation as
    +# listed in Wikipedia, using Google queries like "AEDT site:heraldsun.com.au"
    +# and obtaining estimated counts from the initial page of search results.
    +# All ten papers greatly preferred "AEDT" to "EDT".  The papers
    +# surveyed were the Herald Sun, The Daily Telegraph, The Courier-Mail,
    +# The Sydney Morning Herald, The West Australian, The Age, The Advertiser,
    +# The Australian, The Financial Review, and The Herald (Newcastle).
    +#
    +# I also searched for historical usage, to see whether abbreviations
    +# like "AEDT" are new.  A Trove search 
    +# found only one newspaper (The Canberra Times) with a house style
    +# dating back to the 1970s, I expect because other newspapers weren't
    +# fully indexed.  The Canberra Times strongly preferred abbreviations
    +# like "AEDT".  The first occurrence of "AEDT" was a World Weather
    +# column (1971-11-17, page 24), and of "ACDT" was a Scoreboard column
    +# (1993-01-24, p 16).  The style was the typical usage but was not
    +# strictly enforced; for example, "Welcome to the twilight zones ..."
    +# (1994-10-29, p 1) uses the abbreviations AEST/AEDT, CST/CDT, and
    +# WST, and goes on to say, "The confusion and frustration some feel
    +# about the lack of uniformity among Australia's six states and two
    +# territories has prompted one group to form its very own political
    +# party -- the Sydney-based Daylight Saving Extension Party."
    +#
    +# I also surveyed federal government sources.  They did not agree:
    +#
    +#   The Australian Government (2014-03-26)
    +#   http://australia.gov.au/about-australia/our-country/time
    +#   (This document was produced by the Department of Finance.)
    +#   AEST ACST AWST AEDT ACDT
    +#
    +#   Bureau of Meteorology (2012-11-08)
    +#   http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml
    +#   EST CST WST EDT CDT
    +#
    +#   Civil Aviation Safety Authority (undated)
    +#   http://services.casa.gov.au/outnback/inc/pages/episode3/episode-3_time_zones.shtml
    +#   EST CST WST (no abbreviations given for DST)
    +#
    +#   Geoscience Australia (2011-11-24)
    +#   http://www.ga.gov.au/geodesy/astro/sunrise.jsp
    +#   AEST ACST AWST AEDT ACDT
    +#
    +#   Parliamentary Library (2008-11-10)
    +#   http://www.aph.gov.au/binaries/library/pubs/rp/2008-09/09rp14.pdf
    +#   EST CST WST preferred for standard time; AEST AEDT ACST ACDT also used
    +#
    +#   The Transport Safety Bureau has an extensive series of accident reports,
    +#   and investigators seem to use whatever abbreviation they like.
    +#   Googling site:atsb.gov.au found the following number of unique hits:
    +#   311 "ESuT", 195 "EDT", 26 "AEDT", 83 "CSuT", 46 "CDT".
    +#   "_SuT" tended to appear in older reports, and "A_DT" tended to
    +#   appear in reports of events with international implications.
    +#
    +# From the above it appears that there is a working consensus in
    +# Australia to use trailing "DT" for daylight saving time; although
    +# some sources use trailing "SST" or "ST" or "SuT" they are by far in
    +# the minority.  The case for leading "A" is weaker, but since it
    +# seems to be preferred in the overall web and is preferred in all
    +# the leading newspaper websites and in many government departments,
    +# it has a stronger case than omitting the leading "A".  The current
    +# version of the database therefore uses abbreviations like "AEST" and
    +# "AEDT" for Australian time zones.
     
     # From Paul Eggert (1995-12-19):
     # Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
     # Mark Prior writes that his newspaper
     # reports that NSW's fall 1995 change will occur at 2:00,
     # but Robert Elz says it's been 3:00 in Victoria since 1970
    -# and perhaps the newspaper's `2:00' is referring to standard time.
    +# and perhaps the newspaper's '2:00' is referring to standard time.
     # For now we'll continue to assume 2:00s for changes since 1960.
     
     # From Eric Ulevik (1998-01-05):
    @@ -1055,17 +999,14 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # relevant entries in this database.
     #
     # NSW (including LHI and Broken Hill):
    -# 
     # Standard Time Act 1987 (updated 1995-04-04)
    -# 
    +# http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html
     # ACT
    -# 
     # Standard Time and Summer Time Act 1972
    -# 
    +# http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html
     # SA
    -# 
     # Standard Time Act, 1898
    -# 
    +# http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html
     
     # From David Grosz (2005-06-13):
     # It was announced last week that Daylight Saving would be extended by
    @@ -1083,7 +1024,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # Victoria: I wasn't able to find anything separate, but the other articles
     # allude to it.
     # But not Queensland
    -# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
    +# http://www.news.com.au/story/0,10117,15564030-1248,00.html
     
     # Northern Territory
     
    @@ -1130,9 +1071,9 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # The 1992 ending date used in the rules is a best guess;
     # it matches what was used in the past.
     
    -# 
     # The Australian Bureau of Meteorology FAQ
    -#  (1999-09-27) writes that Giles Meteorological Station uses
    +# http://www.bom.gov.au/faq/faqgen.htm
    +# (1999-09-27) writes that Giles Meteorological Station uses
     # South Australian time even though it's located in Western Australia.
     
     # Queensland
    @@ -1173,9 +1114,9 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
     
     # From Christopher Hunt (2006-11-21), after an advance warning
    -# from Jesper Norgaard Welen (2006-11-01):
    +# from Jesper Nørgaard Welen (2006-11-01):
     # WA are trialing DST for three years.
    -# 
    +# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf
     
     # From Rives McDow (2002-04-09):
     # The most interesting region I have found consists of three towns on the
    @@ -1189,7 +1130,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # From Paul Eggert (2002-04-09):
     # This is confirmed by the section entitled
     # "What's the deal with time zones???" in
    -# .
    +# http://www.earthsci.unimelb.edu.au/~awatkins/null.html
     #
     # From Alex Livingston (2006-12-07):
     # ... it was just on four years ago that I drove along the Eyre Highway,
    @@ -1337,7 +1278,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # Based on law library research by John Mackin,
     # who notes:
     #	In Australia, time is not legislated federally, but rather by the
    -#	individual states.  Thus, while such terms as ``Eastern Standard Time''
    +#	individual states.  Thus, while such terms as "Eastern Standard Time"
     #	[I mean, of course, Australian EST, not any other kind] are in common
     #	use, _they have NO REAL MEANING_, as they are not defined in the
     #	legislation.  This is very important to understand.
    @@ -1345,48 +1286,42 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     
     # From Eric Ulevik (1999-05-26):
     # DST will start in NSW on the last Sunday of August, rather than the usual
    -# October in 2000.  [See: Matthew Moore,
    -# 
    -# Two months more daylight saving
    -# 
    -# Sydney Morning Herald (1999-05-26).]
    +# October in 2000.  See: Matthew Moore,
    +# Two months more daylight saving, Sydney Morning Herald (1999-05-26).
    +# http://www.smh.com.au/news/9905/26/pageone/pageone4.html
     
     # From Paul Eggert (1999-09-27):
     # See the following official NSW source:
    -# 
     # Daylight Saving in New South Wales.
    -# 
    +# http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ
     #
     # Narrabri Shire (NSW) council has announced it will ignore the extension of
     # daylight saving next year.  See:
    -# 
     # Narrabri Council to ignore daylight saving
    -#  (1999-07-22).  For now, we'll wait to see if this really happens.
    +# http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm
    +# (1999-07-22).  For now, we'll wait to see if this really happens.
     #
     # Victoria will following NSW.  See:
    -# 
    -# Vic to extend daylight saving
    -#  (1999-07-28).
    +# Vic to extend daylight saving (1999-07-28)
    +# http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm
     #
     # However, South Australia rejected the DST request.  See:
    -# 
    -# South Australia rejects Olympics daylight savings request
    -#  (1999-07-19).
    +# South Australia rejects Olympics daylight savings request (1999-07-19)
    +# http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm
     #
     # Queensland also will not observe DST for the Olympics.  See:
    -# 
     # Qld says no to daylight savings for Olympics
    -#  (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
    -# ``Look you've got to remember in my family when this came up last time
    +# http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm
    +# (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
    +# "Look you've got to remember in my family when this came up last time
     # I voted for it, my wife voted against it and she said to me it's all very
     # well for you, you don't have to worry about getting the children out of
     # bed, getting them to school, getting them to sleep at night.
    -# I've been through all this argument domestically...my wife rules.''
    +# I've been through all this argument domestically...my wife rules."
     #
     # Broken Hill will stick with South Australian time in 2000.  See:
    -# 
    -# Broken Hill to be behind the times
    -#  (1999-07-21).
    +# Broken Hill to be behind the times (1999-07-21)
    +# http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm
     
     # IATA SSIM (1998-09) says that the spring 2000 change for Australian
     # Capital Territory, New South Wales except Lord Howe Island and Broken
    @@ -1402,7 +1337,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # Yancowinna
     
     # From John Mackin (1989-01-04):
    -# `Broken Hill' means the County of Yancowinna.
    +# 'Broken Hill' means the County of Yancowinna.
     
     # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
     # # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
    @@ -1459,9 +1394,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # summer (southern hemisphere).
     #
     # From
    -# 
     # http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
    -# 
     # The extended daylight saving period that South Australia has been trialling
     # for over the last year is now set to be ongoing.
     # Daylight saving will continue to start on the first Sunday in October each
    @@ -1471,9 +1404,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # the ACT for all 52 weeks of the year...
     #
     # We have a wrap-up here:
    -# 
     # http://www.timeanddate.com/news/time/south-australia-extends-dst.html
    -# 
     ###############################################################################
     
     # New Zealand
    @@ -1482,7 +1413,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # the 1989/90 year was a trial of an extended "daylight saving" period.
     # This trial was deemed successful and the extended period adopted for
     # subsequent years (with the addition of a further week at the start).
    -# source -- phone call to Ministry of Internal Affairs Head Office.
    +# source - phone call to Ministry of Internal Affairs Head Office.
     
     # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
     # # The Country of New Zealand   (Australia's east island -) Gee they hate that!
    @@ -1524,6 +1455,19 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # that DST will begin on 2007-09-30 2008-04-06.
     # http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
     
    +# From Paul Eggert (2014-07-14):
    +# Chatham Island time was formally standardized on 1957-01-01 by
    +# New Zealand's Standard Time Amendment Act 1956 (1956-10-26).
    +# http://www.austlii.edu.au/nz/legis/hist_act/staa19561956n100244.pdf
    +# According to Google Books snippet view, a speaker in the New Zealand
    +# parliamentary debates in 1956 said "Clause 78 makes provision for standard
    +# time in the Chatham Islands.  The time there is 45 minutes in advance of New
    +# Zealand time.  I understand that is the time they keep locally, anyhow."
    +# For now, assume this practice goes back to the introduction of standard time
    +# in New Zealand, as this would make Chatham Islands time almost exactly match
    +# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
    +# not observe New Zealand's prewar DST.
    +
     ###############################################################################
     
     
    @@ -1543,7 +1487,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     
     # From the BBC World Service in
     # http://news.bbc.co.uk/2/hi/asia-pacific/205226.stm (1998-10-31 16:03 UTC):
    -# The Fijiian government says the main reasons for the time change is to
    +# The Fijian government says the main reasons for the time change is to
     # improve productivity and reduce road accidents.... [T]he move is also
     # intended to boost Fiji's ability to attract tourists to witness the dawning
     # of the new millennium.
    @@ -1551,16 +1495,12 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
     # reports that Fiji has discontinued DST.
     
    -# Johnston
    -
    -# Johnston data is from usno1995.
    -
     
     # Kiribati
     
     # From Paul Eggert (1996-01-22):
     # Today's _Wall Street Journal_ (page 1) reports that Kiribati
    -# ``declared it the same day [throughout] the country as of Jan. 1, 1995''
    +# "declared it the same day [throughout] the country as of Jan. 1, 1995"
     # as part of the competition to be first into the 21st century.
     
     
    @@ -1575,8 +1515,8 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     
     # N Mariana Is, Guam
     
    -# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
    -# Philippines and the Ladrones from America,'' and implies that the Ladrones
    +# Howse writes (p 153) "The Spaniards, on the other hand, reached the
    +# Philippines and the Ladrones from America," and implies that the Ladrones
     # (now called the Marianas) kept American date for quite some time.
     # For now, we assume the Ladrones switched at the same time as the Philippines;
     # see Asia/Manila.
    @@ -1590,17 +1530,16 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # Micronesia
     
     # Alan Eugene Davis writes (1996-03-16),
    -# ``I am certain, having lived there for the past decade, that "Truk"
    -# (now properly known as Chuuk) ... is in the time zone GMT+10.''
    +# "I am certain, having lived there for the past decade, that 'Truk'
    +# (now properly known as Chuuk) ... is in the time zone GMT+10."
     #
     # Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
     # on 1978-10-01; ignore this for now.
     
     # From Paul Eggert (1999-10-29):
     # The Federated States of Micronesia Visitors Board writes in
    -# 
    -# The Federated States of Micronesia - Visitor Information
    -#  (1999-01-26)
    +# The Federated States of Micronesia - Visitor Information (1999-01-26)
    +# http://www.fsmgov.org/info/clocks.html
     # that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
     # We don't know when Kosrae switched from UTC+12; assume January 1 for now.
     
    @@ -1646,27 +1585,34 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # Sacramento but it was changed a couple of years ago.
     
     
    -# Samoa
    +# (Western) Samoa and American Samoa
     
     # Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
     # that in 1879 the King of Samoa decided to change
    -# ``the date in his kingdom from the Antipodean to the American system,
    -# ordaining -- by a masterpiece of diplomatic flattery -- that
    -# the Fourth of July should be celebrated twice in that year.''
    -
    +# "the date in his kingdom from the Antipodean to the American system,
    +# ordaining - by a masterpiece of diplomatic flattery - that
    +# the Fourth of July should be celebrated twice in that year."
    +
    +# Although Shanks & Pottenger says they both switched to UTC-11:30
    +# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
    +# for American Samoa, e.g., the US National Bureau of Standards
    +# circular "Standard Time Throughout the World", 1932.
    +# Assume American Samoa switched to UTC-11 in 1911, not 1950,
    +# and that after 1950 they agreed until (western) Samoa skipped a
    +# day in 2011.  Assume also that the Samoas follow the US and New
    +# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
     
     # Tonga
     
     # From Paul Eggert (1996-01-22):
    -# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
    -# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
    +# Today's _Wall Street Journal_ (p 1) reports that "Tonga has been plotting
    +# to sneak ahead of [New Zealanders] by introducing daylight-saving time."
     # Since Kiribati has moved the Date Line it's not clear what Tonga will do.
     
     # Don Mundell writes in the 1997-02-20 Tonga Chronicle
    -# 
    -# How Tonga became `The Land where Time Begins'
    -# :
    -
    +# How Tonga became 'The Land where Time Begins':
    +# http://www.tongatapu.net.to/tonga/homeland/timebegins.htm
    +#
     # Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
     # 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
     # standard time in 1940s, Tonga had the choice of subtracting from its
    @@ -1674,8 +1620,8 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # advancing its time to maintain the differential of 13 degrees
     # (approximately 50 minutes ahead of New Zealand time).
     #
    -# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
    -# Tungi, preferred to ensure Tonga's title as the land where time
    +# Because His Majesty King Tāufaʻāhau Tupou IV, then Crown Prince
    +# Tungī, preferred to ensure Tonga's title as the land where time
     # begins, the Legislative Assembly approved the latter change.
     #
     # But some of the older, more conservative members from the outer
    @@ -1701,9 +1647,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # * Tonga will introduce DST in November
     #
     # I was given this link by John Letts:
    -# 
     # http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
    -# 
     #
     # I have not been able to find exact dates for the transition in November
     # yet. By reading this article it seems like Fiji will be 14 hours ahead
    @@ -1711,9 +1655,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # (12 + 1 hour DST).
     
     # From Arthur David Olson (1999-09-20):
    -# According to 
    -# http://www.tongaonline.com/news/sept1799.html
    -# :
    +# According to :
     # "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
     # and annually thereafter from the first Saturday in October through the
     # third Saturday of April.  Under the system approved by Privy Council on
    @@ -1731,7 +1673,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # instead of the original reported date April 16. Unfortunately, the article
     # is no longer available on the site, and I did not make a copy of the
     # text, and I have forgotten to report it here.
    -# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
    +# (Original URL was )
     
     # From Rives McDow (2000-12-01):
     # Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
    @@ -1751,7 +1693,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # From Vernice Anderson, Personal Secretary to Philip Jessup,
     # US Ambassador At Large (oral history interview, 1971-02-02):
     #
    -# Saturday, the 14th [of October, 1950] -- ...  The time was all the
    +# Saturday, the 14th [of October, 1950] - ...  The time was all the
     # more confusing at that point, because we had crossed the
     # International Date Line, thus getting two Sundays.  Furthermore, we
     # discovered that Wake Island had two hours of daylight saving time
    @@ -1796,7 +1738,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # on the high seas.  Whenever a ship was within the territorial waters of any
     # nation it would use that nation's standard time.  The captain was permitted
     # to change his ship's clocks at a time of his choice following his ship's
    -# entry into another zone time--he often chose midnight.  These zones were
    +# entry into another zone time - he often chose midnight.  These zones were
     # adopted by all major fleets between 1920 and 1925 but not by many
     # independent merchant ships until World War II.
     
    @@ -1804,6 +1746,6 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
     # (2005-03-20):
     #
     # The American Practical Navigator (2002)
    -# 
    +# http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187
     # talks only about the 180-degree meridian with respect to ships in
     # international waters; it ignores the international date line.
    diff --git a/test/sun/util/calendar/zi/tzdata/backward b/test/sun/util/calendar/zi/tzdata/backward
    index 5afe9a317ff7fabc9a4f0d311fcf0f63c6c9ffbd..ba012f45733b46e8fc06f932b8c76d88e4c3f591 100644
    --- a/test/sun/util/calendar/zi/tzdata/backward
    +++ b/test/sun/util/calendar/zi/tzdata/backward
    @@ -21,15 +21,15 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
     # This file provides links between current names for time zones
     # and their old names.  Many names changed in late 1993.
     
    +# Link	TARGET			LINK-NAME
     Link	Africa/Asmara		Africa/Asmera
    -Link	Africa/Bamako		Africa/Timbuktu
    +Link	Africa/Abidjan		Africa/Timbuktu
     Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
     Link	America/Adak		America/Atka
     Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
    @@ -50,8 +50,11 @@ Link	America/Port_of_Spain	America/Virgin
     Link	Pacific/Auckland	Antarctica/South_Pole
     Link	Asia/Ashgabat		Asia/Ashkhabad
     Link	Asia/Kolkata		Asia/Calcutta
    -Link	Asia/Chongqing		Asia/Chungking
    +Link	Asia/Shanghai		Asia/Chongqing
    +Link	Asia/Shanghai		Asia/Chungking
     Link	Asia/Dhaka		Asia/Dacca
    +Link	Asia/Shanghai		Asia/Harbin
    +Link	Asia/Urumqi		Asia/Kashgar
     Link	Asia/Kathmandu		Asia/Katmandu
     Link	Asia/Macau		Asia/Macao
     Link	Asia/Ho_Chi_Minh	Asia/Saigon
    diff --git a/test/sun/util/calendar/zi/tzdata/etcetera b/test/sun/util/calendar/zi/tzdata/etcetera
    index ebaa5fdfc0485682cdfe7b48e8b9e8ab46a9388c..d2fb91c9dd61d63aaaa6277f45c856d5c44f2707 100644
    --- a/test/sun/util/calendar/zi/tzdata/etcetera
    +++ b/test/sun/util/calendar/zi/tzdata/etcetera
    @@ -21,7 +21,6 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    @@ -37,7 +36,7 @@ Zone	Etc/UTC		0	-	UTC
     Zone	Etc/UCT		0	-	UCT
     
     # The following link uses older naming conventions,
    -# but it belongs here, not in the file `backward',
    +# but it belongs here, not in the file 'backward',
     # as functions like gmtime load the "GMT" file to handle leap seconds properly.
     # We want this to work even on installations that omit the other older names.
     Link	Etc/GMT				GMT
    diff --git a/test/sun/util/calendar/zi/tzdata/europe b/test/sun/util/calendar/zi/tzdata/europe
    index 226c393a0f2e38573ab264ab11753d025f32d919..0c5f5667da9085eb5879fe9168ea4320f2fbe6fa 100644
    --- a/test/sun/util/calendar/zi/tzdata/europe
    +++ b/test/sun/util/calendar/zi/tzdata/europe
    @@ -21,15 +21,15 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    -# This data is by no means authoritative; if you think you know better,
    +# This file is by no means authoritative; if you think you know better,
     # go ahead and edit the file (and please send any changes to
    -# tz@iana.org for general use in the future).
    +# tz@iana.org for general use in the future).  For more, please see
    +# the file CONTRIBUTING in the tz distribution.
     
    -# From Paul Eggert (2006-03-22):
    +# From Paul Eggert (2014-05-31):
     # A good source for time zone historical data outside the U.S. is
     # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
     # San Diego: ACS Publications, Inc. (2003).
    @@ -40,6 +40,9 @@
     # published semiannually.  Law sent in several helpful summaries
     # of the IATA's data after 1990.
     #
    +# A reliable and entertaining source about time zones is
    +# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +#
     # Except where otherwise noted, Shanks & Pottenger is the source for
     # entries through 1991, and IATA SSIM is the source for entries afterwards.
     #
    @@ -49,9 +52,9 @@
     #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
     #	which I found in the UCLA library.
     #
    -#	
     #	William Willett, The Waste of Daylight, 19th edition
    -#	 (1914-03)
    +#	
    +#	[PDF] (1914-03)
     #
     #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
     #	.  He writes:
    @@ -59,10 +62,20 @@
     #	may be sent to Mr. John Milne, Royal Geographical Society,
     #	Savile Row, London."  Nowadays please email them to tz@iana.org.
     #
    -#	Brazil's Departamento Servico da Hora (DSH),
    -#	
    +#	Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
    +#	This Russian-language source was consulted by Vladimir Karpinsky; see
    +#	http://mm.icann.org/pipermail/tz/2014-August/021320.html
    +#	The full Russian citation is:
    +#	Бялокоз, Евгений Людвигович. Новый счет времени в течении суток
    +#	введенный декретом Совета народных комиссаров для всей России с 1-го
    +#	июля 1919 г. / Изд. 2-е Междуведомственной комиссии. - Петроград:
    +#	Десятая гос. тип., 1919.
    +#	http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf
    +#
    +#	Brazil's Divisão Serviço da Hora (DSHO),
     #	History of Summer Time
    -#	 (1998-09-21, in Portuguese)
    +#	
    +#	(1998-09-21, in Portuguese)
     
     #
     # I invented the abbreviations marked '*' in the following table;
    @@ -81,10 +94,8 @@
     #        1:00       CET CEST CEMT Central Europe
     #        1:00:14    SET           Swedish (1879-1899)*
     #        2:00       EET EEST      Eastern Europe
    -#        3:00       MSK MSD       Moscow
    -#
    -# A reliable and entertaining source about time zones, especially in Britain,
    -# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +#        3:00       FET           Further-eastern Europe*
    +#        3:00       MSK MSD  MSM* Moscow
     
     # From Peter Ilieve (1994-12-04),
     # The original six [EU members]: Belgium, France, (West) Germany, Italy,
    @@ -128,7 +139,7 @@
     # along the towpath within a few yards of it.'
     #
     # I have a one inch to one mile map of London and my estimate of the stone's
    -# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
    +# position is 51 degrees 28' 30" N, 0 degrees 18' 45" W. The longitude should
     # be within about +-2". The Ordnance Survey grid reference is TQ172761.
     #
     # [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
    @@ -160,8 +171,22 @@
     # transition date for London, namely 1847-12-01.  We don't know as much
     # about Dublin, so we use 1880-08-02, the legal transition time.
     
    -# From Paul Eggert (2003-09-27):
    -# Summer Time was first seriously proposed by William Willett (1857-1915),
    +# From Paul Eggert (2014-07-19):
    +# The ancients had no need for daylight saving, as they kept time
    +# informally or via hours whose length depended on the time of year.
    +# Daylight saving time in its modern sense was invented by the
    +# New Zealand entomologist George Vernon Hudson (1867-1946),
    +# whose day job as a postal clerk led him to value
    +# after-hours daylight in which to pursue his research.
    +# In 1895 he presented a paper to the Wellington Philosophical Society
    +# that proposed a two-hour daylight-saving shift.  See:
    +# Hudson GV. On seasonal time-adjustment in countries south of lat. 30 deg.
    +# Transactions and Proceedings of the New Zealand Institute. 1895;28:734
    +# http://rsnz.natlib.govt.nz/volume/rsnz_28/rsnz_28_00_006110.html
    +# Although some interest was expressed in New Zealand, his proposal
    +# did not find its way into law and eventually it was almost forgotten.
    +#
    +# In England, DST was independently reinvented by William Willett (1857-1915),
     # a London builder and member of the Royal Astronomical Society
     # who circulated a pamphlet "The Waste of Daylight" (1907)
     # that proposed advancing clocks 20 minutes on each of four Sundays in April,
    @@ -174,7 +199,7 @@
     # A monument to Willett was unveiled on 1927-05-21, in an open space in
     # a 45-acre wood near Chislehurst, Kent that was purchased by popular
     # subscription and open to the public.  On the south face of the monolith,
    -# designed by G. W. Miller, is the...William Willett Memorial Sundial,
    +# designed by G. W. Miller, is the William Willett Memorial Sundial,
     # which is permanently set to Summer Time.
     
     # From Winston Churchill (1934-04-28):
    @@ -183,9 +208,9 @@
     # between 160 and 170 hours more daylight leisure, to a war which
     # plunged Europe into darkness for four years, and shook the
     # foundations of civilization throughout the world.
    -#	-- 
    -#	"A Silent Toast to William Willett", Pictorial Weekly
    -#	
    +#	-- "A Silent Toast to William Willett", Pictorial Weekly;
    +#	republished in Finest Hour (Spring 2002) 1(114):26
    +#	http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
     
     # From Paul Eggert (1996-09-03):
     # The OED Supplement says that the English originally said "Daylight Saving"
    @@ -194,7 +219,6 @@
     # proponents (who eventually won the argument) are quoted as using "Summer".
     
     # From Arthur David Olson (1989-01-19):
    -#
     # A source at the British Information Office in New York avers that it's
     # known as "British" Summer Time in all parts of the United Kingdom.
     
    @@ -221,8 +245,8 @@
     # official designation; the reply of the 21st was that there wasn't
     # but he couldn't think of anything better than the "Double British
     # Summer Time" that the BBC had been using informally.
    -# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
    -# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
    +# http://www.polyomino.org.uk/british-time/bbc-19410418.png
    +# http://www.polyomino.org.uk/british-time/ho-19410421.png
     
     # From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
     # [N]o official designation has as far as I know been adopted for the time
    @@ -239,23 +263,14 @@
     # the history of summer time legislation in the United Kingdom.
     # Since 1998 Joseph S. Myers has been updating
     # and extending this list, which can be found in
    -# http://student.cusu.cam.ac.uk/~jsm28/british-time/
    -# 
    -# History of legal time in Britain
    -# 
    -# Rob Crowther (2012-01-04) reports that that URL no longer
    -# exists, and the article can now be found at:
    -# 
     # http://www.polyomino.org.uk/british-time/
    -# 
     
     # From Joseph S. Myers (1998-01-06):
     #
     # The legal time in the UK outside of summer time is definitely GMT, not UTC;
     # see Lord Tanlaw's speech
    -# 
    -# (Lords Hansard 11 June 1997 columns 964 to 976)
    -# .
    +# http://www.publications.parliament.uk/pa/ld199798/ldhansrd/vo970611/text/70611-10.htm#70611-10_head0
    +# (Lords Hansard 11 June 1997 columns 964 to 976).
     
     # From Paul Eggert (2006-03-22):
     #
    @@ -295,8 +310,8 @@
     #   -- James Joyce, Ulysses
     
     # From Joseph S. Myers (2005-01-26):
    -# Irish laws are available online at www.irishstatutebook.ie.  These include
    -# various relating to legal time, for example:
    +# Irish laws are available online at .
    +# These include various relating to legal time, for example:
     #
     # ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
     #
    @@ -458,25 +473,27 @@ Rule	GB-Eire 1990	1995	-	Oct	Sun>=22	1:00u	0	GMT
     # Use Europe/London for Jersey, Guernsey, and the Isle of Man.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1 0:00s
    +Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1  0:00s
     			 0:00	GB-Eire	%s	1968 Oct 27
    -			 1:00	-	BST	1971 Oct 31 2:00u
    +			 1:00	-	BST	1971 Oct 31  2:00u
     			 0:00	GB-Eire	%s	1996
     			 0:00	EU	GMT/BST
     Link	Europe/London	Europe/Jersey
     Link	Europe/London	Europe/Guernsey
     Link	Europe/London	Europe/Isle_of_Man
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
    -			-0:25:21 -	DMT	1916 May 21 2:00
    -			-0:25:21 1:00	IST	1916 Oct  1 2:00s
    +			-0:25:21 -	DMT	1916 May 21  2:00
    +			-0:25:21 1:00	IST	1916 Oct  1  2:00s
     			 0:00	GB-Eire	%s	1921 Dec  6 # independence
    -			 0:00	GB-Eire	GMT/IST	1940 Feb 25 2:00
    -			 0:00	1:00	IST	1946 Oct  6 2:00
    -			 0:00	-	GMT	1947 Mar 16 2:00
    -			 0:00	1:00	IST	1947 Nov  2 2:00
    -			 0:00	-	GMT	1948 Apr 18 2:00
    +			 0:00	GB-Eire	GMT/IST	1940 Feb 25  2:00
    +			 0:00	1:00	IST	1946 Oct  6  2:00
    +			 0:00	-	GMT	1947 Mar 16  2:00
    +			 0:00	1:00	IST	1947 Nov  2  2:00
    +			 0:00	-	GMT	1948 Apr 18  2:00
     			 0:00	GB-Eire	GMT/IST	1968 Oct 27
    -			 1:00	-	IST	1971 Oct 31 2:00u
    +			 1:00	-	IST	1971 Oct 31  2:00u
     			 0:00	GB-Eire	GMT/IST	1996
     			 0:00	EU	GMT/IST
     
    @@ -495,10 +512,9 @@ Rule	EU	1979	1995	-	Sep	lastSun	 1:00u	0	-
     Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
     Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
     # The most recent directive covers the years starting in 2002.  See:
    -# 
     # Directive 2000/84/EC of the European Parliament and of the Council
     # of 19 January 2001 on summer-time arrangements.
    -# 
    +# http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT
     
     # W-Eur differs from EU only in that W-Eur uses standard time.
     Rule	W-Eur	1977	1980	-	Apr	Sun>=1	 1:00s	1:00	S
    @@ -521,18 +537,18 @@ Rule	C-Eur	1943	only	-	Oct	 4	 2:00s	0	-
     Rule	C-Eur	1944	1945	-	Apr	Mon>=1	 2:00s	1:00	S
     # Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
     Rule	C-Eur	1944	only	-	Oct	 2	 2:00s	0	-
    -# From Jesper Norgaard Welen (2008-07-13):
    +# From Jesper Nørgaard Welen (2008-07-13):
     #
     # I found what is probably a typo of 2:00 which should perhaps be 2:00s
     # in the C-Eur rule from tz database version 2008d (this part was
    -# corrected in version 2008d). The circumstancial evidence is simply the
    +# corrected in version 2008d). The circumstantial evidence is simply the
     # tz database itself, as seen below:
     #
     # Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15  0:01
     #    0:00 France WE%sT 1945 Sep 16  3:00
     #
     # Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
    -#    0:00 France WE%sT 1945 Sep 16 3:00
    +#    0:00 France WE%sT 1945 Sep 16  3:00
     #
     # Zone Europe/Belgrade 1:22:00 - LMT 1884
     #    1:00 1:00 CEST 1945 Sep 16  2:00s
    @@ -576,16 +592,16 @@ Rule	E-Eur	1981	max	-	Mar	lastSun	 0:00	1:00	S
     Rule	E-Eur	1996	max	-	Oct	lastSun	 0:00	0	-
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST	# Moscow Summer Time
    -Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT	# Moscow Mean Time
    -Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST	# Moscow Double Summer Time
    +Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST  # Moscow Summer Time
    +Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT  # Moscow Mean Time
    +Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST # Moscow Double Summer Time
     Rule	Russia	1918	only	-	Sep	16	 1:00	1:00	MST
     Rule	Russia	1919	only	-	May	31	23:00	2:00	MDST
    -Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	S
    -Rule	Russia	1919	only	-	Aug	16	 0:00	0	-
    -Rule	Russia	1921	only	-	Feb	14	23:00	1:00	S
    -Rule	Russia	1921	only	-	Mar	20	23:00	2:00	M # Midsummer
    -Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	S
    +Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	MSD
    +Rule	Russia	1919	only	-	Aug	16	 0:00	0	MSK
    +Rule	Russia	1921	only	-	Feb	14	23:00	1:00	MSD
    +Rule	Russia	1921	only	-	Mar	20	23:00	2:00	MSM  # Midsummer
    +Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	MSD
     Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
     # Act No.925 of the Council of Ministers of the USSR (1980-10-24):
     Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
    @@ -607,14 +623,10 @@ Rule	Russia	1996	2010	-	Oct	lastSun	 2:00s	0	-
     # According to the law Russia is abolishing daylight saving time.
     #
     # Medvedev signed a law "On the Calculation of Time" (in russian):
    -# 
     # http://bmockbe.ru/events/?ID=7583
    -# 
     #
     # Medvedev signed a law on the calculation of the time (in russian):
    -# 
     # http://www.regnum.ru/news/polit/1413906.html
    -# 
     
     # From Arthur David Olson (2011-06-15):
     # Take "abolishing daylight saving time" to mean that time is now considered
    @@ -634,10 +646,10 @@ Zone	EET		2:00	EU	EE%sT
     # From Markus Kuhn (1996-07-12):
     # The official German names ... are
     #
    -#	Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
    -#	Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
    +#	Mitteleuropäische Zeit (MEZ)         = UTC+01:00
    +#	Mitteleuropäische Sommerzeit (MESZ)  = UTC+02:00
     #
    -# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
    +# as defined in the German Time Act (Gesetz über die Zeitbestimmung (ZeitG),
     # 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
     # I wrote ... to the German Federal Physical-Technical Institution
     #
    @@ -692,7 +704,7 @@ Zone	Europe/Tirane	1:19:20 -	LMT	1914
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Andorra	0:06:04 -	LMT	1901
     			0:00	-	WET	1946 Sep 30
    -			1:00	-	CET	1985 Mar 31 2:00
    +			1:00	-	CET	1985 Mar 31  2:00
     			1:00	EU	CE%sT
     
     # Austria
    @@ -718,9 +730,9 @@ Rule	Austria	1980	only	-	Sep	28	0:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
     			1:00	C-Eur	CE%sT	1920
    -			1:00	Austria	CE%sT	1940 Apr  1 2:00s
    -			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
    -			1:00	1:00	CEST	1945 Apr 12 2:00s
    +			1:00	Austria	CE%sT	1940 Apr  1  2:00s
    +			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
    +			1:00	1:00	CEST	1945 Apr 12  2:00s
     			1:00	-	CET	1946
     			1:00	Austria	CE%sT	1981
     			1:00	EU	CE%sT
    @@ -731,38 +743,29 @@ Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
     # GMT+3 without DST (was GMT+2 with DST).
     #
     # Sources (Russian language):
    -# 1.
    -# 
     # http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
    -# 
    -# 2.
    -# 
     # http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
    -# 
    -# 3.
    -# 
     # http://news.tut.by/society/250578.html
    -# 
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Minsk	1:50:16 -	LMT	1880
    -			1:50	-	MMT	1924 May 2 # Minsk Mean Time
    +			1:50	-	MMT	1924 May  2 # Minsk Mean Time
     			2:00	-	EET	1930 Jun 21
     			3:00	-	MSK	1941 Jun 28
     			1:00	C-Eur	CE%sT	1944 Jul  3
     			3:00	Russia	MSK/MSD	1990
    -			3:00	-	MSK	1991 Mar 31 2:00s
    -			2:00	1:00	EEST	1991 Sep 29 2:00s
    -			2:00	-	EET	1992 Mar 29 0:00s
    -			2:00	1:00	EEST	1992 Sep 27 0:00s
    -			2:00	Russia	EE%sT	2011 Mar 27 2:00s
    -			3:00	-	FET # Further-eastern European Time
    +			3:00	-	MSK	1991 Mar 31  2:00s
    +			2:00	1:00	EEST	1991 Sep 29  2:00s
    +			2:00	-	EET	1992 Mar 29  0:00s
    +			2:00	1:00	EEST	1992 Sep 27  0:00s
    +			2:00	Russia	EE%sT	2011 Mar 27  2:00s
    +			3:00	-	FET
     
     # Belgium
     #
     # From Paul Eggert (1997-07-02):
     # Entries from 1918 through 1991 are taken from:
     #	Annuaire de L'Observatoire Royal de Belgique,
    -#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
    +#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
     #	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
     #	pp 8-9.
     # LMT before 1892 was 0:17:30, according to the official journal of Belgium:
    @@ -812,7 +815,7 @@ Rule	Belgium	1946	only	-	May	19	 2:00s	1:00	S
     Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Brussels	0:17:30 -	LMT	1880
    -			0:17:30	-	BMT	1892 May  1 12:00 # Brussels MT
    +			0:17:30	-	BMT	1892 May  1 12:00  # Brussels MT
     			0:00	-	WET	1914 Nov  8
     			1:00	-	CET	1916 May  1  0:00
     			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
    @@ -828,8 +831,8 @@ Zone	Europe/Brussels	0:17:30 -	LMT	1880
     #
     # From Plamen Simenov via Steffen Thorsen (1999-09-09):
     # A document of Government of Bulgaria (No.94/1997) says:
    -# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
    -# EETDST --> EET is in 04:00 Local time in last Sunday of October
    +# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
    +# EETDST -> EET is in 04:00 Local time in last Sunday of October
     #
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Bulg	1979	only	-	Mar	31	23:00	1:00	S
    @@ -842,7 +845,7 @@ Zone	Europe/Sofia	1:33:16 -	LMT	1880
     			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
     			2:00	-	EET	1942 Nov  2  3:00
     			1:00	C-Eur	CE%sT	1945
    -			1:00	-	CET	1945 Apr 2 3:00
    +			1:00	-	CET	1945 Apr  2  3:00
     			2:00	-	EET	1979 Mar 31 23:00
     			2:00	Bulg	EE%sT	1982 Sep 26  2:00
     			2:00	C-Eur	EE%sT	1991
    @@ -866,15 +869,15 @@ Rule	Czech	1948	only	-	Apr	18	2:00s	1:00	S
     Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Prague	0:57:44 -	LMT	1850
    -			0:57:44	-	PMT	1891 Oct     # Prague Mean Time
    -			1:00	C-Eur	CE%sT	1944 Sep 17 2:00s
    +			0:57:44	-	PMT	1891 Oct    # Prague Mean Time
    +			1:00	C-Eur	CE%sT	1944 Sep 17  2:00s
     			1:00	Czech	CE%sT	1979
     			1:00	EU	CE%sT
     # Use Europe/Prague also for Slovakia.
     
     # Denmark, Faroe Islands, and Greenland
     
    -# From Jesper Norgaard Welen (2005-04-26):
    +# From Jesper Nørgaard Welen (2005-04-26):
     # http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
     # [introducing standard time] was in effect from 1894-01-01....
     # The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
    @@ -884,7 +887,7 @@ Zone	Europe/Prague	0:57:44 -	LMT	1850
     # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
     #
     # This provoked a new law from 1974 to make possible summer time changes
    -# in subsequenet decrees with the law
    +# in subsequent decrees with the law
     # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
     #
     # It seems however that no decree was set forward until 1980.  I have
    @@ -899,7 +902,7 @@ Zone	Europe/Prague	0:57:44 -	LMT	1850
     # was suspended on that night):
     # http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
     
    -# From Jesper Norgaard Welen (2005-06-11):
    +# From Jesper Nørgaard Welen (2005-06-11):
     # The Herning Folkeblad (1980-09-26) reported that the night between
     # Saturday and Sunday the clock is set back from three to two.
     
    @@ -923,11 +926,11 @@ Rule	Denmark	1948	only	-	Aug	 8	 2:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
     			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
    -			 1:00	Denmark	CE%sT	1942 Nov  2 2:00s
    -			 1:00	C-Eur	CE%sT	1945 Apr  2 2:00
    +			 1:00	Denmark	CE%sT	1942 Nov  2  2:00s
    +			 1:00	C-Eur	CE%sT	1945 Apr  2  2:00
     			 1:00	Denmark	CE%sT	1980
     			 1:00	EU	CE%sT
    -Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
    +Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11 # Tórshavn
     			 0:00	-	WET	1981
     			 0:00	EU	WE%sT
     #
    @@ -939,11 +942,11 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
     # From Paul Eggert (2006-03-22):
     # Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
     # and left the EU on 1985-02-01.  It therefore should have been using EU
    -# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthab
    +# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthåb
     # used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
     # rules since at least 1991.  Assume EU rules since 1980.
     
    -# From Gwillin Law (2001-06-06), citing
    +# From Gwillim Law (2001-06-06), citing
     #  (2001-03-15),
     # and with translations corrected by Steffen Thorsen:
     #
    @@ -978,16 +981,16 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
     # DPC research station at Zackenberg.
     #
     # Scoresbysund and two small villages nearby keep time UTC-1 and use
    -# the same daylight savings time period as in West Greenland (Godthab).
    +# the same daylight savings time period as in West Greenland (Godthåb).
     #
    -# The rest of Greenland, including Godthab (this area, although it
    +# The rest of Greenland, including Godthåb (this area, although it
     # includes central Greenland, is known as west Greenland), keeps time
     # UTC-3, with daylight savings methods according to European rules.
     #
     # It is common procedure to use UTC 0 in the wilderness of East and
     # North Greenland, because it is mainly Icelandic aircraft operators
     # maintaining traffic in these areas.  However, the official status of
    -# this area is that it sticks with Godthab time.  This area might be
    +# this area is that it sticks with Godthåb time.  This area might be
     # considered a dual time zone in some respects because of this.
     
     # From Rives McDow (2001-11-19):
    @@ -996,8 +999,8 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
     
     # From Paul Eggert (2006-03-22):
     # From 1997 on the CIA map shows Danmarkshavn on GMT;
    -# the 1995 map as like Godthab.
    -# For lack of better info, assume they were like Godthab before 1996.
    +# the 1995 map as like Godthåb.
    +# For lack of better info, assume they were like Godthåb before 1996.
     # startkart.no says Thule does not observe DST, but this is clearly an error,
     # so go with Shanks & Pottenger for Thule transitions until this year.
     # For 2007 on assume Thule will stay in sync with US DST rules.
    @@ -1012,15 +1015,15 @@ Rule	Thule	2007	max	-	Nov	Sun>=1	2:00	0	S
     #
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
    -			-3:00	-	WGT	1980 Apr  6 2:00
    +			-3:00	-	WGT	1980 Apr  6  2:00
     			-3:00	EU	WG%sT	1996
     			0:00	-	GMT
     Zone America/Scoresbysund -1:27:52 -	LMT	1916 Jul 28 # Ittoqqortoormiit
    -			-2:00	-	CGT	1980 Apr  6 2:00
    +			-2:00	-	CGT	1980 Apr  6  2:00
     			-2:00	C-Eur	CG%sT	1981 Mar 29
     			-1:00	EU	EG%sT
     Zone America/Godthab	-3:26:56 -	LMT	1916 Jul 28 # Nuuk
    -			-3:00	-	WGT	1980 Apr  6 2:00
    +			-3:00	-	WGT	1980 Apr  6  2:00
     			-3:00	EU	WG%sT
     Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
     			-4:00	Thule	A%sT
    @@ -1042,17 +1045,16 @@ Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
     # summer time next spring."
     
     # From Peter Ilieve (1998-11-04), heavily edited:
    -# 
     # The 1998-09-22 Estonian time law
    -# 
    +# http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390
     # refers to the Eighth Directive and cites the association agreement between
    -# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
    +# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22-27, 120).
     #
     # I also asked [my relative] whether they use any standard abbreviation
     # for their standard and summer times. He says no, they use "suveaeg"
     # (summer time) and "talveaeg" (winter time).
     
    -# From The Baltic Times (1999-09-09)
    +# From The Baltic Times  (1999-09-09)
     # via Steffen Thorsen:
     # This year will mark the last time Estonia shifts to summer time,
     # a council of the ruling coalition announced Sept. 6....
    @@ -1070,19 +1072,19 @@ Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
     # The Estonian government has changed once again timezone politics.
     # Now we are using again EU rules.
     #
    -# From Urmet Jaanes (2002-03-28):
    +# From Urmet Jänes (2002-03-28):
     # The legislative reference is Government decree No. 84 on 2002-02-21.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Tallinn	1:39:00	-	LMT	1880
    -			1:39:00	-	TMT	1918 Feb # Tallinn Mean Time
    +			1:39:00	-	TMT	1918 Feb    # Tallinn Mean Time
     			1:00	C-Eur	CE%sT	1919 Jul
     			1:39:00	-	TMT	1921 May
     			2:00	-	EET	1940 Aug  6
     			3:00	-	MSK	1941 Sep 15
     			1:00	C-Eur	CE%sT	1944 Sep 22
    -			3:00	Russia	MSK/MSD	1989 Mar 26 2:00s
    -			2:00	1:00	EEST	1989 Sep 24 2:00s
    +			3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
    +			2:00	1:00	EEST	1989 Sep 24  2:00s
     			2:00	C-Eur	EE%sT	1998 Sep 22
     			2:00	EU	EE%sT	1999 Nov  1
     			2:00	-	EET	2002 Feb 21
    @@ -1104,35 +1106,45 @@ Zone	Europe/Tallinn	1:39:00	-	LMT	1880
     # This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
     # Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
     # Finnish) at
    -#
    -# 
     # http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
    -# 
     #
     # Page 105 (56 in PDF version) has a handy table of all past daylight savings
     # transitions. It is easy enough to interpret without Finnish skills.
     #
     # This is also confirmed by Finnish Broadcasting Company's archive at:
    -#
    -# 
     # http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
    -# 
     #
     # The news clip from 1981 says that "the time between 2 and 3 o'clock does not
     # exist tonight."
     
    +# From Konstantin Hyppönen (2014-06-13):
    +# [Heikki Oja's book Aikakirja 2013]
    +# http://almanakka.helsinki.fi/images/aikakirja/Aikakirja2013kokonaan.pdf
    +# pages 104-105, including a scan from a newspaper published on Apr 2 1942
    +# say that ... [o]n Apr 2 1942, 24 o'clock (which means Apr 3 1942,
    +# 00:00), clocks were moved one hour forward. The newspaper
    +# mentions "on the night from Thursday to Friday"....
    +# On Oct 4 1942, clocks were moved at 1:00 one hour backwards.
    +#
    +# From Paul Eggert (2014-06-14):
    +# Go with Oja over Shanks.
    +
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	Finland	1942	only	-	Apr	3	0:00	1:00	S
    -Rule	Finland	1942	only	-	Oct	3	0:00	0	-
    +Rule	Finland	1942	only	-	Apr	2	24:00	1:00	S
    +Rule	Finland	1942	only	-	Oct	4	1:00	0	-
     Rule	Finland	1981	1982	-	Mar	lastSun	2:00	1:00	S
     Rule	Finland	1981	1982	-	Sep	lastSun	3:00	0	-
    +
    +# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
    +# round to nearest.
    +
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Europe/Helsinki	1:39:52 -	LMT	1878 May 31
    -			1:39:52	-	HMT	1921 May    # Helsinki Mean Time
    +Zone	Europe/Helsinki	1:39:49 -	LMT	1878 May 31
    +			1:39:49	-	HMT	1921 May    # Helsinki Mean Time
     			2:00	Finland	EE%sT	1983
     			2:00	EU	EE%sT
     
    -# Aaland Is
    +# Åland Is
     Link	Europe/Helsinki	Europe/Mariehamn
     
     
    @@ -1140,14 +1152,14 @@ Link	Europe/Helsinki	Europe/Mariehamn
     
     # From Ciro Discepolo (2000-12-20):
     #
    -# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
    +# Henri Le Corre, Régimes horaires pour le monde entier, Éditions
     # Traditionnelles - Paris 2 books, 1993
     #
    -# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
    +# Gabriel, Traité de l'heure dans le monde, Guy Trédaniel,
     # Paris, 1991
     #
    -# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
    -# Guy tredaniel, Paris 1987
    +# Françoise Gauquelin, Problèmes de l'heure résolus en astrologie,
    +# Guy Trédaniel, Paris 1987
     
     
     #
    @@ -1188,16 +1200,16 @@ Rule	France	1939	only	-	Nov	18	23:00s	0	-
     Rule	France	1940	only	-	Feb	25	 2:00	1:00	S
     # The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
     # write that they were used in Monaco and in many French locations.
    -# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
    -# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
    -# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
    +# Le Corre writes that the upper limit of the free zone was Arnéguy, Orthez,
    +# Mont-de-Marsan, Bazas, Langon, Lamothe-Montravel, Marœuil, La
    +# Rochefoucauld, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
     # Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
    -# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
    +# Paray-le-Monial, Montceau-les-Mines, Chalon-sur-Saône, Arbois,
     # Dole, Morez, St-Claude, and Collonges (Haute-Savoie).
     Rule	France	1941	only	-	May	 5	 0:00	2:00	M # Midsummer
     # Shanks & Pottenger say this transition occurred at Oct 6 1:00,
     # but go with Denis Excoffier (1997-12-12),
    -# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
    +# who quotes the Ephémérides astronomiques for 1998 from Bureau des Longitudes
     # as saying 5/10/41 22hUT.
     Rule	France	1941	only	-	Oct	 6	 0:00	1:00	S
     Rule	France	1942	only	-	Mar	 9	 0:00	2:00	M
    @@ -1218,7 +1230,7 @@ Rule	France	1976	only	-	Sep	26	 1:00	0	-
     # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
    -			0:09:21	-	PMT	1911 Mar 11  0:01  # Paris MT
    +			0:09:21	-	PMT	1911 Mar 11  0:01 # Paris MT
     # Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
     			0:00	France	WE%sT	1940 Jun 14 23:00
     # Le Corre says Paris stuck with occupied-France time after the liberation;
    @@ -1235,15 +1247,13 @@ Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
     # Bundesanstalt contains DST information back to 1916.
     # [See tz-link.htm for the URL.]
     
    -# From Joerg Schilling (2002-10-23):
    +# From Jörg Schilling (2002-10-23):
     # In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
    -# 
    -# General [Nikolai] Bersarin.
    +# http://www.dhm.de/lemo/html/biografien/BersarinNikolai/
    +# General [Nikolai] Bersarin.
     
     # From Paul Eggert (2003-03-08):
    -# 
     # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
    -# 
     # says that Bersarin issued an order to use Moscow time on May 20.
     # However, Moscow did not observe daylight saving in 1945, so
     # this was equivalent to CEMT (GMT+3), not GMT+4.
    @@ -1268,23 +1278,23 @@ Rule SovietZone	1945	only	-	Nov	18	2:00s	0	-
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
    -			1:00	C-Eur	CE%sT	1945 May 24 2:00
    +			1:00	C-Eur	CE%sT	1945 May 24  2:00
     			1:00 SovietZone	CE%sT	1946
     			1:00	Germany	CE%sT	1980
     			1:00	EU	CE%sT
     
     # From Tobias Conradi (2011-09-12):
    -# Busingen , surrounded by the Swiss canton
    +# Büsingen , surrounded by the Swiss canton
     # Schaffhausen, did not start observing DST in 1980 as the rest of DE
     # (West Germany at that time) and DD (East Germany at that time) did.
     # DD merged into DE, the area is currently covered by code DE in ISO 3166-1,
     # which in turn is covered by the zone Europe/Berlin.
     #
    -# Source for the time in Busingen 1980:
    +# Source for the time in Büsingen 1980:
     # http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3
     
     # From Arthur David Olson (2012-03-03):
    -# Busingen and Zurich have shared clocks since 1970.
    +# Büsingen and Zurich have shared clocks since 1970.
     
     Link	Europe/Zurich	Europe/Busingen
     
    @@ -1295,8 +1305,8 @@ Link	Europe/Zurich	Europe/Busingen
     
     # Gibraltar
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2 0:00s
    -			0:00	GB-Eire	%s	1957 Apr 14 2:00
    +Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2  0:00s
    +			0:00	GB-Eire	%s	1957 Apr 14  2:00
     			1:00	-	CET	1982
     			1:00	EU	CE%sT
     
    @@ -1327,7 +1337,7 @@ Rule	Greece	1980	only	-	Apr	 1	0:00	1:00	S
     Rule	Greece	1980	only	-	Sep	28	0:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
    -			1:34:52	-	AMT	1916 Jul 28 0:01     # Athens MT
    +			1:34:52	-	AMT	1916 Jul 28  0:01 # Athens MT
     			2:00	Greece	EE%sT	1941 Apr 30
     			1:00	Greece	CE%sT	1944 Apr  4
     			2:00	Greece	EE%sT	1981
    @@ -1336,15 +1346,20 @@ Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
     			2:00	EU	EE%sT
     
     # Hungary
    +# From Paul Eggert (2014-07-15):
    +# Dates for 1916-1945 are taken from:
    +# Oross A. Jelen a múlt jövője: a nyári időszámítás Magyarországon 1916-1945.
    +# National Archives of Hungary (2012-10-29).
    +# http://mnl.gov.hu/a_het_dokumentuma/a_nyari_idoszamitas_magyarorszagon_19161945.html
    +# This source does not always give times, which are taken from Shanks
    +# & Pottenger (which disagree about the dates).
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Hungary	1918	only	-	Apr	 1	 3:00	1:00	S
    -Rule	Hungary	1918	only	-	Sep	29	 3:00	0	-
    +Rule	Hungary	1918	only	-	Sep	16	 3:00	0	-
     Rule	Hungary	1919	only	-	Apr	15	 3:00	1:00	S
    -Rule	Hungary	1919	only	-	Sep	15	 3:00	0	-
    -Rule	Hungary	1920	only	-	Apr	 5	 3:00	1:00	S
    -Rule	Hungary	1920	only	-	Sep	30	 3:00	0	-
    +Rule	Hungary	1919	only	-	Nov	24	 3:00	0	-
     Rule	Hungary	1945	only	-	May	 1	23:00	1:00	S
    -Rule	Hungary	1945	only	-	Nov	 3	 0:00	0	-
    +Rule	Hungary	1945	only	-	Nov	 1	 0:00	0	-
     Rule	Hungary	1946	only	-	Mar	31	 2:00s	1:00	S
     Rule	Hungary	1946	1949	-	Oct	Sun>=1	 2:00s	0	-
     Rule	Hungary	1947	1949	-	Apr	Sun>=4	 2:00s	1:00	S
    @@ -1360,7 +1375,7 @@ Rule	Hungary	1980	only	-	Apr	 6	 1:00	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
     			1:00	C-Eur	CE%sT	1918
    -			1:00	Hungary	CE%sT	1941 Apr  6  2:00
    +			1:00	Hungary	CE%sT	1941 Apr  8
     			1:00	C-Eur	CE%sT	1945
     			1:00	Hungary	CE%sT	1980 Sep 28  2:00s
     			1:00	EU	CE%sT
    @@ -1423,7 +1438,7 @@ Rule	Iceland	1967	only	-	Oct	29	 1:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
     			-1:27:48 -	RMT	1908 # Reykjavik Mean Time?
    -			-1:00	Iceland	IS%sT	1968 Apr 7 1:00s
    +			-1:00	Iceland	IS%sT	1968 Apr  7  1:00s
     			 0:00	-	GMT
     
     # Italy
    @@ -1438,9 +1453,8 @@ Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
     # From Paul Eggert (2006-03-22):
     # For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
     # F. Pollastri
    -# 
     # Day-light Saving Time in Italy (2006-02-03)
    -# 
    +# http://toi.iriti.cnr.it/uk/ienitlt.html
     # ('FP' below), taken from an Italian National Electrotechnical Institute
     # publication. When the three sources disagree, guess who's right, as follows:
     #
    @@ -1500,8 +1514,8 @@ Rule	Italy	1978	only	-	Oct	 1	0:00s	0	-
     Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
    -			0:49:56	-	RMT	1893 Nov  1 0:00s # Rome Mean
    -			1:00	Italy	CE%sT	1942 Nov  2 2:00s
    +			0:49:56	-	RMT	1893 Nov  1  0:00s # Rome Mean
    +			1:00	Italy	CE%sT	1942 Nov  2  2:00s
     			1:00	C-Eur	CE%sT	1944 Jul
     			1:00	Italy	CE%sT	1980
     			1:00	EU	CE%sT
    @@ -1548,18 +1562,18 @@ Link	Europe/Rome	Europe/San_Marino
     
     # From Andrei Ivanov (2000-03-06):
     # This year Latvia will not switch to Daylight Savings Time (as specified in
    -# 
     # The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
    -# 29-Feb-2000 (#79), in Latvian for subscribers only).
    +# 29-Feb-2000 (#79) ,
    +# in Latvian for subscribers only).
     
    -# 
    -# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
    -# 
    +# From RFE/RL Newsline
    +# http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html
    +# (2001-01-03), noted after a heads-up by Rives McDow:
     # The Latvian government on 2 January decided that the country will
     # institute daylight-saving time this spring, LETA reported.
     # Last February the three Baltic states decided not to turn back their
     # clocks one hour in the spring....
    -# Minister of Economy Aigars Kalvitis noted that Latvia had too few
    +# Minister of Economy Aigars Kalvītis noted that Latvia had too few
     # daylight hours and thus decided to comply with a draft European
     # Commission directive that provides for instituting daylight-saving
     # time in EU countries between 2002 and 2006. The Latvian government
    @@ -1569,18 +1583,23 @@ Link	Europe/Rome	Europe/San_Marino
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Latvia	1989	1996	-	Mar	lastSun	 2:00s	1:00	S
     Rule	Latvia	1989	1996	-	Sep	lastSun	 2:00s	0	-
    +
    +# Milne 1899 says Riga was 1:36:28 (Polytechnique House time).
    +# Byalokoz 1919 says Latvia was 1:36:34.
    +# Go with Byalokoz.
    +
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Europe/Riga	1:36:24	-	LMT	1880
    -			1:36:24	-	RMT	1918 Apr 15 2:00 #Riga Mean Time
    -			1:36:24	1:00	LST	1918 Sep 16 3:00 #Latvian Summer
    -			1:36:24	-	RMT	1919 Apr  1 2:00
    -			1:36:24	1:00	LST	1919 May 22 3:00
    -			1:36:24	-	RMT	1926 May 11
    +Zone	Europe/Riga	1:36:34	-	LMT	1880
    +			1:36:34	-	RMT	1918 Apr 15  2:00 # Riga MT
    +			1:36:34	1:00	LST	1918 Sep 16  3:00 # Latvian ST
    +			1:36:34	-	RMT	1919 Apr  1  2:00
    +			1:36:34	1:00	LST	1919 May 22  3:00
    +			1:36:34	-	RMT	1926 May 11
     			2:00	-	EET	1940 Aug  5
     			3:00	-	MSK	1941 Jul
     			1:00	C-Eur	CE%sT	1944 Oct 13
    -			3:00	Russia	MSK/MSD	1989 Mar lastSun 2:00s
    -			2:00	1:00	EEST	1989 Sep lastSun 2:00s
    +			3:00	Russia	MSK/MSD	1989 Mar lastSun  2:00s
    +			2:00	1:00	EEST	1989 Sep lastSun  2:00s
     			2:00	Latvia	EE%sT	1997 Jan 21
     			2:00	EU	EE%sT	2000 Feb 29
     			2:00	-	EET	2001 Jan  2
    @@ -1614,7 +1633,7 @@ Link Europe/Zurich Europe/Vaduz
     # I would like to inform that in this year Lithuanian time zone
     # (Europe/Vilnius) was changed.
     
    -# From ELTA No. 972 (2582) (1999-09-29),
    +# From ELTA No. 972 (2582) (1999-09-29) ,
     # via Steffen Thorsen:
     # Lithuania has shifted back to the second time zone (GMT plus two hours)
     # to be valid here starting from October 31,
    @@ -1623,9 +1642,9 @@ Link Europe/Zurich Europe/Vaduz
     # motion to give up shifting to summer time in spring, as it was
     # already done by Estonia.
     
    -# From the 
    -# Fact File, Lithuanian State Department of Tourism
    -#  (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
    +# From the Fact File, Lithuanian State Department of Tourism
    +#  (2000-03-27):
    +# Local time is GMT+2 hours ..., no daylight saving.
     
     # From a user via Klaus Marten (2003-02-07):
     # As a candidate for membership of the European Union, Lithuania will
    @@ -1638,18 +1657,18 @@ Link Europe/Zurich Europe/Vaduz
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Vilnius	1:41:16	-	LMT	1880
    -			1:24:00	-	WMT	1917	    # Warsaw Mean Time
    +			1:24:00	-	WMT	1917        # Warsaw Mean Time
     			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
     			1:00	-	CET	1920 Jul 12
     			2:00	-	EET	1920 Oct  9
     			1:00	-	CET	1940 Aug  3
     			3:00	-	MSK	1941 Jun 24
     			1:00	C-Eur	CE%sT	1944 Aug
    -			3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
    -			2:00	1:00	EEST	1991 Sep 29 2:00s
    +			3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
    +			2:00	1:00	EEST	1991 Sep 29  2:00s
     			2:00	C-Eur	EE%sT	1998
    -			2:00	-	EET	1998 Mar 29 1:00u
    -			1:00	EU	CE%sT	1999 Oct 31 1:00u
    +			2:00	-	EET	1998 Mar 29  1:00u
    +			1:00	EU	CE%sT	1999 Oct 31  1:00u
     			2:00	-	EET	2003 Jan  1
     			2:00	EU	EE%sT
     
    @@ -1683,9 +1702,9 @@ Rule	Lux	1929	only	-	Apr	20	23:00	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
     			1:00	Lux	CE%sT	1918 Nov 25
    -			0:00	Lux	WE%sT	1929 Oct  6 2:00s
    -			0:00	Belgium	WE%sT	1940 May 14 3:00
    -			1:00	C-Eur	WE%sT	1944 Sep 18 3:00
    +			0:00	Lux	WE%sT	1929 Oct  6  2:00s
    +			0:00	Belgium	WE%sT	1940 May 14  3:00
    +			1:00	C-Eur	WE%sT	1944 Sep 18  3:00
     			1:00	Belgium	CE%sT	1977
     			1:00	EU	CE%sT
     
    @@ -1702,9 +1721,9 @@ Rule	Malta	1975	1979	-	Apr	Sun>=15	2:00	1:00	S
     Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
     Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
    -			1:00	Italy	CE%sT	1942 Nov  2 2:00s
    -			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
    +Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
    +			1:00	Italy	CE%sT	1942 Nov  2  2:00s
    +			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
     			1:00	Italy	CE%sT	1973 Mar 31
     			1:00	Malta	CE%sT	1981
     			1:00	EU	CE%sT
    @@ -1719,7 +1738,7 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
     # In early 1992 there was large-scale interethnic violence in the area
     # and it's possible that some Russophones continued to observe Moscow time.
     # But [two people] separately reported via
    -# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
    +# Jesper Nørgaard that as of 2001-01-24 Tiraspol was like Chisinau.
     # The Tiraspol entry has therefore been removed for now.
     #
     # From Alexander Krivenyshev (2011-10-17):
    @@ -1728,13 +1747,8 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
     # to the Winter Time).
     #
     # News (in Russian):
    -# 
     # http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html
    -# 
    -#
    -# 
     # http://www.allmoldova.com/moldova-news/1249064116.html
    -# 
     #
     # The substance of this change (reinstatement of the Tiraspol entry)
     # is from a patch from Petr Machata (2011-10-17)
    @@ -1752,9 +1766,7 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
     # Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
     # Tiraspol will go back to winter time on October 30, 2011.
     # News from Moldova (in russian):
    -# 
     # http://ru.publika.md/link_317061.html
    -# 
     
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    @@ -1777,8 +1789,8 @@ Zone	Europe/Chisinau	1:55:20 -	LMT	1880
     # more precise 0:09:21.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
    -			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
    -			0:00	France	WE%sT	1945 Sep 16 3:00
    +			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
    +			0:00	France	WE%sT	1945 Sep 16  3:00
     			1:00	France	CE%sT	1977
     			1:00	EU	CE%sT
     
    @@ -1822,8 +1834,8 @@ Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
     # was not until 1866 when they were all required by law to observe
     # Amsterdam mean time.
     
    -# The data before 1945 are taken from
    -# .
    +# The data entries before 1945 are taken from
    +# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
    @@ -1854,8 +1866,8 @@ Rule	Neth	1945	only	-	Sep	16	2:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Europe/Amsterdam	0:19:32 -	LMT	1835
     			0:19:32	Neth	%s	1937 Jul  1
    -			0:20	Neth	NE%sT	1940 May 16 0:00 # Dutch Time
    -			1:00	C-Eur	CE%sT	1945 Apr  2 2:00
    +			0:20	Neth	NE%sT	1940 May 16  0:00 # Dutch Time
    +			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
     			1:00	Neth	CE%sT	1977
     			1:00	EU	CE%sT
     
    @@ -1885,14 +1897,14 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
     # time they were declared as parts of Norway.  Svalbard was declared
     # as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
     # Mayen by law of 1930-02-27 no 2, section 2. (From
    -# http://www.lovdata.no/all/nl-19250717-011.html and
    -# http://www.lovdata.no/all/nl-19300227-002.html).  The law/regulation
    +#  and
    +# ).  The law/regulation
     # for normal/standard time in Norway is from 1894-06-29 no 1 (came
     # into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
     # part of this law since 1925/1930. (From
    -# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
    +# ) I have not been
     # able to find if Jan Mayen used a different time zone (e.g. -0100)
    -# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
    +# before 1930. Jan Mayen has only been "inhabited" since 1921 by
     # Norwegian meteorologists and maybe used the same time as Norway ever
     # since 1921.  Svalbard (Arctic/Longyearbyen) has been inhabited since
     # before 1895, and therefore probably changed the local time somewhere
    @@ -1907,7 +1919,7 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
     #  says that the meteorologists
     # burned down their station in 1940 and left the island, but returned in
     # 1941 with a small Norwegian garrison and continued operations despite
    -# frequent air ttacks from Germans.  In 1943 the Americans established a
    +# frequent air attacks from Germans.  In 1943 the Americans established a
     # radiolocating station on the island, called "Atlantic City".  Possibly
     # the UT offset changed during the war, but I think it unlikely that
     # Jan Mayen used German daylight-saving rules.
    @@ -1918,7 +1930,7 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
     #  says that the Germans were
     # expelled on 1942-05-14.  However, small parties of Germans did return,
     # and according to Wilhelm Dege's book "War North of 80" (1954)
    -# 
    +# http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html
     # the German armed forces at the Svalbard weather station code-named
     # Haudegen did not surrender to the Allies until September 1945.
     #
    @@ -1927,6 +1939,10 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
     Link	Europe/Oslo	Arctic/Longyearbyen
     
     # Poland
    +
    +# The 1919 dates and times can be found in Tygodnik Urzędowy nr 1 (1919-03-20),
    +#  pp 1-2.
    +
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Poland	1918	1919	-	Sep	16	2:00s	0	-
     Rule	Poland	1919	only	-	Apr	15	2:00s	1:00	S
    @@ -1937,9 +1953,9 @@ Rule	Poland	1944	only	-	Oct	 4	2:00	0	-
     Rule	Poland	1945	only	-	Apr	29	0:00	1:00	S
     Rule	Poland	1945	only	-	Nov	 1	0:00	0	-
     # For 1946 on the source is Kazimierz Borkowski,
    -# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
    -# 
    -# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
    +# Toruń Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
    +# http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1
    +# Thanks to Przemysław Augustyniak (2005-05-28) for this reference.
     # He also gives these further references:
     # Mon Pol nr 13, poz 162 (1995) 
     # Druk nr 2180 (2003) 
    @@ -1959,10 +1975,10 @@ Rule	Poland	1961	1964	-	May	lastSun	1:00s	1:00	S
     Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Warsaw	1:24:00 -	LMT	1880
    -			1:24:00	-	WMT	1915 Aug  5   # Warsaw Mean Time
    -			1:00	C-Eur	CE%sT	1918 Sep 16 3:00
    +			1:24:00	-	WMT	1915 Aug  5 # Warsaw Mean Time
    +			1:00	C-Eur	CE%sT	1918 Sep 16  3:00
     			2:00	Poland	EE%sT	1922 Jun
    -			1:00	Poland	CE%sT	1940 Jun 23 2:00
    +			1:00	Poland	CE%sT	1940 Jun 23  2:00
     			1:00	C-Eur	CE%sT	1944 Oct
     			1:00	Poland	CE%sT	1977
     			1:00	W-Eur	CE%sT	1988
    @@ -1970,6 +1986,14 @@ Zone	Europe/Warsaw	1:24:00 -	LMT	1880
     
     # Portugal
     #
    +# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
    +# According to a Portuguese decree (1911-05-26)
    +# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
    +# Lisbon was at -0:36:44.68, but switched to GMT on 1912-01-01 at 00:00.
    +# Round the old offset to -0:36:45.  This agrees with Willett but disagrees
    +# with Shanks, who says the transition occurred on 1911-05-24 at 00:00 for
    +# Europe/Lisbon, Atlantic/Azores, and Atlantic/Madeira.
    +#
     # From Rui Pedro Salgueiro (1992-11-12):
     # Portugal has recently (September, 27) changed timezone
     # (from WET to MET or CET) to harmonize with EEC.
    @@ -2049,35 +2073,34 @@ Rule	Port	1979	1982	-	Sep	lastSun	 1:00s	0	-
     Rule	Port	1980	only	-	Mar	lastSun	 0:00s	1:00	S
     Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
     Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
    +#
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
    -# Willett says 1912-01-01.  Go with Willett.
    -Zone	Europe/Lisbon	-0:36:32 -	LMT	1884
    -			-0:36:32 -	LMT	1912 Jan  1  # Lisbon Mean Time
    -			 0:00	Port	WE%sT	1966 Apr  3 2:00
    -			 1:00	-	CET	1976 Sep 26 1:00
    -			 0:00	Port	WE%sT	1983 Sep 25 1:00s
    -			 0:00	W-Eur	WE%sT	1992 Sep 27 1:00s
    -			 1:00	EU	CE%sT	1996 Mar 31 1:00u
    +Zone	Europe/Lisbon	-0:36:45 -	LMT	1884
    +			-0:36:45 -	LMT	1912 Jan  1 # Lisbon Mean Time
    +			 0:00	Port	WE%sT	1966 Apr  3  2:00
    +			 1:00	-	CET	1976 Sep 26  1:00
    +			 0:00	Port	WE%sT	1983 Sep 25  1:00s
    +			 0:00	W-Eur	WE%sT	1992 Sep 27  1:00s
    +			 1:00	EU	CE%sT	1996 Mar 31  1:00u
     			 0:00	EU	WE%sT
    -Zone Atlantic/Azores	-1:42:40 -	LMT	1884		# Ponta Delgada
    -			-1:54:32 -	HMT	1911 May 24  # Horta Mean Time
    -			-2:00	Port	AZO%sT	1966 Apr  3 2:00 # Azores Time
    -			-1:00	Port	AZO%sT	1983 Sep 25 1:00s
    -			-1:00	W-Eur	AZO%sT	1992 Sep 27 1:00s
    -			 0:00	EU	WE%sT	1993 Mar 28 1:00u
    +Zone Atlantic/Azores	-1:42:40 -	LMT	1884        # Ponta Delgada
    +			-1:54:32 -	HMT	1912 Jan  1 # Horta Mean Time
    +			-2:00	Port	AZO%sT	1966 Apr  3  2:00  # Azores Time
    +			-1:00	Port	AZO%sT	1983 Sep 25  1:00s
    +			-1:00	W-Eur	AZO%sT	1992 Sep 27  1:00s
    +			 0:00	EU	WE%sT	1993 Mar 28  1:00u
     			-1:00	EU	AZO%sT
    -Zone Atlantic/Madeira	-1:07:36 -	LMT	1884		# Funchal
    -			-1:07:36 -	FMT	1911 May 24  # Funchal Mean Time
    -			-1:00	Port	MAD%sT	1966 Apr  3 2:00 # Madeira Time
    -			 0:00	Port	WE%sT	1983 Sep 25 1:00s
    +Zone Atlantic/Madeira	-1:07:36 -	LMT	1884        # Funchal
    +			-1:07:36 -	FMT	1912 Jan  1 # Funchal Mean Time
    +			-1:00	Port	MAD%sT	1966 Apr  3  2:00 # Madeira Time
    +			 0:00	Port	WE%sT	1983 Sep 25  1:00s
     			 0:00	EU	WE%sT
     
     # Romania
     #
     # From Paul Eggert (1999-10-07):
    -# 
    -# Nine O'clock (1998-10-23) reports that the switch occurred at
    +# Nine O'clock 
    +# (1998-10-23) reports that the switch occurred at
     # 04:00 local time in fall 1998.  For lack of better info,
     # assume that Romania and Moldova switched to EU rules in 1997,
     # the same year as Bulgaria.
    @@ -2094,32 +2117,28 @@ Rule	Romania	1991	1993	-	Mar	lastSun	 0:00s	1:00	S
     Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
    -			1:44:24	-	BMT	1931 Jul 24	# Bucharest MT
    -			2:00	Romania	EE%sT	1981 Mar 29 2:00s
    +			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
    +			2:00	Romania	EE%sT	1981 Mar 29  2:00s
     			2:00	C-Eur	EE%sT	1991
     			2:00	Romania	EE%sT	1994
     			2:00	E-Eur	EE%sT	1997
     			2:00	EU	EE%sT
     
    +
     # Russia
     
     # From Alexander Krivenyshev (2011-09-15):
     # Based on last Russian Government Decree # 725 on August 31, 2011
     # (Government document
    -# 
     # http://www.government.ru/gov/results/16355/print/
    -# 
     # in Russian)
     # there are few corrections have to be made for some Russian time zones...
     # All updated Russian Time Zones were placed in table and translated to English
     # by WorldTimeZone.com at the link below:
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
    -# 
     
     # From Sanjeev Gupta (2011-09-27):
     # Scans of [Decree #23 of January 8, 1992] are available at:
    -# 
     # http://government.consultant.ru/page.aspx?1223966
     # They are in Cyrillic letters (presumably Russian).
     
    @@ -2128,16 +2147,12 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
     # changed in September 2011:
     #
     # One source is
    -# < a href="http://government.ru/gov/results/16355/>
     # http://government.ru/gov/results/16355/
    -# 
     # which, according to translate.google.com, begins "Decree of August 31,
     # 2011 No 725" and contains no other dates or "effective date" information.
     #
     # Another source is
    -# 
     # http://www.rg.ru/2011/09/06/chas-zona-dok.html
    -# 
     # which, according to translate.google.com, begins "Resolution of the
     # Government of the Russian Federation on August 31, 2011 N 725" and also
     # contains "Date first official publication: September 6, 2011 Posted on:
    @@ -2145,28 +2160,45 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
     # does not contain any "effective date" information.
     #
     # Another source is
    -# 
     # http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
    -# 
     # which, in note 8, contains "Resolution #725 of August 31, 2011...
     # Effective as of after 7 days following the day of the official publication"
     # but which does not contain any reference to September 6, 2011.
     #
     # The Wikipedia article refers to
    -# 
     # http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896
    -# 
     # which seems to copy the text of the government.ru page.
     #
     # Tobias Conradi combines Wikipedia's
     # "as of after 7 days following the day of the official publication"
    -# with www.rg.ru's "Date of first official publication: September 6, 2011" to get
    -# September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias Conradi notes).
    +# with www.rg.ru's "Date of first official publication: September 6, 2011" to
    +# get September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias
    +# Conradi notes).
     #
     # None of the sources indicates a time of day for changing clocks.
     #
     # Go with 2011-09-13 0:00s.
     
    +# From Alexander Krivenyshev (2014-07-01):
    +# According to the Russian news (ITAR-TASS News Agency)
    +# http://en.itar-tass.com/russia/738562
    +# the State Duma has approved ... the draft bill on returning to
    +# winter time standard and return Russia 11 time zones.  The new
    +# regulations will come into effect on October 26, 2014 at 02:00 ...
    +# http://asozd2.duma.gov.ru/main.nsf/%28Spravka%29?OpenAgent&RN=431985-6&02
    +# Here is a link where we put together table (based on approved Bill N
    +# 431985-6) with proposed 11 Russian time zones and corresponding
    +# areas/cities/administrative centers in the Russian Federation (in English):
    +# http://www.worldtimezone.com/dst_news/dst_news_russia65.html
    +#
    +# From Alexander Krivenyshev (2014-07-22):
    +# Putin signed the Federal Law 431985-6 ... (in Russian)
    +# http://itar-tass.com/obschestvo/1333711
    +# http://www.pravo.gov.ru:8080/page.aspx?111660
    +# http://www.kremlin.ru/acts/46279
    +# From October 26, 2014 the new Russian time zone map will looks like this:
    +# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
    +
     # From Paul Eggert (2006-03-22):
     # Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
     # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
    @@ -2193,9 +2225,9 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
     #
     # For Grozny, Chechnya, we have the following story from
     # John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
    -# News--often false--is spread by word of mouth.  A rumor that it was
    +# News - often false - is spread by word of mouth.  A rumor that it was
     # time to move the clocks back put this whole city out of sync with
    -# the rest of Russia for two weeks--even soldiers stationed here began
    +# the rest of Russia for two weeks - even soldiers stationed here began
     # enforcing curfew at the wrong time.
     #
     # From Gwillim Law (2001-06-05):
    @@ -2206,107 +2238,265 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
     # since September 1997....  Although the Kuril Islands are
     # administratively part of Sakhalin oblast', they appear to have
     # remained on UTC+11 along with Magadan.
    -#
    +
    +# From Tim Parenti (2014-07-06):
    +# The comments detailing the coverage of each Russian zone are meant to assist
    +# with maintenance only and represent our best guesses as to which regions
    +# are covered by each zone.  They are not meant to be taken as an authoritative
    +# listing.  The region codes listed come from
    +# http://en.wikipedia.org/w/?title=Federal_subjects_of_Russia&oldid=611810498
    +# and are used for convenience only; no guarantees are made regarding their
    +# future stability.  ISO 3166-2:RU codes are also listed for first-level
    +# divisions where available.
    +
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -#
    -# Kaliningradskaya oblast'.
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Europe/Kaliningrad covers...
    +# 39	RU-KGD	Kaliningrad Oblast
    +
     Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
     			 1:00	C-Eur	CE%sT	1945
     			 2:00	Poland	CE%sT	1946
    -			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
    -			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
    -			 3:00	-	FET # Further-eastern European Time
    -#
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Respublika Adygeya, Arkhangel'skaya oblast',
    -# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
    -# Vologodskaya oblast', Voronezhskaya oblast',
    -# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
    -# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
    -# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
    -# Respublika Kareliya, Respublika Komi,
    -# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
    -# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
    -# Respublika Mordoviya, Moskva, Moskovskaya oblast',
    -# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
    -# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
    -# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
    -# Ryazanskaya oblast', Sankt-Peterburg,
    -# Respublika Severnaya Osetiya, Smolenskaya oblast',
    -# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
    -# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
    -# Chechenskaya Respublika, Chuvashskaya oblast',
    -# Yaroslavskaya oblast'
    -Zone Europe/Moscow	 2:30:20 -	LMT	1880
    -			 2:30	-	MMT	1916 Jul  3 # Moscow Mean Time
    -			 2:30:48 Russia	%s	1919 Jul  1 2:00
    +			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
    +			 2:00	Russia	EE%sT	2011 Mar 27  2:00s
    +			 3:00	-	FET	2014 Oct 26  2:00s
    +			 2:00	-	EET
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Europe/Moscow covers...
    +# 01	RU-AD	Adygea, Republic of
    +# 05	RU-DA	Dagestan, Republic of
    +# 06	RU-IN	Ingushetia, Republic of
    +# 07	RU-KB	Kabardino-Balkar Republic
    +# 08	RU-KL	Kalmykia, Republic of
    +# 09	RU-KC	Karachay-Cherkess Republic
    +# 10	RU-KR	Karelia, Republic of
    +# 11	RU-KO	Komi Republic
    +# 12	RU-ME	Mari El Republic
    +# 13	RU-MO	Mordovia, Republic of
    +# 15	RU-SE	North Ossetia-Alania, Republic of
    +# 16	RU-TA	Tatarstan, Republic of
    +# 20	RU-CE	Chechen Republic
    +# 21	RU-CU	Chuvash Republic
    +# 23	RU-KDA	Krasnodar Krai
    +# 26	RU-STA	Stavropol Krai
    +# 29	RU-ARK	Arkhangelsk Oblast
    +# 31	RU-BEL	Belgorod Oblast
    +# 32	RU-BRY	Bryansk Oblast
    +# 33	RU-VLA	Vladimir Oblast
    +# 35	RU-VLG	Vologda Oblast
    +# 36	RU-VOR	Voronezh Oblast
    +# 37	RU-IVA	Ivanovo Oblast
    +# 40	RU-KLU	Kaluga Oblast
    +# 44	RU-KOS	Kostroma Oblast
    +# 46	RU-KRS	Kursk Oblast
    +# 47	RU-LEN	Leningrad Oblast
    +# 48	RU-LIP	Lipetsk Oblast
    +# 50	RU-MOS	Moscow Oblast
    +# 51	RU-MUR	Murmansk Oblast
    +# 52	RU-NIZ	Nizhny Novgorod Oblast
    +# 53	RU-NGR	Novgorod Oblast
    +# 57	RU-ORL	Oryol Oblast
    +# 58	RU-PNZ	Penza Oblast
    +# 60	RU-PSK	Pskov Oblast
    +# 61	RU-ROS	Rostov Oblast
    +# 62	RU-RYA	Ryazan Oblast
    +# 67	RU-SMO	Smolensk Oblast
    +# 68	RU-TAM	Tambov Oblast
    +# 69	RU-TVE	Tver Oblast
    +# 71	RU-TUL	Tula Oblast
    +# 73	RU-ULY	Ulyanovsk Oblast
    +# 76	RU-YAR	Yaroslavl Oblast
    +# 77	RU-MOW	Moscow
    +# 78	RU-SPE	Saint Petersburg
    +# 83	RU-NEN	Nenets Autonomous Okrug
    +
    +# From Vladimir Karpinsky (2014-07-08):
    +# LMT in Moscow (before Jul 3, 1916) is 2:30:17, that was defined by Moscow
    +# Observatory (coordinates: 55 deg. 45'29.70", 37 deg. 34'05.30")....
    +# LMT in Moscow since Jul 3, 1916 is 2:31:01 as a result of new standard.
    +# (The info is from the book by Byalokoz ... p. 18.)
    +# The time in St. Petersburg as capital of Russia was defined by
    +# Pulkov observatory, near St. Petersburg.  In 1916 LMT Moscow
    +# was synchronized with LMT St. Petersburg (+30 minutes), (Pulkov observatory
    +# coordinates: 59 deg. 46'18.70", 30 deg. 19'40.70") so 30 deg. 19'40.70" >
    +# 2h01m18.7s = 2:01:19.  LMT Moscow = LMT St.Petersburg + 30m 2:01:19 + 0:30 =
    +# 2:31:19 ...
    +#
    +# From Paul Eggert (2014-07-08):
    +# Milne does not list Moscow, but suggests that its time might be listed in
    +# Résumés mensuels et annuels des observations météorologiques (1895).
    +# Presumably this is OCLC 85825704, a journal published with parallel text in
    +# Russian and French.  This source has not been located; go with Karpinsky.
    +
    +Zone Europe/Moscow	 2:30:17 -	LMT	1880
    +			 2:30:17 -	MMT	1916 Jul  3 # Moscow Mean Time
    +			 2:31:19 Russia	%s	1919 Jul  1  2:00
    +			 3:00	Russia	%s	1921 Oct
     			 3:00	Russia	MSK/MSD	1922 Oct
     			 2:00	-	EET	1930 Jun 21
    -			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
    -			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
    -			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
    -			 4:00	-	MSK
    -#
    -# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
    -# Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
    -# but Wikipedia (2006-05-09) says +0300.  Perhaps it switched after the
    -# others?  But we have no data.
    +			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
    +			 2:00	Russia	EE%sT	1992 Jan 19  2:00s
    +			 3:00	Russia	MSK/MSD	2011 Mar 27  2:00s
    +			 4:00	-	MSK	2014 Oct 26  2:00s
    +			 3:00	-	MSK
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Europe/Simferopol covers...
    +# **	****	Crimea, Republic of
    +# **	****	Sevastopol
    +
    +Zone Europe/Simferopol	 2:16:24 -	LMT	1880
    +			 2:16	-	SMT	1924 May  2 # Simferopol Mean T
    +			 2:00	-	EET	1930 Jun 21
    +			 3:00	-	MSK	1941 Nov
    +			 1:00	C-Eur	CE%sT	1944 Apr 13
    +			 3:00	Russia	MSK/MSD	1990
    +			 3:00	-	MSK	1990 Jul  1  2:00
    +			 2:00	-	EET	1992
    +# Central Crimea used Moscow time 1994/1997.
    +#
    +# From Paul Eggert (2006-03-22):
    +# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
    +# from Kiev to Moscow time sometime after the January 1994 elections.
    +# Shanks (1999) says "date of change uncertain", but implies that it happened
    +# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
    +# 1994-09-25 03:00, but that can't be right.  For now, guess it
    +# changed in May.
    +			 2:00	E-Eur	EE%sT	1994 May
    +# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
    +			 3:00	E-Eur	MSK/MSD	1996 Mar 31  3:00s
    +			 3:00	1:00	MSD	1996 Oct 27  3:00s
    +# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
    +# Assume it happened in March by not changing the clocks.
    +			 3:00	Russia	MSK/MSD	1997
    +			 3:00	-	MSK	1997 Mar lastSun  1:00u
    +# From Alexander Krivenyshev (2014-03-17):
    +# time change at 2:00 (2am) on March 30, 2014
    +# http://vz.ru/news/2014/3/17/677464.html
    +# From Paul Eggert (2014-03-30):
    +# Simferopol and Sevastopol reportedly changed their central town clocks
    +# late the previous day, but this appears to have been ceremonial
    +# and the discrepancies are small enough to not worry about.
    +			 2:00	EU	EE%sT	2014 Mar 30  2:00
    +			 4:00	-	MSK	2014 Oct 26  2:00s
    +			 3:00	-	MSK
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Europe/Volgograd covers...
    +# 30	RU-AST	Astrakhan Oblast
    +# 34	RU-VGG	Volgograd Oblast
    +# 43	RU-KIR	Kirov Oblast
    +# 64	RU-SAR	Saratov Oblast
    +
    +# From Paul Eggert (2006-05-09):
    +# Shanks & Pottenger say Kirov is still at +0400 but Wikipedia says +0300.
    +# Perhaps it switched after the others?  But we have no data.
    +
     Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
     			 3:00	-	TSAT	1925 Apr  6 # Tsaritsyn Time
     			 3:00	-	STAT	1930 Jun 21 # Stalingrad Time
     			 4:00	-	STAT	1961 Nov 11
    -			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
    -			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
    -			 4:00	-	VOLT	1992 Mar 29 2:00s
    -			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
    -			 4:00	-	VOLT
    -#
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Samarskaya oblast', Udmyrtskaya respublika
    -Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
    +			 4:00	Russia	VOL%sT	1989 Mar 26  2:00s # Volgograd T
    +			 3:00	Russia	VOL%sT	1991 Mar 31  2:00s
    +			 4:00	-	VOLT	1992 Mar 29  2:00s
    +			 3:00	Russia	MSK	2011 Mar 27  2:00s
    +			 4:00	-	MSK	2014 Oct 26  2:00s
    +			 3:00	-	MSK
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Europe/Samara covers...
    +# 18	RU-UD	Udmurt Republic
    +# 63	RU-SAM	Samara Oblast
    +
    +# Byalokoz 1919 says Samara was 3:20:20.
    +
    +Zone Europe/Samara	 3:20:20 -	LMT	1919 Jul  1  2:00
     			 3:00	-	SAMT	1930 Jun 21
     			 4:00	-	SAMT	1935 Jan 27
    -			 4:00	Russia	KUY%sT	1989 Mar 26 2:00s # Kuybyshev
    -			 3:00	Russia	KUY%sT	1991 Mar 31 2:00s
    -			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
    -			 3:00	-	KUYT	1991 Oct 20 3:00
    -			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
    -			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
    +			 4:00	Russia	KUY%sT	1989 Mar 26  2:00s # Kuybyshev
    +			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
    +			 2:00	Russia	EE%sT	1991 Sep 29  2:00s
    +			 3:00	-	KUYT	1991 Oct 20  3:00
    +			 4:00	Russia	SAM%sT	2010 Mar 28  2:00s # Samara Time
    +			 3:00	Russia	SAM%sT	2011 Mar 27  2:00s
     			 4:00	-	SAMT
     
    -#
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
    -# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
    -# Sverdlovskaya oblast', Tyumenskaya oblast',
    -# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
    -# Yamalo-Nenetskij avtonomnyj okrug.
    -Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Asia/Yekaterinburg covers...
    +# 02	RU-BA	Bashkortostan, Republic of
    +# 90	RU-PER	Perm Krai
    +# 45	RU-KGN	Kurgan Oblast
    +# 56	RU-ORE	Orenburg Oblast
    +# 66	RU-SVE	Sverdlovsk Oblast
    +# 72	RU-TYU	Tyumen Oblast
    +# 74	RU-CHE	Chelyabinsk Oblast
    +# 86	RU-KHM	Khanty-Mansi Autonomous Okrug - Yugra
    +# 89	RU-YAN	Yamalo-Nenets Autonomous Okrug
    +#
    +# Note: Effective 2005-12-01, (59) Perm Oblast and (81) Komi-Permyak
    +# Autonomous Okrug merged to form (90, RU-PER) Perm Krai.
    +
    +# Milne says Yekaterinburg was 4:02:32.9; round to nearest.
    +# Byalokoz 1919 says its provincial time was based on Perm, at 3:45:05.
    +# Assume it switched on 1916-07-03, the time of the new standard.
    +# The 1919 and 1930 transitions are from Shanks.
    +
    +Zone Asia/Yekaterinburg	 4:02:33 -	LMT	1916 Jul  3
    +			 3:45:05 -	PMT	1919 Jul 15  4:00
     			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
    -			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
    -			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
    -			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
    -			 6:00	-	YEKT	# Yekaterinburg Time
    -#
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
    -Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
    -			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
    -			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
    -			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
    -			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
    -			 7:00	-	OMST
    -#
    +			 5:00	Russia	SVE%sT	1991 Mar 31  2:00s
    +			 4:00	Russia	SVE%sT	1992 Jan 19  2:00s
    +			 5:00	Russia	YEK%sT	2011 Mar 27  2:00s
    +			 6:00	-	YEKT	2014 Oct 26  2:00s
    +			 5:00	-	YEKT
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Asia/Omsk covers...
    +# 04	RU-AL	Altai Republic
    +# 22	RU-ALT	Altai Krai
    +# 55	RU-OMS	Omsk Oblast
    +
    +# Byalokoz 1919 says Omsk was 4:53:30.
    +
    +Zone Asia/Omsk		 4:53:30 -	LMT	1919 Nov 14
    +			 5:00	-	OMST	1930 Jun 21 # Omsk Time
    +			 6:00	Russia	OMS%sT	1991 Mar 31  2:00s
    +			 5:00	Russia	OMS%sT	1992 Jan 19  2:00s
    +			 6:00	Russia	OMS%sT	2011 Mar 27  2:00s
    +			 7:00	-	OMST	2014 Oct 26  2:00s
    +			 6:00	-	OMST
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Asia/Novosibirsk covers...
    +# 54	RU-NVS	Novosibirsk Oblast
    +# 70	RU-TOM	Tomsk Oblast
    +
     # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
     # not clear when it switched from +7 to +6.
    -# Novosibirskaya oblast', Tomskaya oblast'.
    -Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
    +
    +Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
     			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
    -			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
    -			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
    +			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
    +			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
     			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
    -			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
    -			 7:00	-	NOVT
    +			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
    +			 7:00	-	NOVT	2014 Oct 26  2:00s
    +			 6:00	-	NOVT
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Asia/Novokuznetsk covers...
    +# 42	RU-KEM	Kemerovo Oblast
     
     # From Alexander Krivenyshev (2009-10-13):
     # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
    @@ -2319,14 +2509,10 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
     # time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
     #
     # Russian Government web site (Russian language)
    -# 
     # http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
    -# 
     # or Russian-English translation by WorldTimeZone.com with reference
     # map to local region and new Russia Time Zone map after March 28, 2010
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_russia03.html
    -# 
     #
     # Thus, when Russia will switch to DST on the night of March 28, 2010
     # Kemerovo region (Kemerovo oblast') will not change the clock.
    @@ -2334,152 +2520,319 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
     # As a result, Kemerovo oblast' will be in the same time zone as
     # Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
     
    +# From Tim Parenti (2014-07-02), per Alexander Krivenyshev (2014-07-02):
    +# The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
    +# realigning itself with KRAT.
    +
     Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
     			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
    -			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
    -			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
    -			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
    -			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
    -			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
    -
    -#
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Krasnoyarskij kraj,
    -# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
    -# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
    -Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
    +			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
    +			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
    +			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
    +			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
    +			 7:00	-	NOVT	2014 Oct 26  2:00s
    +			 7:00	-	KRAT	# Krasnoyarsk Time
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Asia/Krasnoyarsk covers...
    +# 17	RU-TY	Tuva Republic
    +# 19	RU-KK	Khakassia, Republic of
    +# 24	RU-KYA	Krasnoyarsk Krai
    +#
    +# Note: Effective 2007-01-01, (88) Evenk Autonomous Okrug and (84) Taymyr
    +# Autonomous Okrug were merged into (24, RU-KYA) Krasnoyarsk Krai.
    +
    +# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
    +
    +Zone Asia/Krasnoyarsk	 6:11:26 -	LMT	1920 Jan  6
     			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
    -			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
    -			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
    -			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
    -			 8:00	-	KRAT
    -#
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Respublika Buryatiya, Irkutskaya oblast',
    -# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
    -Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
    -			 6:57:20 -	IMT	1920 Jan 25 # Irkutsk Mean Time
    +			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
    +			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
    +			 7:00	Russia	KRA%sT	2011 Mar 27  2:00s
    +			 8:00	-	KRAT	2014 Oct 26  2:00s
    +			 7:00	-	KRAT
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Asia/Irkutsk covers...
    +# 03	RU-BU	Buryatia, Republic of
    +# 38	RU-IRK	Irkutsk Oblast
    +#
    +# Note: Effective 2008-01-01, (85) Ust-Orda Buryat Autonomous Okrug was
    +# merged into (38, RU-IRK) Irkutsk Oblast.
    +
    +# Milne 1899 says Irkutsk was 6:57:15.
    +# Byalokoz 1919 says Irkutsk was 6:57:05.
    +# Go with Byalokoz.
    +
    +Zone Asia/Irkutsk	 6:57:05 -	LMT	1880
    +			 6:57:05 -	IMT	1920 Jan 25 # Irkutsk Mean Time
     			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
    -			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
    -			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
    -			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
    -			 9:00	-	IRKT
    -#
    -# From Oscar van Vlijmen (2003-10-18): [This region consists of]
    -# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
    -# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
    -
    -# From Oscar van Vlijmen (2009-11-29):
    -# ...some regions of [Russia] were merged with others since 2005...
    -# Some names were changed, no big deal, except for one instance: a new name.
    -# YAK/YAKST: UTC+9 Zabajkal'skij kraj.
    -
    -# From Oscar van Vlijmen (2009-11-29):
    -# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
    -# Verkhnevilyujskij, Vilyujskij, Gornyj,
    -# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
    -# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij,
    -# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
    -# Churapchinskij, Eveno-Bytantajskij Natsional'nij.
    -
    -Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
    +			 8:00	Russia	IRK%sT	1991 Mar 31  2:00s
    +			 7:00	Russia	IRK%sT	1992 Jan 19  2:00s
    +			 8:00	Russia	IRK%sT	2011 Mar 27  2:00s
    +			 9:00	-	IRKT	2014 Oct 26  2:00s
    +			 8:00	-	IRKT
    +
    +
    +# From Tim Parenti (2014-07-06):
    +# Asia/Chita covers...
    +# 92	RU-ZAB	Zabaykalsky Krai
    +#
    +# Note: Effective 2008-03-01, (75) Chita Oblast and (80) Agin-Buryat
    +# Autonomous Okrug merged to form (92, RU-ZAB) Zabaykalsky Krai.
    +
    +Zone Asia/Chita	 7:33:52 -	LMT	1919 Dec 15
    +			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
    +			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
    +			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
    +			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
    +			10:00	-	YAKT	2014 Oct 26  2:00s
    +			 8:00	-	IRKT
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
    +# Asia/Yakutsk covers...
    +# 28	RU-AMU	Amur Oblast
    +#
    +# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
    +# 14-02	****	Aldansky District
    +# 14-04	****	Amginsky District
    +# 14-05	****	Anabarsky District
    +# 14-06	****	Bulunsky District
    +# 14-07	****	Verkhnevilyuysky District
    +# 14-10	****	Vilyuysky District
    +# 14-11	****	Gorny District
    +# 14-12	****	Zhigansky District
    +# 14-13	****	Kobyaysky District
    +# 14-14	****	Lensky District
    +# 14-15	****	Megino-Kangalassky District
    +# 14-16	****	Mirninsky District
    +# 14-18	****	Namsky District
    +# 14-19	****	Neryungrinsky District
    +# 14-21	****	Nyurbinsky District
    +# 14-23	****	Olenyoksky District
    +# 14-24	****	Olyokminsky District
    +# 14-26	****	Suntarsky District
    +# 14-27	****	Tattinsky District
    +# 14-29	****	Ust-Aldansky District
    +# 14-32	****	Khangalassky District
    +# 14-33	****	Churapchinsky District
    +# 14-34	****	Eveno-Bytantaysky National District
    +
    +# From Tim Parenti (2014-07-03):
    +# Our commentary seems to have lost mention of (14-19) Neryungrinsky District.
    +# Since the surrounding districts of Sakha are all YAKT, assume this is, too.
    +# Also assume its history has been the same as the rest of Asia/Yakutsk.
    +
    +# Byalokoz 1919 says Yakutsk was 8:38:58.
    +
    +Zone Asia/Yakutsk	 8:38:58 -	LMT	1919 Dec 15
     			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
    -			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
    -			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
    -			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
    -			 10:00	-	YAKT
    -#
    -# From Oscar van Vlijmen (2003-10-18): [This region consists of]
    -# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
    -# [parts of] Respublika Sakha (Yakutiya).
    -
    -# From Oscar van Vlijmen (2009-11-29):
    -# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
    -Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
    +			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
    +			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
    +			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
    +			10:00	-	YAKT	2014 Oct 26  2:00s
    +			 9:00	-	YAKT
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
    +# Asia/Vladivostok covers...
    +# 25	RU-PRI	Primorsky Krai
    +# 27	RU-KHA	Khabarovsk Krai
    +# 79	RU-YEV	Jewish Autonomous Oblast
    +#
    +# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
    +# 14-09	****	Verkhoyansky District
    +# 14-31	****	Ust-Yansky District
    +
    +# Milne 1899 says Vladivostok was 8:47:33.5.
    +# Byalokoz 1919 says Vladivostok was 8:47:31.
    +# Go with Byalokoz.
    +
    +Zone Asia/Vladivostok	 8:47:31 -	LMT	1922 Nov 15
     			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
    -			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
    -			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
    -			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
    -			11:00	-	VLAT
    +			10:00	Russia	VLA%sT	1991 Mar 31  2:00s
    +			 9:00	Russia	VLA%sT	1992 Jan 19  2:00s
    +			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
    +			11:00	-	VLAT	2014 Oct 26  2:00s
    +			10:00	-	VLAT
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Asia/Khandyga covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
    +# 14-28	****	Tomponsky District
    +# 14-30	****	Ust-Maysky District
     
     # From Arthur David Olson (2012-05-09):
     # Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time
     # in 2011.
    -#
    +
     # From Paul Eggert (2012-11-25):
     # Shanks and Pottenger (2003) has Khandyga on Yakutsk time.
     # Make a wild guess that it switched to Vladivostok time in 2004.
     # This transition is no doubt wrong, but we have no better info.
    -#
    +
     Zone Asia/Khandyga	 9:02:13 -	LMT	1919 Dec 15
     			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
    -			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
    -			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
    +			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
    +			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
     			 9:00	Russia	YAK%sT	2004
    -			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
    -			11:00	-	VLAT	2011 Sep 13 0:00s # Decree 725?
    -			10:00	-	YAKT
    +			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
    +			11:00	-	VLAT	2011 Sep 13  0:00s # Decree 725?
    +			10:00	-	YAKT	2014 Oct 26  2:00s
    +			 9:00	-	YAKT
     
    -#
    -# Sakhalinskaya oblast'.
    -# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
    +
    +# From Tim Parenti (2014-07-03):
    +# Asia/Sakhalin covers...
    +# 65	RU-SAK	Sakhalin Oblast
    +# ...with the exception of:
    +# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
    +
    +# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
     Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
    -			 9:00	-	CJT	1938
    +			 9:00	-	JCST	1937 Oct  1
     			 9:00	-	JST	1945 Aug 25
    -			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
    -			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
    -			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
    -			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
    -			11:00	-	SAKT
    -#
    -# From Oscar van Vlijmen (2003-10-18): [This region consists of]
    -# Magadanskaya oblast', Respublika Sakha (Yakutiya).
    -# Probably also: Kuril Islands.
    -
    -# From Oscar van Vlijmen (2009-11-29):
    -# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
    -# Nizhnekolymskij, ... Srednekolymskij.
    +			11:00	Russia	SAK%sT	1991 Mar 31  2:00s # Sakhalin T
    +			10:00	Russia	SAK%sT	1992 Jan 19  2:00s
    +			11:00	Russia	SAK%sT	1997 Mar lastSun  2:00s
    +			10:00	Russia	SAK%sT	2011 Mar 27  2:00s
    +			11:00	-	SAKT	2014 Oct 26  2:00s
    +			10:00	-	SAKT
    +
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
    +# Asia/Magadan covers...
    +# 49	RU-MAG	Magadan Oblast
    +
    +# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
    +# Magadan Oblast is moving from UTC+12 to UTC+10 on 2014-10-26; however,
    +# several districts of Sakha Republic as well as Severo-Kurilsky District of
    +# the Sakhalin Oblast (also known as the North Kuril Islands), represented
    +# until now by Asia/Magadan, will instead move to UTC+11.  These regions will
    +# need their own zone.
    +
     Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
     			10:00	-	MAGT	1930 Jun 21 # Magadan Time
    -			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
    -			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
    -			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
    -			12:00	-	MAGT
    +			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
    +			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
    +			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
    +			12:00	-	MAGT	2014 Oct 26  2:00s
    +			10:00	-	MAGT
    +
    +
    +# From Tim Parenti (2014-07-06):
    +# Asia/Srednekolymsk covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
    +# 14-01	****	Abyysky District
    +# 14-03	****	Allaikhovsky District
    +# 14-08	****	Verkhnekolymsky District
    +# 14-17	****	Momsky District
    +# 14-20	****	Nizhnekolymsky District
    +# 14-25	****	Srednekolymsky District
    +#
    +# ...and parts of (65, RU-SAK) Sakhalin Oblast:
    +# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
    +
    +# From Tim Parenti (2014-07-02):
    +# Oymyakonsky District of Sakha Republic (represented by Ust-Nera), along with
    +# most of Sakhalin Oblast (represented by Sakhalin) will be moving to UTC+10 on
    +# 2014-10-26 to stay aligned with VLAT/SAKT; however, Severo-Kurilsky District
    +# of the Sakhalin Oblast (also known as the North Kuril Islands, represented by
    +# Severo-Kurilsk) will remain on UTC+11.
    +
    +# From Tim Parenti (2014-07-06):
    +# Assume North Kuril Islands have history like Magadan before 2011-03-27.
    +# There is a decent chance this is wrong, in which case a new zone
    +# Asia/Severo-Kurilsk would become necessary.
    +#
    +# Srednekolymsk and Zyryanka are the most populous places amongst these
    +# districts, but have very similar populations.  In fact, Wikipedia currently
    +# lists them both as having 3528 people, exactly 1668 males and 1860 females
    +# each!  (Yikes!)
    +# http://en.wikipedia.org/w/?title=Srednekolymsky_District&oldid=603435276
    +# http://en.wikipedia.org/w/?title=Verkhnekolymsky_District&oldid=594378493
    +# Assume this is a mistake, albeit an amusing one.
    +#
    +# Looking at censuses, the populations of the two municipalities seem to have
    +# fluctuated recently.  Zyryanka was more populous than Srednekolymsk in the
    +# 1989 and 2002 censuses, but Srednekolymsk was more populous in the most
    +# recent (2010) census, 3525 to 3170.  (See pages 195 and 197 of
    +# http://www.gks.ru/free_doc/new_site/perepis2010/croc/Documents/Vol1/pub-01-05.pdf
    +# in Russian.)  In addition, Srednekolymsk appears to be a much older
    +# settlement and the population of Zyryanka seems to be declining.
    +# Go with Srednekolymsk.
    +#
    +# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
    +# as the abbreviation.  Use SRET instead.
    +
    +Zone Asia/Srednekolymsk	10:14:52 -	LMT	1924 May  2
    +			10:00	-	MAGT	1930 Jun 21 # Magadan Time
    +			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
    +			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
    +			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
    +			12:00	-	MAGT	2014 Oct 26  2:00s
    +			11:00	-	SRET	# Srednekolymsk Time
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Asia/Ust-Nera covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
    +# 14-22	****	Oymyakonsky District
     
     # From Arthur David Olson (2012-05-09):
    -# Ojmyakonskij and the Kuril Islands switched from
    +# Ojmyakonskij [and the Kuril Islands] switched from
     # Magadan time to Vladivostok time in 2011.
    +#
    +# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
    +# It's unlikely that any of the Kuril Islands were involved in such a switch,
    +# as the South and Middle Kurils have been on UTC+11 (SAKT) with the rest of
    +# Sakhalin Oblast since at least 2011-09, and the North Kurils have been on
    +# UTC+12 since at least then, too.
    +
     Zone Asia/Ust-Nera	 9:32:54 -	LMT	1919 Dec 15
     			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
     			 9:00	Russia	YAKT	1981 Apr  1
    -			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
    -			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
    -			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
    -			12:00	-	MAGT	2011 Sep 13 0:00s # Decree 725?
    -			11:00	-	VLAT
    +			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
    +			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
    +			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
    +			12:00	-	MAGT	2011 Sep 13  0:00s # Decree 725?
    +			11:00	-	VLAT	2014 Oct 26  2:00s
    +			10:00	-	VLAT
     
    -# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    -# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
    +
    +# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
    +# Asia/Kamchatka covers...
    +# 91	RU-KAM	Kamchatka Krai
     #
    -# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
    +# Note: Effective 2007-07-01, (41) Kamchatka Oblast and (82) Koryak
    +# Autonomous Okrug merged to form (91, RU-KAM) Kamchatka Krai.
    +
    +# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
    +# Asia/Petropavlovsk-Kamchatsky, but these are too long.
     Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
     			11:00	-	PETT	1930 Jun 21 # P-K Time
    -			12:00	Russia	PET%sT	1991 Mar 31 2:00s
    -			11:00	Russia	PET%sT	1992 Jan 19 2:00s
    -			12:00	Russia	PET%sT	2010 Mar 28 2:00s
    -			11:00	Russia	PET%sT	2011 Mar 27 2:00s
    +			12:00	Russia	PET%sT	1991 Mar 31  2:00s
    +			11:00	Russia	PET%sT	1992 Jan 19  2:00s
    +			12:00	Russia	PET%sT	2010 Mar 28  2:00s
    +			11:00	Russia	PET%sT	2011 Mar 27  2:00s
     			12:00	-	PETT
    -#
    -# Chukotskij avtonomnyj okrug
    +
    +
    +# From Tim Parenti (2014-07-03):
    +# Asia/Anadyr covers...
    +# 87	RU-CHU	Chukotka Autonomous Okrug
    +
     Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
     			12:00	-	ANAT	1930 Jun 21 # Anadyr Time
    -			13:00	Russia	ANA%sT	1982 Apr  1 0:00s
    -			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
    -			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
    -			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
    -			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
    +			13:00	Russia	ANA%sT	1982 Apr  1  0:00s
    +			12:00	Russia	ANA%sT	1991 Mar 31  2:00s
    +			11:00	Russia	ANA%sT	1992 Jan 19  2:00s
    +			12:00	Russia	ANA%sT	2010 Mar 28  2:00s
    +			11:00	Russia	ANA%sT	2011 Mar 27  2:00s
     			12:00	-	ANAT
     
    +
     # San Marino
     # See Europe/Rome.
     
    @@ -2488,11 +2841,11 @@ Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
     Zone	Europe/Belgrade	1:22:00	-	LMT	1884
     			1:00	-	CET	1941 Apr 18 23:00
     			1:00	C-Eur	CE%sT	1945
    -			1:00	-	CET	1945 May 8 2:00s
    +			1:00	-	CET	1945 May  8  2:00s
     			1:00	1:00	CEST	1945 Sep 16  2:00s
    -# Metod Kozelj reports that the legal date of
    +# Metod Koželj reports that the legal date of
     # transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
    -# Shanks & Pottenger don't give as much detail, so go with Kozelj.
    +# Shanks & Pottenger don't give as much detail, so go with Koželj.
     			1:00	-	CET	1982 Nov 27
     			1:00	EU	CE%sT
     Link Europe/Belgrade Europe/Ljubljana	# Slovenia
    @@ -2568,13 +2921,13 @@ Zone	Africa/Ceuta	-0:21:16 -	LMT	1901
     			 0:00	1:00	WEST	1918 Oct  7 23:00
     			 0:00	-	WET	1924
     			 0:00	Spain	WE%sT	1929
    -			 0:00 SpainAfrica WE%sT 1984 Mar 16
    +			 0:00 SpainAfrica WE%sT	1984 Mar 16
     			 1:00	-	CET	1986
     			 1:00	EU	CE%sT
     Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
    -			-1:00	-	CANT	1946 Sep 30 1:00 # Canaries Time
    -			 0:00	-	WET	1980 Apr  6 0:00s
    -			 0:00	1:00	WEST	1980 Sep 28 0:00s
    +			-1:00	-	CANT	1946 Sep 30  1:00 # Canaries T
    +			 0:00	-	WET	1980 Apr  6  0:00s
    +			 0:00	1:00	WEST	1980 Sep 28  0:00s
     			 0:00	EU	WE%sT
     # IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
     # Ignore this for now, as the Canaries are part of the EU.
    @@ -2583,7 +2936,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
     
     # From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
     #
    -# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
    +# The law "Svensk författningssamling 1878, no 14" about standard time in 1879:
     # From the beginning of 1879 (that is 01-01 00:00) the time for all
     # places in the country is "the mean solar time for the meridian at
     # three degrees, or twelve minutes of time, to the west of the
    @@ -2594,7 +2947,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
     # national standard time as 01:00:14 ahead of GMT....
     #
     # About the beginning of CET in Sweden. The lawtext ("Svensk
    -# forfattningssamling 1899, no 44") states, that "from the beginning
    +# författningssamling 1899, no 44") states, that "from the beginning
     # of 1900... ... the same as the mean solar time for the meridian at
     # the distance of one hour of time from the meridian of the English
     # observatory at Greenwich, or at 12 minutes 14 seconds to the west
    @@ -2602,7 +2955,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
     # 1899-06-16.  In short: At 1900-01-01 00:00:00 the new standard time
     # in Sweden is 01:00:00 ahead of GMT.
     #
    -# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
    +# 1916: The lawtext ("Svensk författningssamling 1916, no 124") states
     # that "1916-05-15 is considered to begin one hour earlier". It is
     # pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
     # Further the law says, that "1916-09-30 is considered to end one hour later".
    @@ -2612,7 +2965,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
     # not available on the site (to my knowledge they are only available
     # in Swedish):  (type
     # "sommartid" without the quotes in the field "Fritext" and then click
    -# the Sok-button).
    +# the Sök-button).
     #
     # (2001-05-13):
     #
    @@ -2627,9 +2980,9 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
    -			1:00:14	-	SET	1900 Jan  1	# Swedish Time
    +			1:00:14	-	SET	1900 Jan  1 # Swedish Time
     			1:00	-	CET	1916 May 14 23:00
    -			1:00	1:00	CEST	1916 Oct  1 01:00
    +			1:00	1:00	CEST	1916 Oct  1  1:00
     			1:00	-	CET	1980
     			1:00	EU	CE%sT
     
    @@ -2637,7 +2990,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
     # From Howse:
     # By the end of the 18th century clocks and watches became commonplace
     # and their performance improved enormously.  Communities began to keep
    -# mean time in preference to apparent time -- Geneva from 1780 ....
    +# mean time in preference to apparent time - Geneva from 1780 ....
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     # From Whitman (who writes "Midnight?"):
     # Rule	Swiss	1940	only	-	Nov	 2	0:00	1:00	S
    @@ -2653,7 +3006,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
     # to be wrong. This is now verified.
     #
     # I have found copies of the original ruling by the Swiss Federal
    -# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss
    +# government, in 'Eidgenössische Gesetzessammlung 1941 and 1942' (Swiss
     # federal law collection)...
     #
     # DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am
    @@ -2672,7 +3025,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
     # night as an absolute novelty, because this was the first time that such
     # a thing had happened in Switzerland.
     #
    -# I have also checked 1916, because one book source (Gabriel, Traite de
    +# I have also checked 1916, because one book source (Gabriel, Traité de
     # l'heure dans le monde) claims that Switzerland had DST in 1916. This is
     # false, no official document could be found. Probably Gabriel got misled
     # by references to Germany, which introduced DST in 1916 for the first time.
    @@ -2686,19 +3039,19 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
     # One further detail for Switzerland, which is probably out of scope for
     # most users of tzdata: The [Europe/Zurich zone] ...
     # describes all of Switzerland correctly, with the exception of
    -# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not
    +# the Canton de Genève (Geneva, Genf). Between 1848 and 1894 Geneva did not
     # follow Bern Mean Time but kept its own local mean time.
     # To represent this, an extra zone would be needed.
     #
     # From Alois Treindl (2013-09-11):
     # The Federal regulations say
     # http://www.admin.ch/opc/de/classified-compilation/20071096/index.html
    -# ... the meridian for Bern mean time ... is 7 degrees 26'22.50".
    +# ... the meridian for Bern mean time ... is 7 degrees 26' 22.50".
     # Expressed in time, it is 0h29m45.5s.
     
     # From Pierre-Yves Berger (2013-09-11):
    -# the "Circulaire du conseil federal" (December 11 1893)
    -#  ...
    +# the "Circulaire du conseil fédéral" (December 11 1893)
    +# http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353
     # clearly states that the [1894-06-01] change should be done at midnight
     # but if no one is present after 11 at night, could be postponed until one
     # hour before the beginning of service.
    @@ -2709,14 +3062,14 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
     # We can find no reliable source for Shanks's assertion that all of Switzerland
     # except Geneva switched to Bern Mean Time at 00:00 on 1848-09-12.  This book:
     #
    -#	Jakob Messerli. Gleichmassig, punktlich, schnell: Zeiteinteilung und
    +#	Jakob Messerli. Gleichmässig, pünktlich, schnell. Zeiteinteilung und
     #	Zeitgebrauch in der Schweiz im 19. Jahrhundert. Chronos, Zurich 1995,
     #	ISBN 3-905311-68-2, OCLC 717570797.
     #
     # suggests that the transition was more gradual, and that the Swiss did not
     # agree about civil time during the transition.  The timekeeping it gives the
     # most detail for is postal and telegraph time: here, federal legislation (the
    -# "Bundesgesetz uber die Erstellung von elektrischen Telegraphen") passed on
    +# "Bundesgesetz über die Erstellung von elektrischen Telegraphen") passed on
     # 1851-11-23, and an official implementation notice was published 1853-07-16
     # (Bundesblatt 1853, Bd. II, S. 859).  On p 72 Messerli writes that in
     # practice since July 1853 Bernese time was used in "all postal and telegraph
    @@ -2730,7 +3083,7 @@ Rule	Swiss	1941	1942	-	May	Mon>=1	1:00	1:00	S
     Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
    -			0:29:46	-	BMT	1894 Jun # Bern Mean Time
    +			0:29:46	-	BMT	1894 Jun    # Bern Mean Time
     			1:00	Swiss	CE%sT	1981
     			1:00	EU	CE%sT
     
    @@ -2738,7 +3091,7 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
     
     # From Amar Devegowda (2007-01-03):
     # The time zone rules for Istanbul, Turkey have not been changed for years now.
    -# ... The latest rules are available at -
    +# ... The latest rules are available at:
     # http://www.timeanddate.com/worldclock/timezone.html?n=107
     # From Steffen Thorsen (2007-01-03):
     # I have been able to find press records back to 1996 which all say that
    @@ -2763,8 +3116,7 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
     # (on a non-government server though) describing dates between 2002 and 2006:
     # http://www.alomaliye.com/bkk_2002_3769.htm
     
    -# From Gökdeniz Karadağ (2011-03-10):
    -#
    +# From Gökdeniz Karadağ (2011-03-10):
     # According to the articles linked below, Turkey will change into summer
     # time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
     # This change is due to a nationwide exam on 27th.
    @@ -2777,9 +3129,16 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
     # Turkish Local election....
     # http://www.sabah.com.tr/Ekonomi/2014/02/12/yaz-saatinde-onemli-degisiklik
     # ... so Turkey will move clocks forward one hour on March 31 at 3:00 a.m.
    -# From Paul Eggert (2014-02-17):
    -# Here is an English-language source:
    -# http://www.worldbulletin.net/turkey/129016/turkey-switches-to-daylight-saving-time-march-31
    +# From Randal L. Schwartz (2014-04-15):
    +# Having landed on a flight from the states to Istanbul (via AMS) on March 31,
    +# I can tell you that NOBODY (even the airlines) respected this timezone DST
    +# change delay.  Maybe the word just didn't get out in time.
    +# From Paul Eggert (2014-06-15):
    +# The press reported massive confusion, as election officials obeyed the rule
    +# change but cell phones (and airline baggage systems) did not.  See:
    +# Kostidis M. Eventful elections in Turkey. Balkan News Agency
    +# http://www.balkaneu.com/eventful-elections-turkey/ 2014-03-30.
    +# I guess the best we can do is document the official time.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Turkey	1916	only	-	May	 1	0:00	1:00	S
    @@ -2846,10 +3205,10 @@ Zone	Europe/Istanbul	1:55:52 -	LMT	1880
     			2:00	Turkey	EE%sT	1978 Oct 15
     			3:00	Turkey	TR%sT	1985 Apr 20 # Turkey Time
     			2:00	Turkey	EE%sT	2007
    -			2:00	EU	EE%sT	2011 Mar 27 1:00u
    -			2:00	-	EET	2011 Mar 28 1:00u
    -			2:00	EU	EE%sT	2014 Mar 30 1:00u
    -			2:00	-	EET	2014 Mar 31 1:00u
    +			2:00	EU	EE%sT	2011 Mar 27  1:00u
    +			2:00	-	EET	2011 Mar 28  1:00u
    +			2:00	EU	EE%sT	2014 Mar 30  1:00u
    +			2:00	-	EET	2014 Mar 31  1:00u
     			2:00	EU	EE%sT
     Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
     
    @@ -2870,7 +3229,7 @@ Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
     # Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
     # approval from 266 deputies.
     #
    -# Ukraine abolishes transter back to the winter time (in Russian)
    +# Ukraine abolishes transfer back to the winter time (in Russian)
     # http://news.mail.ru/politics/6861560/
     #
     # The Ukrainians will no longer change the clock (in Russian)
    @@ -2931,12 +3290,12 @@ Zone Europe/Kiev	2:02:04 -	LMT	1880
     			2:00	-	EET	1930 Jun 21
     			3:00	-	MSK	1941 Sep 20
     			1:00	C-Eur	CE%sT	1943 Nov  6
    -			3:00	Russia	MSK/MSD	1990 Jul  1 2:00
    -			2:00	1:00	EEST	1991 Sep 29 3:00
    +			3:00	Russia	MSK/MSD	1990 Jul  1  2:00
    +			2:00	1:00	EEST	1991 Sep 29  3:00
     			2:00	E-Eur	EE%sT	1995
     			2:00	EU	EE%sT
     # Ruthenia used CET 1990/1991.
    -# "Uzhhorod" is the transliteration of the Ukrainian name, but
    +# "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but
     # "Uzhgorod" is more common in English.
     Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
     			1:00	-	CET	1940
    @@ -2944,8 +3303,8 @@ Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
     			1:00	1:00	CEST	1944 Oct 26
     			1:00	-	CET	1945 Jun 29
     			3:00	Russia	MSK/MSD	1990
    -			3:00	-	MSK	1990 Jul  1 2:00
    -			1:00	-	CET	1991 Mar 31 3:00
    +			3:00	-	MSK	1990 Jul  1  2:00
    +			1:00	-	CET	1991 Mar 31  3:00
     			2:00	-	EET	1992
     			2:00	E-Eur	EE%sT	1995
     			2:00	EU	EE%sT
    @@ -2959,42 +3318,9 @@ Zone Europe/Zaporozhye	2:20:40 -	LMT	1880
     			2:00	-	EET	1930 Jun 21
     			3:00	-	MSK	1941 Aug 25
     			1:00	C-Eur	CE%sT	1943 Oct 25
    -			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
    +			3:00	Russia	MSK/MSD	1991 Mar 31  2:00
     			2:00	E-Eur	EE%sT	1995
     			2:00	EU	EE%sT
    -# Central Crimea used Moscow time 1994/1997.
    -Zone Europe/Simferopol	2:16:24 -	LMT	1880
    -			2:16	-	SMT	1924 May  2 # Simferopol Mean T
    -			2:00	-	EET	1930 Jun 21
    -			3:00	-	MSK	1941 Nov
    -			1:00	C-Eur	CE%sT	1944 Apr 13
    -			3:00	Russia	MSK/MSD	1990
    -			3:00	-	MSK	1990 Jul  1 2:00
    -			2:00	-	EET	1992
    -# From Paul Eggert (2006-03-22):
    -# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
    -# from Kiev to Moscow time sometime after the January 1994 elections.
    -# Shanks (1999) says "date of change uncertain", but implies that it happened
    -# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
    -# 1994-09-25 03:00, but that can't be right.  For now, guess it
    -# changed in May.
    -			2:00	E-Eur	EE%sT	1994 May
    -# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
    -			3:00	E-Eur	MSK/MSD	1996 Mar 31 3:00s
    -			3:00	1:00	MSD	1996 Oct 27 3:00s
    -# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
    -# Assume it happened in March by not changing the clocks.
    -			3:00	Russia	MSK/MSD	1997
    -			3:00	-	MSK	1997 Mar lastSun 1:00u
    -# From Alexander Krivenyshev (2014-03-17):
    -# time change at 2:00 (2am) on March 30, 2014
    -# http://vz.ru/news/2014/3/17/677464.html
    -# From Paul Eggert (2014-03-30):
    -# Simferopol and Sevastopol reportedly changed their central town clocks
    -# late the previous day, but this appears to have been ceremonial
    -# and the discrepancies are small enough to not worry about.
    -			2:00	EU	EE%sT	2014 Mar 30 2:00
    -			4:00	-	MSK
     
     # Vatican City
     # See Europe/Rome.
    @@ -3018,7 +3344,7 @@ Zone Europe/Simferopol	2:16:24 -	LMT	1880
     # ...
     #
     # ...the European time rules are...standardized since 1981, when
    -# most European coun[tr]ies started DST.  Before that year, only
    +# most European countries started DST.  Before that year, only
     # a few countries (UK, France, Italy) had DST, each according
     # to own national rules.  In 1981, however, DST started on
     # 'Apr firstSun', and not on 'Mar lastSun' as in the following
    @@ -3026,7 +3352,7 @@ Zone Europe/Simferopol	2:16:24 -	LMT	1880
     # But also since 1981 there are some more national exceptions
     # than listed in 'europe': Switzerland, for example, joined DST
     # one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
    -# lastSun' in 1981---I don't know how they handle now.
    +# lastSun' in 1981 - I don't know how they handle now.
     #
     # Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
     # Soviet Union (as far as I know).
    diff --git a/test/sun/util/calendar/zi/tzdata/factory b/test/sun/util/calendar/zi/tzdata/factory
    index 813d99a1f1f95d0ff89095a2abd446b190872cb1..0a6041db07e8c0751f5c2d01bd4049035ffc9145 100644
    --- a/test/sun/util/calendar/zi/tzdata/factory
    +++ b/test/sun/util/calendar/zi/tzdata/factory
    @@ -21,7 +21,6 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    diff --git a/test/sun/util/calendar/zi/tzdata/iso3166.tab b/test/sun/util/calendar/zi/tzdata/iso3166.tab
    index 28fb64b647ef58ff9919ca184a0590b464adcdf7..63eadcbd0c512e0bd6239151370160d3b8deab57 100644
    --- a/test/sun/util/calendar/zi/tzdata/iso3166.tab
    +++ b/test/sun/util/calendar/zi/tzdata/iso3166.tab
    @@ -26,21 +26,21 @@
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     #
    -# From Paul Eggert (2013-05-27):
    +# From Paul Eggert (2014-07-18):
    +# This file contains a table of two-letter country codes.  Columns are
    +# separated by a single tab.  Lines beginning with '#' are comments.
    +# Although all text currently uses ASCII encoding, this is planned to
    +# change to UTF-8 soon.  The columns of the table are as follows:
     #
    -# This file contains a table with the following columns:
     # 1.  ISO 3166-1 alpha-2 country code, current as of
    -#     ISO 3166-1 Newsletter VI-15 (2013-05-10).  See: Updates on ISO 3166
    +#     ISO 3166-1 Newsletter VI-16 (2013-07-11).  See: Updates on ISO 3166
     #   http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm
     # 2.  The usual English name for the coded region,
     #     chosen so that alphabetic sorting of subsets produces helpful lists.
     #     This is not the same as the English name in the ISO 3166 tables.
     #
    -# Columns are separated by a single tab.
     # The table is sorted by country code.
     #
    -# Lines beginning with `#' are comments.
    -#
     # This table is intended as an aid for users, to help them select time
     # zone data appropriate for their practical needs.  It is not intended
     # to take or endorse any position on legal or territorial claims.
    diff --git a/test/sun/util/calendar/zi/tzdata/leapseconds b/test/sun/util/calendar/zi/tzdata/leapseconds
    index b423135b942d092c4a8f24eaac19f3c8db1bf021..d38abd6a4bdde8dd16998d1ea03bc131438fe08f 100644
    --- a/test/sun/util/calendar/zi/tzdata/leapseconds
    +++ b/test/sun/util/calendar/zi/tzdata/leapseconds
    @@ -21,7 +21,7 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# Allowance for leapseconds added to each timezone file.
    +# Allowance for leap seconds added to each time zone file.
     
     # This file is in the public domain.
     
    @@ -31,7 +31,7 @@
     # you should be able to pick up leap-seconds.list from a secondary NIST server.
     # For more about leap-seconds.list, please see
     # The NTP Timescale and Leap Seconds
    -# .
    +# http://www.eecis.udel.edu/~mills/leap.html
     
     # The International Earth Rotation Service periodically uses leap seconds
     # to keep UTC to within 0.9 s of UT1
    diff --git a/test/sun/util/calendar/zi/tzdata/northamerica b/test/sun/util/calendar/zi/tzdata/northamerica
    index dc0c2e92cff499a8a1c53d2ce2be86ec84465c2c..0dc714aa92d9cd3b7d59128c1074eeb53ec01f67 100644
    --- a/test/sun/util/calendar/zi/tzdata/northamerica
    +++ b/test/sun/util/calendar/zi/tzdata/northamerica
    @@ -21,15 +21,15 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
     # also includes Central America and the Caribbean
     
    -# This data is by no means authoritative; if you think you know better,
    +# This file is by no means authoritative; if you think you know better,
     # go ahead and edit the file (and please send any changes to
    -# tz@iana.org for general use in the future).
    +# tz@iana.org for general use in the future).  For more, please see
    +# the file CONTRIBUTING in the tz distribution.
     
     # From Paul Eggert (1999-03-22):
     # A reliable and entertaining source about time zones is
    @@ -78,13 +78,13 @@
     #	to push people into bed earlier, and get them up earlier, to make
     #	them healthy, wealthy and wise in spite of themselves.
     #
    -#	-- Robertson Davies, The diary of Samuel Marchbanks,
    +#	 -- Robertson Davies, The diary of Samuel Marchbanks,
     #	   Clarke, Irwin (1947), XIX, Sunday
     #
     # For more about the first ten years of DST in the United States, see
    -# Robert Garland's 
    -# Ten years of daylight saving from the Pittsburgh standpoint
    -# (Carnegie Library of Pittsburgh, 1927).
    +# Robert Garland, Ten years of daylight saving from the Pittsburgh standpoint
    +# (Carnegie Library of Pittsburgh, 1927).
    +# http://www.clpgh.org/exhibit/dst.html
     #
     # Shanks says that DST was called "War Time" in the US in 1918 and 1919.
     # However, DST was imposed by the Standard Time Act of 1918, which
    @@ -103,11 +103,11 @@
     # From Arthur David Olson (2000-09-25):
     # Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
     # In the introduction, Oboler spoke of "Eastern Peace Time."
    -# An AltaVista search turned up
    -# :
    +# An AltaVista search turned up:
    +# http://rowayton.org/rhs/hstaug45.html
     # "When the time is announced over the radio now, it is 'Eastern Peace
     # Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
    -#  (August 1945) by way of confirmation.
    +# (August 1945) by way of confirmation.
     
     # From Joseph Gallant citing
     # George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
    @@ -205,7 +205,7 @@ Zone	PST8PDT		 -8:00	US	P%sT
     # USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
     # USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
     # USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
    -# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
    +# USA    "           9 H  BEHIND UTC    APR 3 - OCT 30
     # USA  HAWAII       10 H  BEHIND UTC
     # USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
     
    @@ -258,19 +258,19 @@ Zone	PST8PDT		 -8:00	US	P%sT
     # The following was signed into law on 2005-08-08.
     #
     # H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
    -#   (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
    +#   (a) Amendment.--Section 3(a) of the Uniform Time Act of 1966 (15
     #   U.S.C. 260a(a)) is amended--
    -#     (1) by striking 'first Sunday of April' and inserting 'second
    -#     Sunday of March'; and
    -#     (2) by striking 'last Sunday of October' and inserting 'first
    +#     (1) by striking "first Sunday of April" and inserting "second
    +#     Sunday of March"; and
    +#     (2) by striking "last Sunday of October" and inserting "first
     #     Sunday of November'.
    -#   (b) Effective Date- Subsection (a) shall take effect 1 year after the
    +#   (b) Effective Date.--Subsection (a) shall take effect 1 year after the
     #   date of enactment of this Act or March 1, 2007, whichever is later.
    -#   (c) Report to Congress- Not later than 9 months after the effective
    +#   (c) Report to Congress.--Not later than 9 months after the effective
     #   date stated in subsection (b), the Secretary shall report to Congress
     #   on the impact of this section on energy consumption in the United
     #   States.
    -#   (d) Right to Revert- Congress retains the right to revert the
    +#   (d) Right to Revert.--Congress retains the right to revert the
     #   Daylight Saving Time back to the 2005 time schedules once the
     #   Department study is complete.
     
    @@ -292,7 +292,7 @@ Zone	PST8PDT		 -8:00	US	P%sT
     
     # From Paul Eggert (2005-08-26):
     # According to today's Huntsville Times
    -# 
    +# http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1
     # a few towns on Alabama's "eastern border with Georgia, such as Phenix City
     # in Russell County, Lanett in Chambers County and some towns in Lee County,
     # set their watches and clocks on Eastern time."  It quotes H.H. "Bubba"
    @@ -347,15 +347,15 @@ Rule	Chicago	1955	1966	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
     			-6:00	US	C%sT	1920
    -			-6:00	Chicago	C%sT	1936 Mar  1 2:00
    -			-5:00	-	EST	1936 Nov 15 2:00
    +			-6:00	Chicago	C%sT	1936 Mar  1  2:00
    +			-5:00	-	EST	1936 Nov 15  2:00
     			-6:00	Chicago	C%sT	1942
     			-6:00	US	C%sT	1946
     			-6:00	Chicago	C%sT	1967
     			-6:00	US	C%sT
     # Oliver County, ND switched from mountain to central time on 1992-10-25.
     Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
    -			-7:00	US	M%sT	1992 Oct 25 02:00
    +			-7:00	US	M%sT	1992 Oct 25  2:00
     			-6:00	US	C%sT
     # Morton County, ND, switched from mountain to central time on
     # 2003-10-26, except for the area around Mandan which was already central time.
    @@ -364,29 +364,26 @@ Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
     # Jones, Mellette, and Todd Counties in South Dakota;
     # but in practice these other counties were already observing central time.
     # See .
    -Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
    -			-7:00	US	M%sT	2003 Oct 26 02:00
    +Zone America/North_Dakota/New_Salem -6:45:39 - LMT	1883 Nov 18 12:14:21
    +			-7:00	US	M%sT	2003 Oct 26  2:00
     			-6:00	US	C%sT
     
     # From Josh Findley (2011-01-21):
     # ...it appears that Mercer County, North Dakota, changed from the
     # mountain time zone to the central time zone at the last transition from
     # daylight-saving to standard time (on Nov. 7, 2010):
    -# 
     # http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm
    -# 
    -# 
     # http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html
    -# 
     
     # From Andy Lipscomb (2011-01-24):
     # ...according to the Census Bureau, the largest city is Beulah (although
     # it's commonly referred to as Beulah-Hazen, with Hazen being the next
     # largest city in Mercer County).  Google Maps places Beulah's city hall
    -# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07".
    +# at 47 degrees 15' 51" N, 101 degrees 46' 40" W, which yields an offset
    +# of 6h47'07".
     
    -Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53
    -			-7:00	US	M%sT	2010 Nov  7 2:00
    +Zone America/North_Dakota/Beulah -6:47:07 - LMT	1883 Nov 18 12:12:53
    +			-7:00	US	M%sT	2010 Nov  7  2:00
     			-6:00	US	C%sT
     
     # US mountain time, represented by Denver
    @@ -448,15 +445,18 @@ Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
     # was destroyed in 1805 by a Yakutat-kon war party.)  However, there
     # were nearby inhabitants in some cases and for our purposes perhaps
     # it's best to simply use the official transition.
    -#
     
    -# From Steve Ferguson (2011-01-31):
    -# The author lives in Alaska and many of the references listed are only
    -# available to Alaskan residents.
    +# From Paul Eggert (2014-07-18):
    +# One opinion of the early-1980s turmoil in Alaska over time zones and
    +# daylight saving time appeared as graffiti on a Juneau airport wall:
    +# "Welcome to Juneau.  Please turn your watch back to the 19th century."
    +# See: Turner W. Alaska's four time zones now two. NY Times 1983-11-01.
    +# http://www.nytimes.com/1983/11/01/us/alaska-s-four-time-zones-now-two.html
     #
    -# 
    -# http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98
    -# 
    +# Steve Ferguson (2011-01-31) referred to the following source:
    +# Norris F. Keeping time in Alaska: national directives, local response.
    +# Alaska History 2001;16(1-2).
    +# http://alaskahistoricalsociety.org/discover-alaska/glimpses-of-the-past/keeping-time-in-alaska/
     
     # From Arthur David Olson (2011-02-01):
     # Here's database-relevant material from the 2001 "Alaska History" article:
    @@ -482,12 +482,10 @@ Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
     # From Arthur David Olson (2011-02-09):
     # I just spoke by phone with a staff member at the Metlakatla Indian
     # Community office (using contact information available at
    -# 
     # http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla
    -# ).
     # It's shortly after 1:00 here on the east coast of the United States;
     # the staffer said it was shortly after 10:00 there. When I asked whether
    -# that meant they were on Pacific time, they said no--they were on their
    +# that meant they were on Pacific time, they said no - they were on their
     # own time. I asked about daylight saving; they said it wasn't used. I
     # did not inquire about practices in the past.
     
    @@ -501,9 +499,9 @@ Zone America/Juneau	 15:02:19 -	LMT	1867 Oct 18
     			 -8:00	-	PST	1942
     			 -8:00	US	P%sT	1946
     			 -8:00	-	PST	1969
    -			 -8:00	US	P%sT	1980 Apr 27 2:00
    -			 -9:00	US	Y%sT	1980 Oct 26 2:00
    -			 -8:00	US	P%sT	1983 Oct 30 2:00
    +			 -8:00	US	P%sT	1980 Apr 27  2:00
    +			 -9:00	US	Y%sT	1980 Oct 26  2:00
    +			 -8:00	US	P%sT	1983 Oct 30  2:00
     			 -9:00	US	Y%sT	1983 Nov 30
     			 -9:00	US	AK%sT
     Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
    @@ -511,7 +509,7 @@ Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
     			 -8:00	-	PST	1942
     			 -8:00	US	P%sT	1946
     			 -8:00	-	PST	1969
    -			 -8:00	US	P%sT	1983 Oct 30 2:00
    +			 -8:00	US	P%sT	1983 Oct 30  2:00
     			 -9:00	US	Y%sT	1983 Nov 30
     			 -9:00	US	AK%sT
     Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
    @@ -519,8 +517,8 @@ Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
     			 -8:00	-	PST	1942
     			 -8:00	US	P%sT	1946
     			 -8:00	-	PST	1969
    -			 -8:00	US	P%sT	1983 Oct 30 2:00
    -			 -8:00	-	MeST
    +			 -8:00	US	P%sT	1983 Oct 30  2:00
    +			 -8:00	-	PST
     Zone America/Yakutat	 14:41:05 -	LMT	1867 Oct 18
     			 -9:18:55 -	LMT	1900 Aug 20 12:00
     			 -9:00	-	YST	1942
    @@ -535,7 +533,7 @@ Zone America/Anchorage	 14:00:24 -	LMT	1867 Oct 18
     			-10:00	US	CAT/CAPT 1946 # Peace
     			-10:00	-	CAT	1967 Apr
     			-10:00	-	AHST	1969
    -			-10:00	US	AH%sT	1983 Oct 30 2:00
    +			-10:00	US	AH%sT	1983 Oct 30  2:00
     			 -9:00	US	Y%sT	1983 Nov 30
     			 -9:00	US	AK%sT
     Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
    @@ -544,7 +542,7 @@ Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
     			-11:00	US	N%sT	1946
     			-11:00	-	NST	1967 Apr
     			-11:00	-	BST	1969
    -			-11:00	US	B%sT	1983 Oct 30 2:00
    +			-11:00	US	B%sT	1983 Oct 30  2:00
     			 -9:00	US	Y%sT	1983 Nov 30
     			 -9:00	US	AK%sT
     Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
    @@ -553,7 +551,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
     			-11:00	US	N%sT	1946
     			-11:00	-	NST	1967 Apr
     			-11:00	-	BST	1969
    -			-11:00	US	B%sT	1983 Oct 30 2:00
    +			-11:00	US	B%sT	1983 Oct 30  2:00
     			-10:00	US	AH%sT	1983 Nov 30
     			-10:00	US	HA%sT
     # The following switches don't quite make our 1970 cutoff.
    @@ -571,7 +569,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
     #  Minutes of the Unalaska City Council Meeting, January 10, 1967:
     #  "Except for St. Paul and Akutan, Unalaska is the only important
     #  location not on Alaska Standard Time.  The following resolution was
    -#  made by William Robinson and seconded by Henry Swanson:  Be it
    +#  made by William Robinson and seconded by Henry Swanson: Be it
     #  resolved that the City of Unalaska hereby goes to Alaska Standard
     #  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
     #  January 14, Alaska Standard Time.)  This resolution was passed with
    @@ -583,9 +581,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
     # "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225
     # of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09,
     # the article is available at
    -# 
     # http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf
    -# 
     # and indicates that standard time was adopted effective noon, January
     # 13, 1896 (page 218), that in "1933, the Legislature decreed daylight
     # saving for the period between the last Sunday of each April and the
    @@ -606,7 +602,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
     # year, the standard time of this Territory shall be advanced one
     # hour...This Act shall take effect upon its approval. Approved this 26th
     # day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of
    -# Hawaii." Page 172:  "Act 163...Act 90 of the Session Laws of 1933 is
    +# Hawaii." Page 172: "Act 163...Act 90 of the Session Laws of 1933 is
     # hereby repealed...This Act shall take effect upon its approval, upon
     # which date the standard time of this Territory shall be restored to
     # that existing immediately prior to the taking effect of said Act 90.
    @@ -616,14 +612,14 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
     # Note that 1933-05-21 was a Sunday.
     # We're left to guess the time of day when Act 163 was approved; guess noon.
     
    -Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00 #Schmitt&Cox
    -			-10:30	-	HST	1933 Apr 30 2:00 #Laws 1933
    -			-10:30	1:00	HDT	1933 May 21 12:00 #Laws 1933+12
    -			-10:30	-	HST	1942 Feb 09 2:00 #Schmitt&Cox+2
    -			-10:30	1:00	HDT	1945 Sep 30 2:00 #Schmitt&Cox+2
    -			-10:30	-	HST	1947 Jun  8 2:00 #Schmitt&Cox+2
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00
    +			-10:30	-	HST	1933 Apr 30  2:00
    +			-10:30	1:00	HDT	1933 May 21 12:00
    +			-10:30	-	HST	1942 Feb  9  2:00
    +			-10:30	1:00	HDT	1945 Sep 30  2:00
    +			-10:30	-	HST	1947 Jun  8  2:00
     			-10:00	-	HST
    -
     Link Pacific/Honolulu Pacific/Johnston
     
     # Now we turn to US areas that have diverged from the consensus since 1970.
    @@ -633,9 +629,9 @@ Link Pacific/Honolulu Pacific/Johnston
     # From Paul Eggert (2002-10-20):
     #
     # The information in the rest of this paragraph is derived from the
    -# 
    -# Daylight Saving Time web page (2002-01-23) maintained by the
    -# Arizona State Library, Archives and Public Records.
    +# Daylight Saving Time web page
    +#  (2002-01-23)
    +# maintained by the Arizona State Library, Archives and Public Records.
     # Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
     # time, but by federal law railroads, airlines, bus lines, military
     # personnel, and some engaged in interstate commerce continued to
    @@ -649,10 +645,11 @@ Link Pacific/Honolulu Pacific/Johnston
     # Shanks says the 1944 experiment came to an end on 1944-03-17.
     # Go with the Arizona State Library instead.
     
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
    -			-7:00	US	M%sT	1944 Jan  1 00:01
    -			-7:00	-	MST	1944 Apr  1 00:01
    -			-7:00	US	M%sT	1944 Oct  1 00:01
    +			-7:00	US	M%sT	1944 Jan  1  0:01
    +			-7:00	-	MST	1944 Apr  1  0:01
    +			-7:00	US	M%sT	1944 Oct  1  0:01
     			-7:00	-	MST	1967
     			-7:00	US	M%sT	1968 Mar 21
     			-7:00	-	MST
    @@ -676,24 +673,22 @@ Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
     #
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
    -			-8:00	US	P%sT	1923 May 13 2:00
    +			-8:00	US	P%sT	1923 May 13  2:00
     			-7:00	US	M%sT	1974
    -			-7:00	-	MST	1974 Feb  3 2:00
    +			-7:00	-	MST	1974 Feb  3  2:00
     			-7:00	US	M%sT
     
     # Indiana
     #
     # For a map of Indiana's time zone regions, see:
    -# 
    -# What time is it in Indiana?
    -#  (2006-03-01)
    +# http://en.wikipedia.org/wiki/Time_in_Indiana
     #
     # From Paul Eggert (2007-08-17):
     # Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
     # with the following exceptions:
     #
     # - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
    -#   Vandenburgh, and Warrick counties have been like America/Chicago.
    +#   Vanderburgh, and Warrick counties have been like America/Chicago.
     #
     # - Dearborn and Ohio counties have been like America/New_York.
     #
    @@ -712,22 +707,16 @@ Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
     # that they would be ambiguous if we left them at the 'America' level.
     # So we reluctantly put them all in a subdirectory 'America/Indiana'.
     
    -# From Paul Eggert (2005-08-16):
    -# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
    -
    -# From Nathan Stratton Treadway (2006-03-30):
    -# http://www.dot.gov/affairs/dot0406.htm [3705 B]
    -# From Deborah Goldsmith (2006-01-18):
    -# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
    -# From Paul Eggert (2006-01-20):
    -# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
    +# From Paul Eggert (2014-06-26):
    +# https://www.federalregister.gov/articles/2006/01/20/06-563/standard-time-zone-boundary-in-the-state-of-indiana
    +# says "DOT is relocating the time zone boundary in Indiana to move Starke,
     # Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
     # Eastern Time Zone to the Central Time Zone.... The effective date of
    -# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
    +# this rule is 2 a.m. EST Sunday, April 2, 2006, which is the
     # changeover date from standard time to Daylight Saving Time."
    -# Strictly speaking, this means the affected counties will change their
    -# clocks twice that night, but this obviously is in error.  The intent
    -# is that 01:59:59 EST be followed by 02:00:00 CDT.
    +# Strictly speaking, this meant the affected counties changed their
    +# clocks twice that night, but this obviously was in error.  The intent
    +# was that 01:59:59 EST be followed by 02:00:00 CDT.
     
     # From Gwillim Law (2007-02-10):
     # The Associated Press has been reporting that Pulaski County, Indiana is
    @@ -739,13 +728,13 @@ Rule Indianapolis 1941	only	-	Jun	22	2:00	1:00	D
     Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
     Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
    +Zone America/Indiana/Indianapolis -5:44:38 - LMT	1883 Nov 18 12:15:22
     			-6:00	US	C%sT	1920
     			-6:00 Indianapolis C%sT	1942
     			-6:00	US	C%sT	1946
    -			-6:00 Indianapolis C%sT	1955 Apr 24 2:00
    -			-5:00	-	EST	1957 Sep 29 2:00
    -			-6:00	-	CST	1958 Apr 27 2:00
    +			-6:00 Indianapolis C%sT	1955 Apr 24  2:00
    +			-5:00	-	EST	1957 Sep 29  2:00
    +			-6:00	-	CST	1958 Apr 27  2:00
     			-5:00	-	EST	1969
     			-5:00	US	E%sT	1971
     			-5:00	-	EST	2006
    @@ -761,10 +750,10 @@ Rule	Marengo	1954	1960	-	Sep	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
     			-6:00	US	C%sT	1951
    -			-6:00	Marengo	C%sT	1961 Apr 30 2:00
    +			-6:00	Marengo	C%sT	1961 Apr 30  2:00
     			-5:00	-	EST	1969
    -			-5:00	US	E%sT	1974 Jan  6 2:00
    -			-6:00	1:00	CDT	1974 Oct 27 2:00
    +			-5:00	US	E%sT	1974 Jan  6  2:00
    +			-6:00	1:00	CDT	1974 Oct 27  2:00
     			-5:00	US	E%sT	1976
     			-5:00	-	EST	2006
     			-5:00	US	E%sT
    @@ -785,11 +774,11 @@ Rule Vincennes	1962	1963	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
     			-6:00	US	C%sT	1946
    -			-6:00 Vincennes	C%sT	1964 Apr 26 2:00
    +			-6:00 Vincennes	C%sT	1964 Apr 26  2:00
     			-5:00	-	EST	1969
     			-5:00	US	E%sT	1971
    -			-5:00	-	EST	2006 Apr  2 2:00
    -			-6:00	US	C%sT	2007 Nov  4 2:00
    +			-5:00	-	EST	2006 Apr  2  2:00
    +			-6:00	US	C%sT	2007 Nov  4  2:00
     			-5:00	US	E%sT
     #
     # Perry County, Indiana, switched from eastern to central time in April 2006.
    @@ -806,10 +795,10 @@ Rule Perry	1962	1963	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
     			-6:00	US	C%sT	1946
    -			-6:00 Perry	C%sT	1964 Apr 26 2:00
    +			-6:00 Perry	C%sT	1964 Apr 26  2:00
     			-5:00	-	EST	1969
     			-5:00	US	E%sT	1971
    -			-5:00	-	EST	2006 Apr  2 2:00
    +			-5:00	-	EST	2006 Apr  2  2:00
     			-6:00	US	C%sT
     #
     # Pike County, Indiana moved from central to eastern time in 1977,
    @@ -822,11 +811,11 @@ Rule	Pike	1961	1964	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
     			-6:00	US	C%sT	1955
    -			-6:00	Pike	C%sT	1965 Apr 25 2:00
    -			-5:00	-	EST	1966 Oct 30 2:00
    -			-6:00	US	C%sT	1977 Oct 30 2:00
    -			-5:00	-	EST	2006 Apr  2 2:00
    -			-6:00	US	C%sT	2007 Nov  4 2:00
    +			-6:00	Pike	C%sT	1965 Apr 25  2:00
    +			-5:00	-	EST	1966 Oct 30  2:00
    +			-6:00	US	C%sT	1977 Oct 30  2:00
    +			-5:00	-	EST	2006 Apr  2  2:00
    +			-6:00	US	C%sT	2007 Nov  4  2:00
     			-5:00	US	E%sT
     #
     # Starke County, Indiana moved from central to eastern time in 1991,
    @@ -844,10 +833,10 @@ Rule	Starke	1959	1961	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
     			-6:00	US	C%sT	1947
    -			-6:00	Starke	C%sT	1962 Apr 29 2:00
    -			-5:00	-	EST	1963 Oct 27 2:00
    -			-6:00	US	C%sT	1991 Oct 27 2:00
    -			-5:00	-	EST	2006 Apr  2 2:00
    +			-6:00	Starke	C%sT	1962 Apr 29  2:00
    +			-5:00	-	EST	1963 Oct 27  2:00
    +			-6:00	US	C%sT	1991 Oct 27  2:00
    +			-5:00	-	EST	2006 Apr  2  2:00
     			-6:00	US	C%sT
     #
     # Pulaski County, Indiana, switched from eastern to central time in
    @@ -860,17 +849,17 @@ Rule	Pulaski	1957	1960	-	Sep	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
     			-6:00	US	C%sT	1946
    -			-6:00	Pulaski	C%sT	1961 Apr 30 2:00
    +			-6:00	Pulaski	C%sT	1961 Apr 30  2:00
     			-5:00	-	EST	1969
     			-5:00	US	E%sT	1971
    -			-5:00	-	EST	2006 Apr  2 2:00
    -			-6:00	US	C%sT	2007 Mar 11 2:00
    +			-5:00	-	EST	2006 Apr  2  2:00
    +			-6:00	US	C%sT	2007 Mar 11  2:00
     			-5:00	US	E%sT
     #
     # Switzerland County, Indiana, did not observe DST from 1973 through 2005.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
    -			-6:00	US	C%sT	1954 Apr 25 2:00
    +			-6:00	US	C%sT	1954 Apr 25  2:00
     			-5:00	-	EST	1969
     			-5:00	US	E%sT	1973
     			-5:00	-	EST	2006
    @@ -891,18 +880,17 @@ Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
     			-6:00	US	C%sT	1921
     			-6:00 Louisville C%sT	1942
     			-6:00	US	C%sT	1946
    -			-6:00 Louisville C%sT	1961 Jul 23 2:00
    +			-6:00 Louisville C%sT	1961 Jul 23  2:00
     			-5:00	-	EST	1968
    -			-5:00	US	E%sT	1974 Jan  6 2:00
    -			-6:00	1:00	CDT	1974 Oct 27 2:00
    +			-5:00	US	E%sT	1974 Jan  6  2:00
    +			-6:00	1:00	CDT	1974 Oct 27  2:00
     			-5:00	US	E%sT
     #
     # Wayne County, Kentucky
     #
    -# From
    -# 
    -# Lake Cumberland LIFE
    -#  (1999-01-29) via WKYM-101.7:
    +# From Lake Cumberland LIFE
    +# http://www.lake-cumberland.com/life/archive/news990129time.shtml
    +# (1999-01-29) via WKYM-101.7:
     # Clinton County has joined Wayne County in asking the DoT to change from
     # the Central to the Eastern time zone....  The Wayne County government made
     # the same request in December.  And while Russell County officials have not
    @@ -919,9 +907,8 @@ Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
     #
     # From Paul Eggert (2001-07-16):
     # The final rule was published in the
    -# 
    -# Federal Register 65, 160 (2000-08-17), page 50154-50158.
    -# 
    +# Federal Register 65, 160 (2000-08-17), pp 50154-50158.
    +# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22
     #
     Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
     			-6:00	US	C%sT	1946
    @@ -946,9 +933,8 @@ Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
     # See America/North_Dakota/Center for the Oliver County, ND change.
     # West Wendover, NV officially switched from Pacific to mountain time on
     # 1999-10-31.  See the
    -# 
    -# Federal Register 64, 203 (1999-10-21), page 56705-56707.
    -# 
    +# Federal Register 64, 203 (1999-10-21), pp 56705-56707.
    +# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15
     # However, the Federal Register says that West Wendover already operated
     # on mountain time, and the rule merely made this official;
     # hence a separate tz entry is not needed.
    @@ -986,12 +972,12 @@ Rule	Detroit	1967	only	-	Jun	14	2:00	1:00	D
     Rule	Detroit	1967	only	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Detroit	-5:32:11 -	LMT	1905
    -			-6:00	-	CST	1915 May 15 2:00
    +			-6:00	-	CST	1915 May 15  2:00
     			-5:00	-	EST	1942
     			-5:00	US	E%sT	1946
     			-5:00	Detroit	E%sT	1973
     			-5:00	US	E%sT	1975
    -			-5:00	-	EST	1975 Apr 27 2:00
    +			-5:00	-	EST	1975 Apr 27  2:00
     			-5:00	US	E%sT
     #
     # Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
    @@ -1004,8 +990,8 @@ Rule Menominee	1966	only	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     			-6:00	US	C%sT	1946
    -			-6:00 Menominee	C%sT	1969 Apr 27 2:00
    -			-5:00	-	EST	1973 Apr 29 2:00
    +			-6:00 Menominee	C%sT	1969 Apr 27  2:00
    +			-5:00	-	EST	1973 Apr 29  2:00
     			-6:00	US	C%sT
     
     # Navassa
    @@ -1042,9 +1028,9 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
     #	which I found in the UCLA library.
     #
    -#	
     #	William Willett, The Waste of Daylight, 19th edition
    -#	 (1914-03)
    +#	
    +#	[PDF] (1914-03)
     #
     #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
     #	.
    @@ -1053,11 +1039,11 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     
     # Canada
     
    -# From Alain LaBont (1994-11-14):
    +# From Alain LaBonté (1994-11-14):
     # I post here the time zone abbreviations standardized in Canada
     # for both English and French in the CAN/CSA-Z234.4-89 standard....
     #
    -#	UTC	Standard time	Daylight savings time
    +#	UTC	Standard time	Daylight saving time
     #	offset	French	English	French	English
     #	-2:30	-	-	HAT	NDT
     #	-3	-	-	HAA	ADT
    @@ -1070,7 +1056,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     #	-9	HNY	YST	-	-
     #
     #	HN: Heure Normale	ST: Standard Time
    -#	HA: Heure Avance	DT: Daylight saving Time
    +#	HA: Heure Avancée	DT: Daylight saving Time
     #
     #	A: de l'Atlantique	Atlantic
     #	C: du Centre		Central
    @@ -1085,7 +1071,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     # From Paul Eggert (1994-11-22):
     # Alas, this sort of thing must be handled by localization software.
     
    -# Unless otherwise specified, the data for Canada are all from Shanks
    +# Unless otherwise specified, the data entries for Canada are all from Shanks
     # & Pottenger.
     
     # From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
    @@ -1134,15 +1120,15 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     
     # From Paul Eggert (2006-04-25):
     # H. David Matthews and Mary Vincent's map
    -# 
     # "It's about TIME", _Canadian Geographic_ (September-October 1998)
    -#  contains detailed boundaries for regions observing nonstandard
    +# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
    +# contains detailed boundaries for regions observing nonstandard
     # time and daylight saving time arrangements in Canada circa 1998.
     #
    -# INMS, the Institute for National Measurement Standards in Ottawa, has 
    +# INMS, the Institute for National Measurement Standards in Ottawa, has
     # information about standard and daylight saving time zones in Canada.
    -#  (updated periodically).
    +# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php
    +# (updated periodically).
     # Its unofficial information is often taken from Matthews and Vincent.
     
     # From Paul Eggert (2006-06-27):
    @@ -1151,9 +1137,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
     
     # From Chris Walton (2011-12-01)
     # In the first of Tammy Hardwick's articles
    -# 
     # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
    -# 
     # she quotes the Friday November 1/1918 edition of the Creston Review.
     # The quote includes these two statements:
     # 'Sunday the CPR went back to the old system of time...'
    @@ -1221,9 +1205,7 @@ Rule	StJohns	1960	1986	-	Oct	lastSun	2:00	0	S
     # Time to Standard Time and from Standard Time to Daylight Savings Time
     # now occurs at 2:00AM.
     # ...
    -# 
     # http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
    -# 
     # ...
     # MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
     # Office of the Chief Information Officer
    @@ -1259,7 +1241,7 @@ Zone America/Goose_Bay	-4:01:40 -	LMT	1884 # Happy Valley-Goose Bay
     			-3:30	-	NST	1936
     			-3:30	StJohns	N%sT	1942 May 11
     			-3:30	Canada	N%sT	1946
    -			-3:30	StJohns	N%sT	1966 Mar 15 2:00
    +			-3:30	StJohns	N%sT	1966 Mar 15  2:00
     			-4:00	StJohns	A%sT	2011 Nov
     			-4:00	Canada	A%sT
     
    @@ -1320,7 +1302,7 @@ Rule	Halifax	1962	1973	-	Oct	lastSun	2:00	0	S
     Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
     			-4:00	Halifax	A%sT	1918
     			-4:00	Canada	A%sT	1919
    -			-4:00	Halifax	A%sT	1942 Feb  9 2:00s
    +			-4:00	Halifax	A%sT	1942 Feb  9  2:00s
     			-4:00	Canada	A%sT	1946
     			-4:00	Halifax	A%sT	1974
     			-4:00	Canada	A%sT
    @@ -1379,7 +1361,7 @@ Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
     # meridian is supposed to observe AST, but residents as far east as
     # Natashquan use EST/EDT, and residents east of Natashquan use AST.
     # The Quebec department of justice writes in
    -# "The situation in Minganie and Basse-Cote-Nord"
    +# "The situation in Minganie and Basse-Côte-Nord"
     # http://www.justice.gouv.qc.ca/english/publications/generale/temps-minganie-a.htm
     # that the coastal strip from just east of Natashquan to Blanc-Sablon
     # observes Atlantic standard time all year round.
    @@ -1387,7 +1369,6 @@ Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
     # says this common practice was codified into law as of 2007.
     # For lack of better info, guess this practice began around 1970, contra to
     # Shanks & Pottenger who have this region observing AST/ADT.
    -# for post-1970 data America/Puerto_Rico.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
    @@ -1401,18 +1382,10 @@ Rule	Mont	1922	only	-	Apr	30	2:00	1:00	D
     Rule	Mont	1924	only	-	May	17	2:00	1:00	D
     Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
     Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
    -# The 1927-to-1937 rules can be expressed more simply as
    -# Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
    -# Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
    -# The rules below avoid use of 24:00
    -# (which pre-1998 versions of zic cannot handle).
    -Rule	Mont	1927	only	-	May	1	0:00	1:00	D
    -Rule	Mont	1927	1932	-	Sep	lastSun	0:00	0	S
    -Rule	Mont	1928	1931	-	Apr	lastSun	0:00	1:00	D
    -Rule	Mont	1932	only	-	May	1	0:00	1:00	D
    -Rule	Mont	1933	1940	-	Apr	lastSun	0:00	1:00	D
    -Rule	Mont	1933	only	-	Oct	1	0:00	0	S
    -Rule	Mont	1934	1939	-	Sep	lastSun	0:00	0	S
    +Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
    +Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
    +Rule	Mont	1938	1940	-	Apr	lastSun	0:00	1:00	D
    +Rule	Mont	1938	1939	-	Sep	lastSun	0:00	0	S
     Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
     Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
     Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
    @@ -1426,7 +1399,7 @@ Zone America/Blanc-Sablon -3:48:28 -	LMT	1884
     Zone America/Montreal	-4:54:16 -	LMT	1884
     			-5:00	Mont	E%sT	1918
     			-5:00	Canada	E%sT	1919
    -			-5:00	Mont	E%sT	1942 Feb  9 2:00s
    +			-5:00	Mont	E%sT	1942 Feb  9  2:00s
     			-5:00	Canada	E%sT	1946
     			-5:00	Mont	E%sT	1974
     			-5:00	Canada	E%sT
    @@ -1448,7 +1421,7 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
     # have already done so.  In Orillia DST was to run until Saturday,
     # 1912-08-31 (no time mentioned), but it was met with considerable
     # hostility from certain segments of the public, and was revoked after
    -# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
    +# only two weeks - I copied it as Saturday, 1912-07-07, 22:00, but
     # presumably that should be -07-06.  (1912-06-19, -07-12; also letters
     # earlier in June).
     #
    @@ -1458,10 +1431,8 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
     # Mark Brader writes that an article in the 1997-10-14 Toronto Star
     # says that Atikokan, Ontario currently does not observe DST,
     # but will vote on 11-10 whether to use EST/EDT.
    -# He also writes that the
    -# 
    -# Ontario Time Act (1990, Chapter T.9)
    -# 
    +# He also writes that the Ontario Time Act (1990, Chapter T.9)
    +# http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html
     # says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
     # Officially Atikokan is therefore on CST/CDT, and most likely this report
     # concerns a non-official time observed as a matter of local practice.
    @@ -1540,9 +1511,7 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
     # The Journal of The Royal Astronomical Society of Canada,
     # volume 26, number 2 (February 1932) and, as of 2010-07-17,
     # was available at
    -# 
     # http://adsabs.harvard.edu/full/1932JRASC..26...49S
    -# 
     #
     # It includes the text below (starting on page 57):
     #
    @@ -1553,26 +1522,26 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
     # ing in 1930. The information for the province of Quebec is definite,
     # for the other provinces only approximate:
     #
    -# 	Province	Daylight saving time used
    +#	Province	Daylight saving time used
     # Prince Edward Island	Not used.
     # Nova Scotia		In Halifax only.
     # New Brunswick		In St. John only.
     # Quebec		In the following places:
    -# 			Montreal	Lachine
    -# 			Quebec		Mont-Royal
    -# 			Levis		Iberville
    -# 			St. Lambert	Cap de la Madeleine
    -# 			Verdun		Loretteville
    -# 			Westmount	Richmond
    -# 			Outremont	St. Jerome
    -# 			Longueuil	Greenfield Park
    -# 			Arvida		Waterloo
    -# 			Chambly-Canton	Beaulieu
    -# 			Melbourne	La Tuque
    -# 			St. Theophile	Buckingham
    +#			Montreal	Lachine
    +#			Quebec		Mont-Royal
    +#			Lévis		Iberville
    +#			St. Lambert	Cap de la Madelèine
    +#			Verdun		Loretteville
    +#			Westmount	Richmond
    +#			Outremont	St. Jérôme
    +#			Longueuil	Greenfield Park
    +#			Arvida		Waterloo
    +#			Chambly-Canton	Beaulieu
    +#			Melbourne	La Tuque
    +#			St. Théophile	Buckingham
     # Ontario		Used generally in the cities and towns along
    -# 			the southerly part of the province. Not
    -# 			used in the northwesterlhy part.
    +#			the southerly part of the province. Not
    +#			used in the northwesterly part.
     # Manitoba		Not used.
     # Saskatchewan		In Regina only.
     # Alberta		Not used.
    @@ -1641,7 +1610,7 @@ Rule	Toronto	1957	1973	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Toronto	-5:17:32 -	LMT	1895
     			-5:00	Canada	E%sT	1919
    -			-5:00	Toronto	E%sT	1942 Feb  9 2:00s
    +			-5:00	Toronto	E%sT	1942 Feb  9  2:00s
     			-5:00	Canada	E%sT	1946
     			-5:00	Toronto	E%sT	1974
     			-5:00	Canada	E%sT
    @@ -1654,16 +1623,16 @@ Zone America/Thunder_Bay -5:57:00 -	LMT	1895
     			-5:00	Canada	E%sT
     Zone America/Nipigon	-5:53:04 -	LMT	1895
     			-5:00	Canada	E%sT	1940 Sep 29
    -			-5:00	1:00	EDT	1942 Feb  9 2:00s
    +			-5:00	1:00	EDT	1942 Feb  9  2:00s
     			-5:00	Canada	E%sT
     Zone America/Rainy_River -6:18:16 -	LMT	1895
     			-6:00	Canada	C%sT	1940 Sep 29
    -			-6:00	1:00	CDT	1942 Feb  9 2:00s
    +			-6:00	1:00	CDT	1942 Feb  9  2:00s
     			-6:00	Canada	C%sT
     Zone America/Atikokan	-6:06:28 -	LMT	1895
     			-6:00	Canada	C%sT	1940 Sep 29
    -			-6:00	1:00	CDT	1942 Feb  9 2:00s
    -			-6:00	Canada	C%sT	1945 Sep 30 2:00
    +			-6:00	1:00	CDT	1942 Feb  9  2:00s
    +			-6:00	Canada	C%sT	1945 Sep 30  2:00
     			-5:00	-	EST
     
     
    @@ -1676,7 +1645,7 @@ Zone America/Atikokan	-6:06:28 -	LMT	1895
     # the first Sunday of April of each year and two o'clock Central
     # Standard Time in the morning of the last Sunday of October next
     # following, one hour in advance of Central Standard Time."...
    -# I believe that the English legislation [of the old time act] had =
    +# I believe that the English legislation [of the old time act] had
     # been assented to (March 22, 1967)....
     # Also, as far as I can tell, there was no order-in-council varying
     # the time of Daylight Saving Time for 2005 and so the provisions of
    @@ -1799,12 +1768,12 @@ Rule	Swift	1959	only	-	Oct	lastSun	2:00	0	S
     Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Regina	-6:58:36 -	LMT	1905 Sep
    -			-7:00	Regina	M%sT	1960 Apr lastSun 2:00
    +			-7:00	Regina	M%sT	1960 Apr lastSun  2:00
     			-6:00	-	CST
     Zone America/Swift_Current -7:11:20 -	LMT	1905 Sep
    -			-7:00	Canada	M%sT	1946 Apr lastSun 2:00
    +			-7:00	Canada	M%sT	1946 Apr lastSun  2:00
     			-7:00	Regina	M%sT	1950
    -			-7:00	Swift	M%sT	1972 Apr lastSun 2:00
    +			-7:00	Swift	M%sT	1972 Apr lastSun  2:00
     			-6:00	-	CST
     
     
    @@ -1854,9 +1823,7 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
     # Earlier this year I stumbled across a detailed article about the time
     # keeping history of Creston; it was written by Tammy Hardwick who is the
     # manager of the Creston & District Museum. The article was written in May 2009.
    -# 
     # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
    -# 
     # According to the article, Creston has not changed its clocks since June 1918.
     # i.e. Creston has been stuck on UTC-7 for 93 years.
     # Dawson Creek, on the other hand, changed its clocks as recently as April 1972.
    @@ -1864,18 +1831,16 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
     # Unfortunately the exact date for the time change in June 1918 remains
     # unknown and will be difficult to ascertain.  I e-mailed Tammy a few months
     # ago to ask if Sunday June 2 was a reasonable guess.  She said it was just
    -# as plausible as any other date (in June).  She also said that after writing the
    -# article she had discovered another time change in 1916; this is the subject
    -# of another article which she wrote in October 2010.
    -# 
    +# as plausible as any other date (in June).  She also said that after writing
    +# the article she had discovered another time change in 1916; this is the
    +# subject of another article which she wrote in October 2010.
     # http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56
    -# 
     
     # Here is a summary of the three clock change events in Creston's history:
     # 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
     # Exact date unknown
     # 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
    -# Exact date in October unknown;  Sunday October 1 is a reasonable guess.
    +# Exact date in October unknown; Sunday October 1 is a reasonable guess.
     # 3. June 1918: switch to Pacific Daylight Time (GMT-7)
     # Exact date in June unknown; Sunday June 2 is a reasonable guess.
     # note#1:
    @@ -1888,9 +1853,7 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
     # There is no guarantee that Creston will remain on Mountain Standard Time
     # (UTC-7) forever.
     # The subject was debated at least once this year by the town Council.
    -# 
     # http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html
    -# 
     
     # During a period WWII, summer time (Daylight saying) was mandatory in Canada.
     # In Creston, that was handled by shifting the area to PST (-8:00) then applying
    @@ -1917,7 +1880,7 @@ Zone America/Vancouver	-8:12:28 -	LMT	1884
     			-8:00	Canada	P%sT
     Zone America/Dawson_Creek -8:00:56 -	LMT	1884
     			-8:00	Canada	P%sT	1947
    -			-8:00	Vanc	P%sT	1972 Aug 30 2:00
    +			-8:00	Vanc	P%sT	1972 Aug 30  2:00
     			-7:00	-	MST
     Zone America/Creston	-7:46:04 -	LMT	1884
     			-7:00	-	MST	1916 Oct 1
    @@ -1944,18 +1907,17 @@ Zone America/Creston	-7:46:04 -	LMT	1884
     
     # From Rives McDow (1999-09-04):
     # Nunavut ... moved ... to incorporate the whole territory into one time zone.
    -# 
     # Nunavut moves to single time zone Oct. 31
    -# 
    +# http://www.nunatsiaq.com/nunavut/nvt90903_13.html
     #
     # From Antoine Leca (1999-09-06):
     # We then need to create a new timezone for the Kitikmeot region of Nunavut
     # to differentiate it from the Yellowknife region.
     
     # From Paul Eggert (1999-09-20):
    -# 
     # Basic Facts: The New Territory
    -#  (1999) reports that Pangnirtung operates on eastern time,
    +# http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html
    +# (1999) reports that Pangnirtung operates on eastern time,
     # and that Coral Harbour does not observe DST.  We don't know when
     # Pangnirtung switched to eastern time; we'll guess 1995.
     
    @@ -1983,8 +1945,8 @@ Zone America/Creston	-7:46:04 -	LMT	1884
     # the current state of affairs.
     
     # From Michaela Rodrigue, writing in the
    -# 
    -# Nunatsiaq News (1999-11-19):
    +# Nunatsiaq News (1999-11-19):
    +# http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html
     # Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
     # central - or Nunavut time - for government offices, and eastern time
     # for municipal offices and schools....  Igloolik [was similar but then]
    @@ -2002,10 +1964,8 @@ Zone America/Creston	-7:46:04 -	LMT	1884
     # Central Time and Southampton Island [in the Central zone] is not
     # required to use daylight savings.
     
    -# From
    -# 
    -# Nunavut now has two time zones
    -#  (2000-11-10):
    +# From 
    +# Nunavut now has two time zones (2000-11-10):
     # The Nunavut government would allow its employees in Kugluktuk and
     # Cambridge Bay to operate on central time year-round, putting them
     # one hour behind the rest of Nunavut for six months during the winter.
    @@ -2096,9 +2056,7 @@ Zone America/Creston	-7:46:04 -	LMT	1884
     # used to be the mayor of Resolute Bay and he apparently owns half the
     # businesses including "South Camp Inn." This website has some info on
     # Aziz:
    -# 
     # http://www.uphere.ca/node/493
    -# 
     #
     # I sent Aziz an e-mail asking when Resolute Bay had stopped using
     # Eastern Standard Time.
    @@ -2136,47 +2094,47 @@ Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     # aka Panniqtuuq
     Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
    -			-4:00	NT_YK	A%sT	1995 Apr Sun>=1 2:00
    -			-5:00	Canada	E%sT	1999 Oct 31 2:00
    -			-6:00	Canada	C%sT	2000 Oct 29 2:00
    +			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
    +			-5:00	Canada	E%sT	1999 Oct 31  2:00
    +			-6:00	Canada	C%sT	2000 Oct 29  2:00
     			-5:00	Canada	E%sT
     # formerly Frobisher Bay
     Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
    -			-5:00	NT_YK	E%sT	1999 Oct 31 2:00
    -			-6:00	Canada	C%sT	2000 Oct 29 2:00
    +			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
    +			-6:00	Canada	C%sT	2000 Oct 29  2:00
     			-5:00	Canada	E%sT
     # aka Qausuittuq
     Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
    -			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
    -			-5:00	-	EST	2001 Apr  1 3:00
    -			-6:00	Canada	C%sT	2006 Oct 29 2:00
    -			-5:00	-	EST	2007 Mar 11 3:00
    +			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
    +			-5:00	-	EST	2001 Apr  1  3:00
    +			-6:00	Canada	C%sT	2006 Oct 29  2:00
    +			-5:00	-	EST	2007 Mar 11  3:00
     			-6:00	Canada	C%sT
     # aka Kangiqiniq
     Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
    -			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
    -			-5:00	-	EST	2001 Apr  1 3:00
    +			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
    +			-5:00	-	EST	2001 Apr  1  3:00
     			-6:00	Canada	C%sT
     # aka Iqaluktuuttiaq
     Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
    -			-7:00	NT_YK	M%sT	1999 Oct 31 2:00
    -			-6:00	Canada	C%sT	2000 Oct 29 2:00
    -			-5:00	-	EST	2000 Nov  5 0:00
    -			-6:00	-	CST	2001 Apr  1 3:00
    +			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
    +			-6:00	Canada	C%sT	2000 Oct 29  2:00
    +			-5:00	-	EST	2000 Nov  5  0:00
    +			-6:00	-	CST	2001 Apr  1  3:00
     			-7:00	Canada	M%sT
     Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
     			-7:00	NT_YK	M%sT	1980
     			-7:00	Canada	M%sT
     Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
    -			-8:00	NT_YK	P%sT	1979 Apr lastSun 2:00
    +			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
     			-7:00	NT_YK	M%sT	1980
     			-7:00	Canada	M%sT
     Zone America/Whitehorse	-9:00:12 -	LMT	1900 Aug 20
    -			-9:00	NT_YK	Y%sT	1966 Jul 1 2:00
    +			-9:00	NT_YK	Y%sT	1966 Jul  1  2:00
     			-8:00	NT_YK	P%sT	1980
     			-8:00	Canada	P%sT
     Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
    -			-9:00	NT_YK	Y%sT	1973 Oct 28 0:00
    +			-9:00	NT_YK	Y%sT	1973 Oct 28  0:00
     			-8:00	NT_YK	P%sT	1980
     			-8:00	Canada	P%sT
     
    @@ -2188,9 +2146,8 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # From Paul Eggert (2001-03-05):
     # The Investigation and Analysis Service of the
     # Mexican Library of Congress (MLoC) has published a
    -# 
     # history of Mexican local time (in Spanish)
    -# .
    +# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
     #
     # Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
     # (In all cases we go with the MLoC.)
    @@ -2235,9 +2192,8 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # -------------- End Forwarded Message --------------
     # From Paul Eggert (1996-06-12):
     # For an English translation of the decree, see
    -# 
     # "Diario Oficial: Time Zone Changeover" (1996-01-04).
    -# 
    +# http://mexico-travel.com/extra/timezone_eng.html
     
     # From Rives McDow (1998-10-08):
     # The State of Quintana Roo has reverted back to central STD and DST times
    @@ -2249,7 +2205,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # savings time so as to stay on the same time zone as the southern part of
     # Arizona year round.
     
    -# From Jesper Norgaard, translating
    +# From Jesper Nørgaard, translating
     #  (2001-01-17):
     # In Oaxaca, the 55.000 teachers from the Section 22 of the National
     # Syndicate of Education Workers, refuse to apply daylight saving each
    @@ -2262,7 +2218,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
     # that Summer Time will be reduced from seven to five months, starting
     # this year....
    -# 
    +# http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001
     # [translated], says "summer time will ... take effect on the first Sunday
     # in May, and end on the last Sunday of September.
     
    @@ -2270,23 +2226,22 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # The 2001-01-24 traditional Washington Post contained the page one
     # story "Timely Issue Divides Mexicans."...
     # http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
    -# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
    +# ... Mexico City Mayor López Obrador "...is threatening to keep
     # Mexico City and its 20 million residents on a different time than
    -# the rest of the country..." In particular, Lopez Obrador would abolish
    +# the rest of the country..." In particular, López Obrador would abolish
     # observation of Daylight Saving Time.
     
    -# 
     # Official statute published by the Energy Department
    -#  (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
    -# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
    +# http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre
    +# (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
    +# and Sonora with no DST.  This was reported by Jesper Nørgaard (2001-02-03).
     
     # From Paul Eggert (2001-03-03):
     #
    -# 
    +# http://www.latimes.com/news/nation/20010303/t000018766.html
     # James F. Smith writes in today's LA Times
    -# 
     # * Sonora will continue to observe standard time.
    -# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
    +# * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
     #   the Federal District will not adopt DST.
     # * 4 of 16 district leaders announced they'll ignore the decree.
     # * The decree does not affect federal-controlled facilities including
    @@ -2294,7 +2249,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     #
     # For now we'll assume that the Federal District will bow to federal rules.
     
    -# From Jesper Norgaard (2001-04-01):
    +# From Jesper Nørgaard (2001-04-01):
     # I found some references to the Mexican application of daylight
     # saving, which modifies what I had already sent you, stating earlier
     # that a number of northern Mexican states would go on daylight
    @@ -2303,7 +2258,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # saving all year) will follow the original decree of president
     # Vicente Fox, starting daylight saving May 6, 2001 and ending
     # September 30, 2001.
    -# References: "Diario de Monterrey" 
    +# References: "Diario de Monterrey" 
     # Palabra  (2001-03-31)
     
     # From Reuters (2001-09-04):
    @@ -2315,7 +2270,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # standard time. "This is so residents of the Federal District are not
     # subject to unexpected time changes," a statement from the court said.
     
    -# From Jesper Norgaard Welen (2002-03-12):
    +# From Jesper Nørgaard Welen (2002-03-12):
     # ... consulting my local grocery store(!) and my coworkers, they all insisted
     # that a new decision had been made to reinstate US style DST in Mexico....
     # http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
    @@ -2329,48 +2284,36 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
     # > the United States.
     # Now this has passed both the Congress and the Senate, so starting from
     # 2010, some border regions will be the same:
    -# 
     # http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/
    -# 
    -# 
     # http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939
    -# 
     # (Spanish)
     #
     # Could not find the new law text, but the proposed law text changes are here:
    -# 
     # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf
    -# 
     # (Gaceta Parlamentaria)
     #
     # There is also a list of the votes here:
    -# 
     # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html
    -# 
     #
     # Our page:
    -# 
     # http://www.timeanddate.com/news/time/north-mexico-dst-change.html
    -# 
     
     # From Arthur David Olson (2010-01-20):
     # The page
    -# 
     # http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010
    -# 
     # includes this text:
     # En los municipios fronterizos de Tijuana y Mexicali en Baja California;
    -# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
    -# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
    -# Tamaulipas, la aplicación de este horario estacional surtirá efecto
    -# desde las dos horas del segundo domingo de marzo y concluirá a las dos
    +# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
    +# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
    +# Tamaulipas, la aplicación de este horario estacional surtirá efecto
    +# desde las dos horas del segundo domingo de marzo y concluirá a las dos
     # horas del primer domingo de noviembre.
     # En los municipios fronterizos que se encuentren ubicados en la franja
    -# fronteriza norte en el territorio comprendido entre la línea
    -# internacional y la línea paralela ubicada a una distancia de veinte
    -# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
    -# interior del país, la aplicación de este horario estacional surtirá
    -# efecto desde las dos horas del segundo domingo de marzo y concluirá a
    +# fronteriza norte en el territorio comprendido entre la línea
    +# internacional y la línea paralela ubicada a una distancia de veinte
    +# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
    +# interior del país, la aplicación de este horario estacional surtirá
    +# efecto desde las dos horas del segundo domingo de marzo y concluirá a
     # las dos horas del primer domingo de noviembre.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    @@ -2389,39 +2332,39 @@ Rule	Mexico	2001	only	-	Sep	lastSun	2:00	0	S
     Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
     Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -# Quintana Roo
    +# Quintana Roo; represented by Cancún
     Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
     			-6:00	-	CST	1981 Dec 23
     			-5:00	Mexico	E%sT	1998 Aug  2  2:00
     			-6:00	Mexico	C%sT
    -# Campeche, Yucatan
    +# Campeche, Yucatán; represented by Mérida
     Zone America/Merida	-5:58:28 -	LMT	1922 Jan  1  0:01:32
     			-6:00	-	CST	1981 Dec 23
     			-5:00	-	EST	1982 Dec  2
     			-6:00	Mexico	C%sT
    -# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border)
    +# Coahuila, Durango, Nuevo León, Tamaulipas (near US border)
     Zone America/Matamoros	-6:40:00 -	LMT	1921 Dec 31 23:20:00
     			-6:00	-	CST	1988
     			-6:00	US	C%sT	1989
     			-6:00	Mexico	C%sT	2010
     			-6:00	US	C%sT
    -# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border)
    +# Coahuila, Durango, Nuevo León, Tamaulipas (away from US border)
     Zone America/Monterrey	-6:41:16 -	LMT	1921 Dec 31 23:18:44
     			-6:00	-	CST	1988
     			-6:00	US	C%sT	1989
     			-6:00	Mexico	C%sT
     # Central Mexico
    -Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1 0:23:24
    +Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1  0:23:24
     			-7:00	-	MST	1927 Jun 10 23:00
     			-6:00	-	CST	1930 Nov 15
     			-7:00	-	MST	1931 May  1 23:00
     			-6:00	-	CST	1931 Oct
     			-7:00	-	MST	1932 Apr  1
    -			-6:00	Mexico	C%sT	2001 Sep 30 02:00
    +			-6:00	Mexico	C%sT	2001 Sep 30  2:00
     			-6:00	-	CST	2002 Feb 20
     			-6:00	Mexico	C%sT
     # Chihuahua (near US border)
    -Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
    +Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan  1  0:02:20
     			-7:00	-	MST	1927 Jun 10 23:00
     			-6:00	-	CST	1930 Nov 15
     			-7:00	-	MST	1931 May  1 23:00
    @@ -2429,7 +2372,7 @@ Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
     			-7:00	-	MST	1932 Apr  1
     			-6:00	-	CST	1996
     			-6:00	Mexico	C%sT	1998
    -			-6:00	-	CST	1998 Apr Sun>=1 3:00
    +			-6:00	-	CST	1998 Apr Sun>=1  3:00
     			-7:00	Mexico	M%sT	2010
     			-7:00	US	M%sT
     # Chihuahua (away from US border)
    @@ -2441,7 +2384,7 @@ Zone America/Chihuahua	-7:04:20 -	LMT	1921 Dec 31 23:55:40
     			-7:00	-	MST	1932 Apr  1
     			-6:00	-	CST	1996
     			-6:00	Mexico	C%sT	1998
    -			-6:00	-	CST	1998 Apr Sun>=1 3:00
    +			-6:00	-	CST	1998 Apr Sun>=1  3:00
     			-7:00	Mexico	M%sT
     # Sonora
     Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
    @@ -2457,42 +2400,33 @@ Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
     			-7:00	-	MST
     
     # From Alexander Krivenyshev (2010-04-21):
    -# According to news, Bahía de Banderas (Mexican state of Nayarit)
    +# According to news, Bahía de Banderas (Mexican state of Nayarit)
     # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
     # share the same time zone as nearby city Puerto Vallarta, Jalisco).
     #
     # (Spanish)
    -# Bahía de Banderas homologa su horario al del centro del
    -# país, a partir de este domingo
    -# 
    +# Bahía de Banderas homologa su horario al del centro del
    +# país, a partir de este domingo
     # http://www.nayarit.gob.mx/notes.asp?id=20748
    -# 
     #
    -# Bahía de Banderas homologa su horario con el del Centro del
    -# País
    -# 
    -# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
    -# 
    +# Bahía de Banderas homologa su horario con el del Centro del
    +# País
    +# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50
     #
     # (English)
    -# Puerto Vallarta and Bahía de Banderas: One Time Zone
    -# 
    +# Puerto Vallarta and Bahía de Banderas: One Time Zone
     # http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
    -# 
    -#
    -# or
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
    -# 
     #
     # "Mexico's Senate approved the amendments to the Mexican Schedule System that
    -# will allow Bahía de Banderas and Puerto Vallarta to share the same time
    +# will allow Bahía de Banderas and Puerto Vallarta to share the same time
     # zone ..."
     # Baja California Sur, Nayarit, Sinaloa
     
     # From Arthur David Olson (2010-05-01):
     # Use "Bahia_Banderas" to keep the name to fourteen characters.
     
    +# Mazatlán
     Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
     			-7:00	-	MST	1927 Jun 10 23:00
     			-6:00	-	CST	1930 Nov 15
    @@ -2504,6 +2438,7 @@ Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
     			-8:00	-	PST	1970
     			-7:00	Mexico	M%sT
     
    +# Bahía de Banderas
     Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
     			-7:00	-	MST	1927 Jun 10 23:00
     			-6:00	-	CST	1930 Nov 15
    @@ -2513,7 +2448,7 @@ Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
     			-6:00	-	CST	1942 Apr 24
     			-7:00	-	MST	1949 Jan 14
     			-8:00	-	PST	1970
    -			-7:00	Mexico	M%sT	2010 Apr 4 2:00
    +			-7:00	Mexico	M%sT	2010 Apr  4  2:00
     			-6:00	Mexico	C%sT
     
     # Baja California (near US border)
    @@ -2560,7 +2495,7 @@ Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
     # America/Tijuana only in that it did not observe DST from 1976
     # through 1995.  This was as per Shanks (1999).  But Shanks & Pottenger say
     # Ensenada did not observe DST from 1948 through 1975.  Guy Harris reports
    -# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
    +# that the 1987 OAG says "Only Ensenada, Mexicali, San Felipe and
     # Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
     # DST-observance was a town-by-town matter back then.  This concerns
     # data after 1970 so most likely there should be at least one Zone
    @@ -2573,7 +2508,7 @@ Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
     ###############################################################################
     
     # Anguilla
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
     
     # Antigua and Barbuda
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    @@ -2609,8 +2544,8 @@ Rule	Barb	1978	1980	-	Apr	Sun>=15	2:00	1:00	D
     Rule	Barb	1979	only	-	Sep	30	2:00	0	S
     Rule	Barb	1980	only	-	Sep	25	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/Barbados	-3:58:29 -	LMT	1924		# Bridgetown
    -			-3:58:29 -	BMT	1932	  # Bridgetown Mean Time
    +Zone America/Barbados	-3:58:29 -	LMT	1924 # Bridgetown
    +			-3:58:29 -	BMT	1932 # Bridgetown Mean Time
     			-4:00	Barb	A%sT
     
     # Belize
    @@ -2640,20 +2575,20 @@ Zone	America/Belize	-5:52:48 -	LMT	1912 Apr
     # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1 2:00    # Hamilton
    -			-4:00	-	AST	1974 Apr 28 2:00
    +Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1  2:00 # Hamilton
    +			-4:00	-	AST	1974 Apr 28  2:00
     			-4:00	Canada	A%sT	1976
     			-4:00	US	A%sT
     
     # Cayman Is
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	America/Cayman	-5:25:32 -	LMT	1890		# Georgetown
    -			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
    +Zone	America/Cayman	-5:25:32 -	LMT	1890     # Georgetown
    +			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
     			-5:00	-	EST
     
     # Costa Rica
     
    -# Milne gives -5:36:13.3 as San Jose mean time; round to nearest.
    +# Milne gives -5:36:13.3 as San José mean time; round to nearest.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	CR	1979	1980	-	Feb	lastSun	0:00	1:00	D
    @@ -2663,10 +2598,10 @@ Rule	CR	1991	1992	-	Jan	Sat>=15	0:00	1:00	D
     # go with Shanks & Pottenger.
     Rule	CR	1991	only	-	Jul	 1	0:00	0	S
     Rule	CR	1992	only	-	Mar	15	0:00	0	S
    -# There are too many San Joses elsewhere, so we'll use 'Costa Rica'.
    +# There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
    -			-5:36:13 -	SJMT	1921 Jan 15 # San Jose Mean Time
    +Zone America/Costa_Rica	-5:36:13 -	LMT	1890        # San José
    +			-5:36:13 -	SJMT	1921 Jan 15 # San José Mean Time
     			-6:00	CR	C%sT
     # Coco
     # no information; probably like America/Costa_Rica
    @@ -2685,8 +2620,8 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # During the game, play-by-play announcer Jim Hunter noted that
     # "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
     # Time today."  (The "two hour" remark referred to losing one hour of
    -# sleep on 1999-03-28--when the announcers were in Cuba as it switched
    -# to DST--and one more hour on 1999-04-04--when the announcers will have
    +# sleep on 1999-03-28 - when the announcers were in Cuba as it switched
    +# to DST - and one more hour on 1999-04-04 - when the announcers will have
     # returned to Baltimore, which switches on that date.)
     
     # From Steffen Thorsen (2013-11-11):
    @@ -2708,16 +2643,16 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # adjustment in Cuba.  We will stay in daylight saving time:
     # http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
     
    -# From Jesper Norgaard Welen (2006-10-21):
    +# From Jesper Nørgaard Welen (2006-10-21):
     # An article in GRANMA INTERNACIONAL claims that Cuba will end
     # the 3 years of permanent DST next weekend, see
     # http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
     # "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
    -# watches should be set back one hour -- going back to 00:00 hours -- returning
    +# watches should be set back one hour - going back to 00:00 hours - returning
     # to the normal schedule....
     
     # From Paul Eggert (2007-03-02):
    -# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
    +# , dated yesterday,
     # says Cuban clocks will advance at midnight on March 10.
     # For lack of better information, assume Cuba will use US rules,
     # except that it switches at midnight standard time as usual.
    @@ -2731,10 +2666,10 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
     # http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
     #
    -# From Alex Kryvenishev (2007-10-25):
    +# From Alex Krivenyshev (2007-10-25):
     # Here is also article from Granma (Cuba):
     #
    -# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
    +# Regirá el Horario Normal desde el próximo domingo 28 de octubre
     # http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
     #
     # http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
    @@ -2742,23 +2677,18 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # From Arthur David Olson (2008-03-09):
     # I'm in Maryland which is now observing United States Eastern Daylight
     # Time. At 9:44 local time I used RealPlayer to listen to
    -# 
     # http://media.enet.cu/radioreloj
    -# , a Cuban information station, and heard
    +# a Cuban information station, and heard
     # the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
     # indicating that Cuba is still on standard time.
     
     # From Steffen Thorsen (2008-03-12):
     # It seems that Cuba will start DST on Sunday, 2007-03-16...
     # It was announced yesterday, according to this source (in Spanish):
    -# 
     # http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
    -# 
     #
     # Some more background information is posted here:
    -# 
     # http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
    -# 
     #
     # The article also says that Cuba has been observing DST since 1963,
     # while Shanks (and tzdata) has 1965 as the first date (except in the
    @@ -2768,18 +2698,14 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # change some historic records as well.
     #
     # One example:
    -# 
     # http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
    -# 
     
    -# From Jesper Norgaard Welen (2008-03-13):
    +# From Jesper Nørgaard Welen (2008-03-13):
     # The Cuban time change has just been confirmed on the most authoritative
     # web site, the Granma.  Please check out
    -# 
     # http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
    -# 
     #
    -# Basically as expected after Steffen Thorsens information, the change
    +# Basically as expected after Steffen Thorsen's information, the change
     # will take place midnight between Saturday and Sunday.
     
     # From Arthur David Olson (2008-03-12):
    @@ -2790,18 +2716,14 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
     # not on midnight March 14 / March 15 as previously thought.
     #
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
     # (in Spanish)
    -# 
     
     # From Arthur David Olson (2009-03-09)
     # I listened over the Internet to
    -# 
     # http://media.enet.cu/readioreloj
    -# 
     # this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
    -# the time was announced as "diez cinco"--the same time as here, indicating
    +# the time was announced as "diez cinco" - the same time as here, indicating
     # that has indeed switched to DST. Assume second Sunday from 2009 forward.
     
     # From Steffen Thorsen (2011-03-08):
    @@ -2810,42 +2732,30 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
     # changed at all).
     #
     # Source:
    -# 
     # http://granma.co.cu/2011/03/08/nacional/artic01.html
    -# 
     #
     # Our info:
    -# 
     # http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html
    -# 
     #
     # From Steffen Thorsen (2011-10-30)
     # Cuba will end DST two weeks later this year. Instead of going back
     # tonight, it has been delayed to 2011-11-13 at 01:00.
     #
     # One source (Spanish)
    -# 
     # http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html
    -# 
     #
     # Our page:
    -# 
     # http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
    -# 
     #
     # From Steffen Thorsen (2012-03-01)
     # According to Radio Reloj, Cuba will start DST on Midnight between March
     # 31 and April 1.
     #
     # Radio Reloj has the following info (Spanish):
    -# 
     # http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
    -# 
     #
     # Our info on it:
    -# 
     # http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
    -# 
     
     # From Steffen Thorsen (2012-11-03):
     # Radio Reloj and many other sources report that Cuba is changing back
    @@ -2901,7 +2811,7 @@ Zone	America/Havana	-5:29:28 -	LMT	1890
     			-5:00	Cuba	C%sT
     
     # Dominica
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
     
     # Dominican Republic
     
    @@ -2934,8 +2844,8 @@ Rule	DR	1972	1974	-	Jan	21	0:00	0	S
     Zone America/Santo_Domingo -4:39:36 -	LMT	1890
     			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
     			-5:00	DR	E%sT	1974 Oct 27
    -			-4:00	-	AST	2000 Oct 29 02:00
    -			-5:00	US	E%sT	2000 Dec  3 01:00
    +			-4:00	-	AST	2000 Oct 29  2:00
    +			-5:00	US	E%sT	2000 Dec  3  1:00
     			-4:00	-	AST
     
     # El Salvador
    @@ -2946,20 +2856,20 @@ Rule	Salv	1987	1988	-	Sep	lastSun	0:00	0	S
     # There are too many San Salvadors elsewhere, so use America/El_Salvador
     # instead of America/San_Salvador.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
    +Zone America/El_Salvador -5:56:48 -	LMT	1921 # San Salvador
     			-6:00	Salv	C%sT
     
     # Grenada
     # Guadeloupe
    -# St Barthelemy
    +# St Barthélemy
     # St Martin (French part)
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
     
     # Guatemala
     #
     # From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
     # Diario Co Latino, at
    -# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
    +# ,
     # says in an article dated 2006-04-19 that the Guatemalan government had
     # decided on that date to advance official time by 60 minutes, to lessen the
     # impact of the elevated cost of oil....  Daylight saving time will last from
    @@ -2967,7 +2877,7 @@ Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
     # From Paul Eggert (2006-06-22):
     # The Ministry of Energy and Mines, press release CP-15/2006
     # (2006-04-19), says DST ends at 24:00.  See
    -# .
    +# http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
     Rule	Guat	1973	only	-	Nov	25	0:00	1:00	D
    @@ -2984,11 +2894,10 @@ Zone America/Guatemala	-6:02:04 -	LMT	1918 Oct 5
     
     # Haiti
     # From Gwillim Law (2005-04-15):
    -# Risto O. Nykanen wrote me that Haiti is now on DST.
    -# I searched for confirmation, and I found a
    -#  press release
    +# Risto O. Nykänen wrote me that Haiti is now on DST.
    +# I searched for confirmation, and I found a press release
     # on the Web page of the Haitian Consulate in Chicago (2005-03-31),
    -# .  Translated from French, it says:
    +# .  Translated from French, it says:
     #
     #  "The Prime Minister's Communication Office notifies the public in general
     #   and the press in particular that, following a decision of the Interior
    @@ -3065,14 +2974,14 @@ Zone America/Port-au-Prince -4:49:20 -	LMT	1890
     #  that Manuel Zelaya, the president
     # of Honduras, refused to back down on this.
     
    -# From Jesper Norgaard Welen (2006-08-08):
    +# From Jesper Nørgaard Welen (2006-08-08):
     # It seems that Honduras has returned from DST to standard time this Monday at
     # 00:00 hours (prolonging Sunday to 25 hours duration).
     # http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
     
     # From Paul Eggert (2006-08-08):
    -# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
    -# .
    +# Also see Diario El Heraldo, The country returns to standard time (2006-08-08).
    +# http://www.elheraldo.hn/nota.php?nid=54941&sec=12
     # It mentions executive decree 18-2006.
     
     # From Steffen Thorsen (2006-08-17):
    @@ -3100,22 +3009,22 @@ Zone America/Tegucigalpa -5:48:52 -	LMT	1921 Apr
     # unspecified official document, and says "This time is used throughout the
     # island".  Go with Milne.  Round to the nearest second as required by zic.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	America/Jamaica	-5:07:11 -	LMT	1890		# Kingston
    +Zone	America/Jamaica	-5:07:11 -	LMT	1890        # Kingston
     			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
    -			-5:00	-	EST	1974 Apr 28 2:00
    +			-5:00	-	EST	1974 Apr 28  2:00
     			-5:00	US	E%sT	1984
     			-5:00	-	EST
     
     # Martinique
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
    -			-4:04:20 -	FFMT	1911 May     # Fort-de-France MT
    +Zone America/Martinique	-4:04:20 -      LMT	1890        # Fort-de-France
    +			-4:04:20 -	FFMT	1911 May    # Fort-de-France MT
     			-4:00	-	AST	1980 Apr  6
     			-4:00	1:00	ADT	1980 Sep 28
     			-4:00	-	AST
     
     # Montserrat
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
     
     # Nicaragua
     #
    @@ -3138,27 +3047,27 @@ Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
     # From Gwillim Law (2005-04-21):
     # The Associated Press story on the time change, which can be found at
     # http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
    -# and elsewhere, says (fifth paragraph, translated from Spanish):  "The last
    +# and elsewhere, says (fifth paragraph, translated from Spanish): "The last
     # time that a change of clocks was applied to save energy was in the year 2000
    -# during the Arnoldo Aleman administration."...
    +# during the Arnoldo Alemán administration."...
     # The northamerica file says that Nicaragua has been on UTC-6 continuously
     # since December 1998.  I wasn't able to find any details of Nicaraguan time
     # changes in 2000.  Perhaps a note could be added to the northamerica file, to
     # the effect that we have indirect evidence that DST was observed in 2000.
     #
    -# From Jesper Norgaard Welen (2005-11-02):
    +# From Jesper Nørgaard Welen (2005-11-02):
     # Nicaragua left DST the 2005-10-02 at 00:00 (local time).
     # http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
     # (2005-09-26)
     #
    -# From Jesper Norgaard Welen (2006-05-05):
    +# From Jesper Nørgaard Welen (2006-05-05):
     # http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
     # (my informal translation)
    -# By order of the president of the republic, Enrique Bolanos, Nicaragua
    +# By order of the president of the republic, Enrique Bolaños, Nicaragua
     # advanced by sixty minutes their official time, yesterday at 2 in the
    -# morning, and will stay that way until 30.th. of september.
    +# morning, and will stay that way until 30th of September.
     #
    -# From Jesper Norgaard Welen (2006-09-30):
    +# From Jesper Nørgaard Welen (2006-09-30):
     # http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
     # My informal translation runs:
     # The natural sun time is restored in all the national territory, in that the
    @@ -3176,7 +3085,7 @@ Zone	America/Managua	-5:45:08 -	LMT	1890
     			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
     			-6:00	-	CST	1973 May
     			-5:00	-	EST	1975 Feb 16
    -			-6:00	Nic	C%sT	1992 Jan  1 4:00
    +			-6:00	Nic	C%sT	1992 Jan  1  4:00
     			-5:00	-	EST	1992 Sep 24
     			-6:00	-	CST	1993
     			-5:00	-	EST	1997
    @@ -3185,36 +3094,36 @@ Zone	America/Managua	-5:45:08 -	LMT	1890
     # Panama
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	America/Panama	-5:18:08 -	LMT	1890
    -			-5:19:36 -	CMT	1908 Apr 22   # Colon Mean Time
    +			-5:19:36 -	CMT	1908 Apr 22 # Colón Mean Time
     			-5:00	-	EST
     
     # Puerto Rico
     # There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00    # San Juan
    +Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00 # San Juan
     			-4:00	-	AST	1942 May  3
     			-4:00	US	A%sT	1946
     			-4:00	-	AST
     
     # St Kitts-Nevis
     # St Lucia
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
     
     # St Pierre and Miquelon
     # There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
    +Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15 # St Pierre
     			-4:00	-	AST	1980 May
     			-3:00	-	PMST	1987 # Pierre & Miquelon Time
     			-3:00	Canada	PM%sT
     
     # St Vincent and the Grenadines
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
     
     # Turks and Caicos
     #
     # From Chris Dunn in
    -# 
    +# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007
     # (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
     # daylight saving dates for time changes have been adjusted to match
     # the recent U.S. change of dates.
    @@ -3227,21 +3136,23 @@ Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
     # Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
     # indicating that the normal ET rules are followed.
     #
    -# From Paul Eggert (2006-05-01):
    -# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
    -# says they switch at midnight.  Go with Shanks & Pottenger.
    +# From Paul Eggert (2014-08-19):
    +# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round.  See:
    +# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
    +# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
     #
    -# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	TC	1979	1986	-	Apr	lastSun	2:00	1:00	D
    -Rule	TC	1979	2006	-	Oct	lastSun	2:00	0	S
    -Rule	TC	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
    -Rule	TC	2007	max	-	Mar	Sun>=8	2:00	1:00	D
    -Rule	TC	2007	max	-	Nov	Sun>=1	2:00	0	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Grand_Turk	-4:44:32 -	LMT	1890
    -			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
    -			-5:00	TC	E%sT
    +			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
    +			-5:00	-	EST	1979
    +			-5:00	US	E%sT	2014 Nov  2  2:00
    +			-4:00	-	AST
     
     # British Virgin Is
     # Virgin Is
    -# See 'southamerica'.
    +# See America/Port_of_Spain.
    +
    +
    +# Local Variables:
    +# coding: utf-8
    +# End:
    diff --git a/test/sun/util/calendar/zi/tzdata/pacificnew b/test/sun/util/calendar/zi/tzdata/pacificnew
    index 09000c3457a9333a19a8207c57644cfc4d117621..9b9257a45fea207e960f5745b24e8a816be16e9d 100644
    --- a/test/sun/util/calendar/zi/tzdata/pacificnew
    +++ b/test/sun/util/calendar/zi/tzdata/pacificnew
    @@ -21,7 +21,6 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    diff --git a/test/sun/util/calendar/zi/tzdata/southamerica b/test/sun/util/calendar/zi/tzdata/southamerica
    index 02bf3bb633268d7eb403183746a3b44e21888aca..398ec0e4f064f68105ed43bd50f56f479a59d1eb 100644
    --- a/test/sun/util/calendar/zi/tzdata/southamerica
    +++ b/test/sun/util/calendar/zi/tzdata/southamerica
    @@ -21,13 +21,13 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    -# This data is by no means authoritative; if you think you know better,
    +# This file is by no means authoritative; if you think you know better,
     # go ahead and edit the file (and please send any changes to
    -# tz@iana.org for general use in the future).
    +# tz@iana.org for general use in the future).  For more, please see
    +# the file CONTRIBUTING in the tz distribution.
     
     # From Paul Eggert (2006-03-22):
     # A good source for time zone historical data outside the U.S. is
    @@ -35,8 +35,8 @@
     # San Diego: ACS Publications, Inc. (2003).
     #
     # For data circa 1899, a common source is:
    -# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
    -# .
    +# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
    +# http://www.jstor.org/stable/1774359
     #
     # Gwillim Law writes that a good source
     # for recent time zone data is the International Air Transport
    @@ -53,24 +53,24 @@
     #	I suggest the use of _Summer time_ instead of the more cumbersome
     #	_daylight-saving time_.  _Summer time_ seems to be in general use
     #	in Europe and South America.
    -#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
    +#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
     #	H L Mencken, _The American Language: Supplement I_ (1960), p 466
     #
     # Earlier editions of these tables also used the North American style
     # for time zones in Brazil, but this was incorrect, as Brazilians say
    -# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
    +# "summer time".  Reinaldo Goulart, a São Paulo businessman active in
     # the railroad sector, writes (1999-07-06):
     #	The subject of time zones is currently a matter of discussion/debate in
    -#	Brazil.  Let's say that "the Brasilia time" is considered the
    -#	"official time" because Brasilia is the capital city.
    -#	The other three time zones are called "Brasilia time "minus one" or
    +#	Brazil.  Let's say that "the Brasília time" is considered the
    +#	"official time" because Brasília is the capital city.
    +#	The other three time zones are called "Brasília time "minus one" or
     #	"plus one" or "plus two".  As far as I know there is no such
     #	name/designation as "Eastern Time" or "Central Time".
     # So I invented the following (English-language) abbreviations for now.
     # Corrections are welcome!
     #		std	dst
     #	-2:00	FNT	FNST	Fernando de Noronha
    -#	-3:00	BRT	BRST	Brasilia
    +#	-3:00	BRT	BRST	Brasília
     #	-4:00	AMT	AMST	Amazon
     #	-5:00	ACT	ACST	Acre
     
    @@ -84,7 +84,7 @@
     # Argentina: first Sunday in October to first Sunday in April since 1976.
     # Double Summer time from 1969 to 1974.  Switches at midnight.
     
    -# From U. S. Naval Observatory (1988-01-199):
    +# From U. S. Naval Observatory (1988-01-19):
     # ARGENTINA           3 H BEHIND   UTC
     
     # From Hernan G. Otero (1995-06-26):
    @@ -118,7 +118,7 @@ Rule	Arg	1988	only	-	Dec	 1	0:00	1:00	S
     # From Hernan G. Otero (1995-06-26):
     # These corrections were contributed by InterSoft Argentina S.A.,
     # obtaining the data from the:
    -# Talleres de Hidrografia Naval Argentina
    +# Talleres de Hidrografía Naval Argentina
     # (Argentine Naval Hydrography Institute)
     Rule	Arg	1989	1993	-	Mar	Sun>=1	0:00	0	-
     Rule	Arg	1989	1992	-	Oct	Sun>=15	0:00	1:00	S
    @@ -140,13 +140,13 @@ Rule	Arg	1999	only	-	Oct	Sun>=1	0:00	1:00	S
     Rule	Arg	2000	only	-	Mar	3	0:00	0	-
     #
     # From Peter Gradelski via Steffen Thorsen (2000-03-01):
    -# We just checked with our Sao Paulo office and they say the government of
    +# We just checked with our São Paulo office and they say the government of
     # Argentina decided not to become one of the countries that go on or off DST.
     # So Buenos Aires should be -3 hours from GMT at all times.
     #
    -# From Fabian L. Arce Jofre (2000-04-04):
    +# From Fabián L. Arce Jofré (2000-04-04):
     # The law that claimed DST for Argentina was derogated by President Fernando
    -# de la Rua on March 2, 2000, because it would make people spend more energy
    +# de la Rúa on March 2, 2000, because it would make people spend more energy
     # in the winter time, rather than less.  The change took effect on March 3.
     #
     # From Mariano Absatz (2001-06-06):
    @@ -179,15 +179,13 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
     # that Argentina will use DST next year as well, from October to
     # March, although exact rules are not given.
     #
    -# From Jesper Norgaard Welen (2007-12-26)
    +# From Jesper Nørgaard Welen (2007-12-26)
     # The last hurdle of Argentina DST is over, the proposal was approved in
    -# the lower chamber too (Deputados) with a vote 192 for and 2 against.
    +# the lower chamber too (Diputados) with a vote 192 for and 2 against.
     # By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
     # the original scanned proposal, where the dates and the zero hours are
     # clear and unambiguous...This is the article about final approval:
    -# 
     # http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
    -# 
     #
     # From Paul Eggert (2007-12-22):
     # For dates after mid-2008, the following rules are my guesses and
    @@ -197,13 +195,8 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
     # As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
     # Argentina will start DST on Sunday October 19, 2008.
     #
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
    -# 
    -# OR
    -# 
     # http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
    -# 
     
     # From Rodrigo Severo (2008-10-06):
     # Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
    @@ -212,48 +205,39 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
     # Hi, there is a problem with timezone-data-2008e and maybe with
     # timezone-data-2008f
     # Argentinian law [Number] 25.155 is no longer valid.
    -# 
     # http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
    -# 
     # The new one is law [Number] 26.350
    -# 
     # http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
    -# 
     # So there is no summer time in Argentina for now.
     
     # From Mariano Absatz (2008-10-20):
    -# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina
    -# From 2008-10-19 until 2009-03-15
    -# 
    +# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST
    +# in Argentina from 2008-10-19 until 2009-03-15.
     # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01
    -# 
     #
    -# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009:
    -# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz
    -# and Tierra del Fuego
    -# 
    +
    +# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer
    +# 2008/2009: Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La
    +# Pampa, Neuquén, Rio Negro, Chubut, Santa Cruz and Tierra del Fuego
     # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01
    -# 
     #
    -# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying
    -# it will not apply DST either (even when it was not included in Decree 1705/2008)
    -# 
    +# Press release 235 dated Saturday October 18th, from the Government of the
    +# Province of Jujuy saying it will not apply DST either (even when it was not
    +# included in Decree 1705/2008).
     # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
    -# 
     
     # From fullinet (2009-10-18):
     # As announced in
    -# 
     # http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
    -# 
    -# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
    +# (an official .gob.ar) under title: "Sin Cambio de Hora"
    +# (English: "No hour change").
     #
    -# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
    -# oficial, decision que estaba en estudio para su implementacion el
    -# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
    -# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
    -# la modificacion del huso horario, ya que 2009 nos encuentra con
    -# crecimiento en la produccion y distribucion energetica."
    +# "Por el momento, el Gobierno Nacional resolvió no modificar la hora
    +# oficial, decisión que estaba en estudio para su implementación el
    +# domingo 18 de octubre. Desde el Ministerio de Planificación se anunció
    +# que la Argentina hoy, en estas condiciones meteorológicas, no necesita
    +# la modificación del huso horario, ya que 2009 nos encuentra con
    +# crecimiento en la producción y distribución energética."
     
     Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
     Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
    @@ -267,10 +251,10 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # It's Law No. 7,210.  This change is due to a public power emergency, so for
     # now we'll assume it's for this year only.
     #
    -# From Paul Eggert (2006-03-22):
    -# 
    -# Hora de verano para la Republica Argentina (2003-06-08)
    -#  says that standard time in Argentina from 1894-10-31
    +# From Paul Eggert (2014-08-09):
    +# Hora de verano para la República Argentina
    +# http://buenasiembra.com.ar/esoterismo/astrologia/hora-de-verano-de-la-republica-argentina-27.html
    +# says that standard time in Argentina from 1894-10-31
     # to 1920-05-01 was -4:16:48.25.  Go with this more-precise value
     # over Shanks & Pottenger.
     #
    @@ -285,10 +269,10 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # time in October 17th.
     #
     # Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
    -# Tierra del Fuego, Tucuman.
    +# Tierra del Fuego, Tucumán.
     #
     # From Mariano Absatz (2004-06-14):
    -# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
    +# ... this weekend, the Province of Tucumán decided it'd go back to UTC-03:00
     # yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
     # annoyance with the change is much higher than the power savings obtained....
     #
    @@ -323,49 +307,38 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # Here are articles that Argentina Province San Luis is planning to end DST
     # as earlier as upcoming Monday January 21, 2008 or February 2008:
     #
    -# Provincia argentina retrasa reloj y marca diferencia con resto del pais
    +# Provincia argentina retrasa reloj y marca diferencia con resto del país
     # (Argentine Province delayed clock and mark difference with the rest of the
     # country)
    -# 
     # http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
    -# 
     #
     # Es inminente que en San Luis atrasen una hora los relojes
     # (It is imminent in San Luis clocks one hour delay)
    -# 
    -# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
    -# 
    -#
    -# 
    +# http://www.lagaceta.com.ar/nota/253414/Economia/Es-inminente-que-en-San-Luis-atrasen-una-hora-los-relojes.html
     # http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
    -# 
     
    -# From Jesper Norgaard Welen (2008-01-18):
    +# From Jesper Nørgaard Welen (2008-01-18):
     # The page of the San Luis provincial government
    -# 
     # http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
    -# 
     # confirms what Alex Krivenyshev has earlier sent to the tz
     # emailing list about that San Luis plans to return to standard
     # time much earlier than the rest of the country. It also
     # confirms that upon request the provinces San Juan and Mendoza
     # refused to follow San Luis in this change.
     #
    -# The change is supposed to take place Monday the 21.st at 0:00
    +# The change is supposed to take place Monday the 21st at 0:00
     # hours. As far as I understand it if this goes ahead, we need
     # a new timezone for San Luis (although there are also documented
     # independent changes in the southamerica file of San Luis in
     # 1990 and 1991 which has not been confirmed).
     
    -# From Jesper Norgaard Welen (2008-01-25):
    +# From Jesper Nørgaard Welen (2008-01-25):
     # Unfortunately the below page has become defunct, about the San Luis
     # time change. Perhaps because it now is part of a group of pages "Most
     # important pages of 2008."
     #
     # You can use
    -# 
     # http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
    -# 
     # instead it seems. Or use "Buscador" from the main page of the San Luis
     # government, and fill in "huso" and click OK, and you will get 3 pages
     # from which the first one is identical to the above.
    @@ -385,9 +358,9 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # back in 2004, when these provinces changed to UTC-4 for a few days, I
     # mailed them personally and never got an answer).
     
    -# From Paul Eggert (2008-06-30):
    -# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
    -# from the IATA otherwise.  As noted below, Shanks & Pottenger say that
    +# From Paul Eggert (2014-08-12):
    +# Unless otherwise specified, data entries are from Shanks & Pottenger through
    +# 1992, from the IATA otherwise.  As noted below, Shanks & Pottenger say that
     # America/Cordoba split into 6 subregions during 1991/1992, one of which
     # was America/San_Luis, but we haven't verified this yet so for now we'll
     # keep America/Cordoba a single region rather than splitting it into the
    @@ -399,14 +372,9 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # to utc-04:00 until the second Saturday in October...
     #
     # The press release is at
    -# 
     # http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
    -# 
    -# (I couldn't find the decree, but
    -# 
    -# www.sanluis.gov.ar
    -# 
    -# is the official page for the Province Government).
    +# (I couldn't find the decree, but www.sanluis.gov.ar
    +# is the official page for the Province Government.)
     #
     # There's also a note in only one of the major national papers ...
     # http://www.lanacion.com.ar/nota.asp?nota_id=1107912
    @@ -423,9 +391,7 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # ...the Province of San Luis is a case in itself.
     #
     # The Law at
    -# 
     # is ambiguous because establishes a calendar from the 2nd Sunday in
     # October at 0:00 thru the 2nd Saturday in March at 24:00 and the
     # complement of that starting on the 2nd Sunday of March at 0:00 and
    @@ -454,19 +420,15 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # ...
     
     # From Alexander Krivenyshev (2010-04-09):
    -# According to news reports from El Diario de la Republica Province San
    +# According to news reports from El Diario de la República Province San
     # Luis, Argentina (standard time UTC-04) will keep Daylight Saving Time
    -# after April 11, 2010--will continue to have same time as rest of
    +# after April 11, 2010 - will continue to have same time as rest of
     # Argentina (UTC-3) (no DST).
     #
    -# Confirmaron la prórroga del huso horario de verano (Spanish)
    -# 
    +# Confirmaron la prórroga del huso horario de verano (Spanish)
     # http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9
    -# 
     # or (some English translation):
    -# 
     # http://www.worldtimezone.com/dst_news/dst_news_argentina08.html
    -# 
     
     # From Mariano Absatz (2010-04-12):
     # yes...I can confirm this...and given that San Luis keeps calling
    @@ -478,7 +440,7 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # Perhaps San Luis operates on the legal fiction that it is at UTC-4
     # with perpetual summer time, but ordinary usage typically seems to
     # just say it's at UTC-3; see, for example,
    -# .
    +# http://es.wikipedia.org/wiki/Hora_oficial_argentina
     # We've documented similar situations as being plain changes to
     # standard time, so let's do that here too.  This does not change UTC
     # offsets, only tm_isdst and the time zone abbreviations.  One minor
    @@ -486,20 +448,20 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
     # setting for time stamps past 2038.
     
     # From Paul Eggert (2013-02-21):
    -# Milne says Cordoba time was -4:16:48.2.  Round to the nearest second.
    +# Milne says Córdoba time was -4:16:48.2.  Round to the nearest second.
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     #
     # Buenos Aires (BA), Capital Federal (CF),
    -Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
    -			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
    +Zone America/Argentina/Buenos_Aires -3:53:48 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
     			-4:00	-	ART	1930 Dec
     			-4:00	Arg	AR%sT	1969 Oct  5
     			-3:00	Arg	AR%sT	1999 Oct  3
     			-4:00	Arg	AR%sT	2000 Mar  3
     			-3:00	Arg	AR%sT
     #
    -# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN),
    +# Córdoba (CB), Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN),
     # Chaco (CC), Formosa (FM), Santiago del Estero (SE)
     #
     # Shanks & Pottenger also make the following claims, which we haven't verified:
    @@ -519,7 +481,7 @@ Zone America/Argentina/Cordoba -4:16:48 - LMT	1894 Oct 31
     			-4:00	Arg	AR%sT	2000 Mar  3
     			-3:00	Arg	AR%sT
     #
    -# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
    +# Salta (SA), La Pampa (LP), Neuquén (NQ), Rio Negro (RN)
     Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
     			-4:16:48 -	CMT	1920 May
     			-4:00	-	ART	1930 Dec
    @@ -531,7 +493,7 @@ Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
     			-3:00	Arg	AR%sT	2008 Oct 18
     			-3:00	-	ART
     #
    -# Tucuman (TM)
    +# Tucumán (TM)
     Zone America/Argentina/Tucuman -4:20:52 - LMT	1894 Oct 31
     			-4:16:48 -	CMT	1920 May
     			-4:00	-	ART	1930 Dec
    @@ -642,8 +604,8 @@ Zone America/Argentina/San_Luis -4:25:24 - LMT	1894 Oct 31
     			-3:00	-	ART
     #
     # Santa Cruz (SC)
    -Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
    -			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
    +Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
     			-4:00	-	ART	1930 Dec
     			-4:00	Arg	AR%sT	1969 Oct  5
     			-3:00	Arg	AR%sT	1999 Oct  3
    @@ -653,9 +615,9 @@ Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
     			-3:00	Arg	AR%sT	2008 Oct 18
     			-3:00	-	ART
     #
    -# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
    -Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
    -			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
    +# Tierra del Fuego, Antártida e Islas del Atlántico Sur (TF)
    +Zone America/Argentina/Ushuaia -4:33:12 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
     			-4:00	-	ART	1930 Dec
     			-4:00	Arg	AR%sT	1969 Oct  5
     			-3:00	Arg	AR%sT	1999 Oct  3
    @@ -686,13 +648,13 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     
     # From IATA SSIM (1996-02):
     # _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
    -# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
    -# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
    +# Santa Catarina (SC), Paraná (PR), São Paulo (SP), Rio de Janeiro (RJ),
    +# Espírito Santo (ES), Minas Gerais (MG), Bahia (BA), Goiás (GO),
     # Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
     # [The last three states are new to this issue of the IATA SSIM.]
     
     # From Gwillim Law (1996-10-07):
    -# Geography, history (Tocantins was part of Goias until 1989), and other
    +# Geography, history (Tocantins was part of Goiás until 1989), and other
     # sources of time zone information lead me to believe that AL, SE, and TO were
     # always in BR1, and so the only change was whether or not they observed DST....
     # The earliest issue of the SSIM I have is 2/91.  Each issue from then until
    @@ -706,16 +668,14 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     # However, some conclusions can be drawn from another IATA manual: the Airline
     # Coding Directory, which lists close to 400 airports in Brazil.  For each
     # airport it gives a time zone which is coded to the SSIM.  From that
    -# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
    -# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
    -# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
    +# information, I'm led to conclude that the states of Amapá (AP), Ceará (CE),
    +# Maranhão (MA), Paraíba (PR), Pernambuco (PE), Piauí (PI), and Rio Grande do
    +# Norte (RN), and the eastern part of Pará (PA) are all in BR1 without DST.
     
     # From Marcos Tadeu (1998-09-27):
    -# 
    -# Brazilian official page
    -# 
    +# Brazilian official page 
     
    -# From Jesper Norgaard (2000-11-03):
    +# From Jesper Nørgaard (2000-11-03):
     # [For an official list of which regions in Brazil use which time zones, see:]
     # http://pcdsh01.on.br/Fusbr.htm
     # http://pcdsh01.on.br/Fusbrhv.htm
    @@ -748,13 +708,13 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     
     # From Paul Schulze (2008-06-24):
     # ...by law number 11.662 of April 24, 2008 (published in the "Diario
    -# Oficial da Uniao"...) in Brazil there are changes in the timezones,
    +# Oficial da União"...) in Brazil there are changes in the timezones,
     # effective today (00:00am at June 24, 2008) as follows:
     #
    -# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
    +# a) The timezone UTC+5 is extinguished, with all the Acre state and the
     # part of the Amazonas state that had this timezone now being put to the
     # timezone UTC+4
    -# b) The whole Para state now is put at timezone UTC+3, instead of just
    +# b) The whole Pará state now is put at timezone UTC+3, instead of just
     # part of it, as was before.
     #
     # This change follows a proposal of senator Tiao Viana of Acre state, that
    @@ -767,13 +727,11 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     
     # From Rodrigo Severo (2008-06-24):
     # Just correcting the URL:
    -# 
     # https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
    -# 
     #
     # As a result of the above Decree I believe the America/Rio_Branco
     # timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
    -# be created to represent the...west side of the Para State. I
    +# be created to represent the...west side of the Pará State. I
     # suggest this new timezone be called Santarem as the most
     # important/populated city in the affected area.
     #
    @@ -782,19 +740,16 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     
     # From Alex Krivenyshev (2008-06-24):
     # This is a quick reference page for New and Old Brazil Time Zones map.
    -# 
     # http://www.worldtimezone.com/brazil-time-new-old.php
    -# 
     #
    -# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
    -# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
    -# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
    +# - 4 time zones replaced by 3 time zones - eliminating time zone UTC-05
    +# (state Acre and the part of the Amazonas will be UTC/GMT-04) - western
    +# part of Par state is moving to one timezone UTC-03 (from UTC-04).
     
     # From Paul Eggert (2002-10-10):
     # The official decrees referenced below are mostly taken from
    -# 
    -# Decretos sobre o Horario de Verao no Brasil
    -# .
    +# Decretos sobre o Horário de Verão no Brasil.
    +# http://pcdsh01.on.br/DecHV.html
     
     # From Steffen Thorsen (2008-08-29):
     # As announced by the government and many newspapers in Brazil late
    @@ -806,25 +761,17 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     # It has not yet been posted to http://pcdsh01.on.br/DecHV.html
     #
     # An official page about it:
    -# 
     # http://www.mme.gov.br/site/news/detail.do?newsId=16722
    -# 
     # Note that this link does not always work directly, but must be accessed
     # by going to
    -# 
     # http://www.mme.gov.br/first
    -# 
     #
     # One example link that works directly:
    -# 
     # http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
     # (Portuguese)
    -# 
     #
     # We have a written a short article about it as well:
    -# 
     # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
    -# 
     #
     # From Alexander Krivenyshev (2011-10-04):
     # State Bahia will return to Daylight savings time this year after 8 years off.
    @@ -832,17 +779,12 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     # television station in Salvador.
     
     # In Portuguese:
    -# 
     # http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
    -#  and
    -# 
     # http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
    -# 
     
     # From Guilherme Bernardes Rodrigues (2011-10-07):
     # There is news in the media, however there is still no decree about it.
    -# I just send a e-mail to Zulmira Brandao at
    -# http://pcdsh01.on.br/ the
    +# I just send a e-mail to Zulmira Brandao at http://pcdsh01.on.br/ the
     # official agency about time in Brazil, and she confirmed that the old rule is
     # still in force.
     
    @@ -854,9 +796,7 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     #
     # DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
     # Link :
    -# 
     # http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
    -# 
     
     # From Kelley Cook (2012-10-16):
     # The governor of state of Bahia in Brazil announced on Thursday that
    @@ -884,42 +824,42 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
     # For now, assume western Amazonas will change as well.
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -# Decree 20,466 (1931-10-01)
    -# Decree 21,896 (1932-01-10)
    +# Decree 20,466  (1931-10-01)
    +# Decree 21,896  (1932-01-10)
     Rule	Brazil	1931	only	-	Oct	 3	11:00	1:00	S
     Rule	Brazil	1932	1933	-	Apr	 1	 0:00	0	-
     Rule	Brazil	1932	only	-	Oct	 3	 0:00	1:00	S
    -# Decree 23,195 (1933-10-10)
    +# Decree 23,195  (1933-10-10)
     # revoked DST.
    -# Decree 27,496 (1949-11-24)
    -# Decree 27,998 (1950-04-13)
    +# Decree 27,496  (1949-11-24)
    +# Decree 27,998  (1950-04-13)
     Rule	Brazil	1949	1952	-	Dec	 1	 0:00	1:00	S
     Rule	Brazil	1950	only	-	Apr	16	 1:00	0	-
     Rule	Brazil	1951	1952	-	Apr	 1	 0:00	0	-
    -# Decree 32,308 (1953-02-24)
    +# Decree 32,308  (1953-02-24)
     Rule	Brazil	1953	only	-	Mar	 1	 0:00	0	-
    -# Decree 34,724 (1953-11-30)
    +# Decree 34,724  (1953-11-30)
     # revoked DST.
    -# Decree 52,700 (1963-10-18)
    +# Decree 52,700  (1963-10-18)
     # established DST from 1963-10-23 00:00 to 1964-02-29 00:00
     # in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
    -# Decree 53,071 (1963-12-03)
    +# Decree 53,071  (1963-12-03)
     # extended the above decree to all of the national territory on 12-09.
     Rule	Brazil	1963	only	-	Dec	 9	 0:00	1:00	S
    -# Decree 53,604 (1964-02-25)
    +# Decree 53,604  (1964-02-25)
     # extended summer time by one day to 1964-03-01 00:00 (start of school).
     Rule	Brazil	1964	only	-	Mar	 1	 0:00	0	-
    -# Decree 55,639 (1965-01-27)
    +# Decree 55,639  (1965-01-27)
     Rule	Brazil	1965	only	-	Jan	31	 0:00	1:00	S
     Rule	Brazil	1965	only	-	Mar	31	 0:00	0	-
    -# Decree 57,303 (1965-11-22)
    +# Decree 57,303  (1965-11-22)
     Rule	Brazil	1965	only	-	Dec	 1	 0:00	1:00	S
    -# Decree 57,843 (1966-02-18)
    +# Decree 57,843  (1966-02-18)
     Rule	Brazil	1966	1968	-	Mar	 1	 0:00	0	-
     Rule	Brazil	1966	1967	-	Nov	 1	 0:00	1:00	S
    -# Decree 63,429 (1968-10-15)
    +# Decree 63,429  (1968-10-15)
     # revoked DST.
    -# Decree 91,698 (1985-09-27)
    +# Decree 91,698  (1985-09-27)
     Rule	Brazil	1985	only	-	Nov	 2	 0:00	1:00	S
     # Decree 92,310 (1986-01-21)
     # Decree 92,463 (1986-03-13)
    @@ -927,42 +867,42 @@ Rule	Brazil	1986	only	-	Mar	15	 0:00	0	-
     # Decree 93,316 (1986-10-01)
     Rule	Brazil	1986	only	-	Oct	25	 0:00	1:00	S
     Rule	Brazil	1987	only	-	Feb	14	 0:00	0	-
    -# Decree 94,922 (1987-09-22)
    +# Decree 94,922  (1987-09-22)
     Rule	Brazil	1987	only	-	Oct	25	 0:00	1:00	S
     Rule	Brazil	1988	only	-	Feb	 7	 0:00	0	-
    -# Decree 96,676 (1988-09-12)
    +# Decree 96,676  (1988-09-12)
     # except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
     Rule	Brazil	1988	only	-	Oct	16	 0:00	1:00	S
     Rule	Brazil	1989	only	-	Jan	29	 0:00	0	-
    -# Decree 98,077 (1989-08-21)
    +# Decree 98,077  (1989-08-21)
     # with the same exceptions
     Rule	Brazil	1989	only	-	Oct	15	 0:00	1:00	S
     Rule	Brazil	1990	only	-	Feb	11	 0:00	0	-
    -# Decree 99,530 (1990-09-17)
    +# Decree 99,530  (1990-09-17)
     # adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
     # Decree 99,629 (1990-10-19) adds BA, MT.
     Rule	Brazil	1990	only	-	Oct	21	 0:00	1:00	S
     Rule	Brazil	1991	only	-	Feb	17	 0:00	0	-
    -# Unnumbered decree (1991-09-25)
    +# Unnumbered decree  (1991-09-25)
     # adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
     Rule	Brazil	1991	only	-	Oct	20	 0:00	1:00	S
     Rule	Brazil	1992	only	-	Feb	 9	 0:00	0	-
    -# Unnumbered decree (1992-10-16)
    +# Unnumbered decree  (1992-10-16)
     # adopted by same states.
     Rule	Brazil	1992	only	-	Oct	25	 0:00	1:00	S
     Rule	Brazil	1993	only	-	Jan	31	 0:00	0	-
    -# Decree 942 (1993-09-28)
    +# Decree 942  (1993-09-28)
     # adopted by same states, plus AM.
    -# Decree 1,252 (1994-09-22;
    +# Decree 1,252  (1994-09-22;
     # web page corrected 2004-01-07) adopted by same states, minus AM.
    -# Decree 1,636 (1995-09-14)
    +# Decree 1,636  (1995-09-14)
     # adopted by same states, plus MT and TO.
    -# Decree 1,674 (1995-10-13)
    +# Decree 1,674  (1995-10-13)
     # adds AL, SE.
     Rule	Brazil	1993	1995	-	Oct	Sun>=11	 0:00	1:00	S
     Rule	Brazil	1994	1995	-	Feb	Sun>=15	 0:00	0	-
     Rule	Brazil	1996	only	-	Feb	11	 0:00	0	-
    -# Decree 2,000 (1996-09-04)
    +# Decree 2,000  (1996-09-04)
     # adopted by same states, minus AL, SE.
     Rule	Brazil	1996	only	-	Oct	 6	 0:00	1:00	S
     Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
    @@ -975,53 +915,51 @@ Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
     #
     # Decree 2,317 (1997-09-04), adopted by same states.
     Rule	Brazil	1997	only	-	Oct	 6	 0:00	1:00	S
    -# Decree 2,495
    +# Decree 2,495 
     # (1998-02-10)
     Rule	Brazil	1998	only	-	Mar	 1	 0:00	0	-
    -# Decree 2,780 (1998-09-11)
    +# Decree 2,780  (1998-09-11)
     # adopted by the same states as before.
     Rule	Brazil	1998	only	-	Oct	11	 0:00	1:00	S
     Rule	Brazil	1999	only	-	Feb	21	 0:00	0	-
    -# Decree 3,150
    +# Decree 3,150 
     # (1999-08-23) adopted by same states.
    -# Decree 3,188 (1999-09-30)
    +# Decree 3,188  (1999-09-30)
     # adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
     Rule	Brazil	1999	only	-	Oct	 3	 0:00	1:00	S
     Rule	Brazil	2000	only	-	Feb	27	 0:00	0	-
    -# Decree 3,592 (2000-09-06)
    +# Decree 3,592  (2000-09-06)
     # adopted by the same states as before.
    -# Decree 3,630 (2000-10-13)
    +# Decree 3,630  (2000-10-13)
     # repeals DST in PE and RR, effective 2000-10-15 00:00.
    -# Decree 3,632 (2000-10-17)
    +# Decree 3,632  (2000-10-17)
     # repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
    -# Decree 3,916
    +# Decree 3,916 
     # (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
     Rule	Brazil	2000	2001	-	Oct	Sun>=8	 0:00	1:00	S
     Rule	Brazil	2001	2006	-	Feb	Sun>=15	 0:00	0	-
     # Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
    -# 4,399
    +# 4,399 
     Rule	Brazil	2002	only	-	Nov	 3	 0:00	1:00	S
     # Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
    -# 4,844
    +# 4,844 
     Rule	Brazil	2003	only	-	Oct	19	 0:00	1:00	S
     # Decree 5,223 (2004-10-01) reestablishes DST in MT.
    -# 5,223
    +# 5,223 
     Rule	Brazil	2004	only	-	Nov	 2	 0:00	1:00	S
    -# Decree 5,539 (2005-09-19),
    +# Decree 5,539  (2005-09-19),
     # adopted by the same states as before.
     Rule	Brazil	2005	only	-	Oct	16	 0:00	1:00	S
    -# Decree 5,920 (2006-10-03),
    +# Decree 5,920  (2006-10-03),
     # adopted by the same states as before.
     Rule	Brazil	2006	only	-	Nov	 5	 0:00	1:00	S
     Rule	Brazil	2007	only	-	Feb	25	 0:00	0	-
    -# Decree 6,212 (2007-09-26),
    +# Decree 6,212  (2007-09-26),
     # adopted by the same states as before.
     Rule	Brazil	2007	only	-	Oct	Sun>=8	 0:00	1:00	S
     # From Frederico A. C. Neves (2008-09-10):
     # According to this decree
    -# 
     # http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
    -# 
     # [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
     # 3rd Feb Sunday. There is an exception on the return date when this is
     # the Carnival Sunday then the return date will be the next Sunday...
    @@ -1056,29 +994,29 @@ Zone America/Noronha	-2:09:40 -	LMT	1914
     			-2:00	Brazil	FN%sT	2002 Oct  1
     			-2:00	-	FNT
     # Other Atlantic islands have no permanent settlement.
    -# These include Trindade and Martin Vaz (administratively part of ES),
    -# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
    +# These include Trindade and Martim Vaz (administratively part of ES),
    +# Rocas Atoll (RN), and the St Peter and St Paul Archipelago (PE).
     # Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
     # it also included the Penedos.
     #
    -# Amapa (AP), east Para (PA)
    -# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
    -# The division between east and west Para is the river Xingu.
    +# Amapá (AP), east Pará (PA)
    +# East Pará includes Belém, Marabá, Serra Norte, and São Félix do Xingu.
    +# The division between east and west Pará is the river Xingu.
     # In the north a very small part from the river Javary (now Jari I guess,
    -# the border with Amapa) to the Amazon, then to the Xingu.
    +# the border with Amapá) to the Amazon, then to the Xingu.
     Zone America/Belem	-3:13:56 -	LMT	1914
     			-3:00	Brazil	BR%sT	1988 Sep 12
     			-3:00	-	BRT
     #
    -# west Para (PA)
    -# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
    +# west Pará (PA)
    +# West Pará includes Altamira, Óbidos, Prainha, Oriximiná, and Santarém.
     Zone America/Santarem	-3:38:48 -	LMT	1914
     			-4:00	Brazil	AM%sT	1988 Sep 12
    -			-4:00	-	AMT	2008 Jun 24 00:00
    +			-4:00	-	AMT	2008 Jun 24  0:00
     			-3:00	-	BRT
     #
    -# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
    -# Paraiba (PB)
    +# Maranhão (MA), Piauí (PI), Ceará (CE), Rio Grande do Norte (RN),
    +# Paraíba (PB)
     Zone America/Fortaleza	-2:34:00 -	LMT	1914
     			-3:00	Brazil	BR%sT	1990 Sep 17
     			-3:00	-	BRT	1999 Sep 30
    @@ -1125,11 +1063,11 @@ Zone America/Bahia	-2:34:04 -	LMT	1914
     			-3:00	Brazil	BR%sT	2012 Oct 21
     			-3:00	-	BRT
     #
    -# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
    -# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
    +# Goiás (GO), Distrito Federal (DF), Minas Gerais (MG),
    +# Espírito Santo (ES), Rio de Janeiro (RJ), São Paulo (SP), Paraná (PR),
     # Santa Catarina (SC), Rio Grande do Sul (RS)
     Zone America/Sao_Paulo	-3:06:28 -	LMT	1914
    -			-3:00	Brazil	BR%sT	1963 Oct 23 00:00
    +			-3:00	Brazil	BR%sT	1963 Oct 23  0:00
     			-3:00	1:00	BRST	1964
     			-3:00	Brazil	BR%sT
     #
    @@ -1143,7 +1081,7 @@ Zone America/Cuiaba	-3:44:20 -	LMT	1914
     			-4:00	-	AMT	2004 Oct  1
     			-4:00	Brazil	AM%sT
     #
    -# Rondonia (RO)
    +# Rondônia (RO)
     Zone America/Porto_Velho -4:15:36 -	LMT	1914
     			-4:00	Brazil	AM%sT	1988 Sep 12
     			-4:00	-	AMT
    @@ -1155,7 +1093,7 @@ Zone America/Boa_Vista	-4:02:40 -	LMT	1914
     			-4:00	Brazil	AM%sT	2000 Oct 15
     			-4:00	-	AMT
     #
    -# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
    +# east Amazonas (AM): Boca do Acre, Jutaí, Manaus, Floriano Peixoto
     # The great circle line from Tabatinga to Porto Acre divides
     # east from west Amazonas.
     Zone America/Manaus	-4:00:04 -	LMT	1914
    @@ -1165,19 +1103,19 @@ Zone America/Manaus	-4:00:04 -	LMT	1914
     			-4:00	-	AMT
     #
     # west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
    -#	Eirunepe, Envira, Ipixuna
    +#	Eirunepé, Envira, Ipixuna
     Zone America/Eirunepe	-4:39:28 -	LMT	1914
     			-5:00	Brazil	AC%sT	1988 Sep 12
     			-5:00	-	ACT	1993 Sep 28
     			-5:00	Brazil	AC%sT	1994 Sep 22
    -			-5:00	-	ACT	2008 Jun 24 00:00
    +			-5:00	-	ACT	2008 Jun 24  0:00
     			-4:00	-	AMT	2013 Nov 10
     			-5:00	-	ACT
     #
     # Acre (AC)
     Zone America/Rio_Branco	-4:31:12 -	LMT	1914
     			-5:00	Brazil	AC%sT	1988 Sep 12
    -			-5:00	-	ACT	2008 Jun 24 00:00
    +			-5:00	-	ACT	2008 Jun 24  0:00
     			-4:00	-	AMT	2013 Nov 10
     			-5:00	-	ACT
     
    @@ -1198,66 +1136,54 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
     # From Oscar van Vlijmen (2006-10-08):
     # http://www.horaoficial.cl/cambio.htm
     
    -# From Jesper Norgaard Welen (2006-10-08):
    +# From Jesper Nørgaard Welen (2006-10-08):
     # I think that there are some obvious mistakes in the suggested link
     # from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
     # ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
     # (they should have been 1990-09-15 and 1990-09-16 respectively), but
     # anyhow it clears up some doubts too.
     
    -# From Paul Eggert (2006-12-27):
    -# The following data for Chile and America/Santiago are from
    +# From Paul Eggert (2014-08-12):
    +# The following data entries for Chile and America/Santiago are from
     #  (2006-09-20), transcribed by
    -# Jesper Norgaard Welen.  The data for Pacific/Easter are from Shanks
    +# Jesper Nørgaard Welen.  The data entries for Pacific/Easter are from Shanks
     # & Pottenger, except with DST transitions after 1932 cloned from
    -# America/Santiago.  The pre-1980 Pacific/Easter data are dubious,
    +# America/Santiago.  The pre-1980 Pacific/Easter data entries are dubious,
     # but we have no other source.
     
    -# From German Poo-Caaman~o (2008-03-03):
    +# From Germán Poo-Caamaño (2008-03-03):
     # Due to drought, Chile extends Daylight Time in three weeks.  This
     # is one-time change (Saturday 3/29 at 24:00 for America/Santiago
     # and Saturday 3/29 at 22:00 for Pacific/Easter)
     # The Supreme Decree is located at
    -# 
     # http://www.shoa.cl/servicios/supremo316.pdf
    -# 
     # and the instructions for 2008 are located in:
    -# 
     # http://www.horaoficial.cl/cambio.htm
    -# .
     
    -# From Jose Miguel Garrido (2008-03-05):
    +# From José Miguel Garrido (2008-03-05):
     # ...
     # You could see the announces of the change on
    -# 
     # http://www.shoa.cl/noticias/2008/04hora/hora.htm
    -# .
     
     # From Angel Chiang (2010-03-04):
     # Subject: DST in Chile exceptionally extended to 3 April due to earthquake
    -# 
     # http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098
    -# 
     # (in Spanish, last paragraph).
     #
     # This is breaking news. There should be more information available later.
     
    -# From Arthur Daivd Olson (2010-03-06):
    +# From Arthur David Olson (2010-03-06):
     # Angel Chiang's message confirmed by Julio Pacheco; Julio provided a patch.
     
    -# From Glenn Eychaner (2011-03-02): [geychaner@mac.com]
    +# From Glenn Eychaner (2011-03-02):
     # It appears that the Chilean government has decided to postpone the
     # change from summer time to winter time again, by three weeks to April
     # 2nd:
    -# 
     # http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651
    -# 
     #
     # This is not yet reflected in the official "cambio de hora" site, but
     # probably will be soon:
    -# 
     # http://www.horaoficial.cl/cambio.htm
    -# 
     
     # From Arthur David Olson (2011-03-02):
     # The emol.com article mentions a water shortage as the cause of the
    @@ -1265,9 +1191,7 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
     
     # From Glenn Eychaner (2011-03-28):
     # The article:
    -# 
     # http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}
    -# 
     #
     # In English:
     # Chile's clocks will go back an hour this year on the 7th of May instead
    @@ -1298,7 +1222,7 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
     # start date is 2013-09-08 00:00....
     # http://www.gob.cl/informa/2013/02/15/gobierno-anuncia-fechas-de-cambio-de-hora-para-el-ano-2013.htm
     
    -# From Jose Miguel Garrido (2014-02-19):
    +# From José Miguel Garrido (2014-02-19):
     # Today appeared in the Diario Oficial a decree amending the time change
     # dates to 2014.
     # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC)
    @@ -1352,7 +1276,7 @@ Rule	Chile	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
     # (1996-09) says 1998-03-08.  Ignore these.
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Santiago	-4:42:46 -	LMT	1890
    -			-4:42:46 -	SMT	1910 	    # Santiago Mean Time
    +			-4:42:46 -	SMT	1910        # Santiago Mean Time
     			-5:00	-	CLT	1916 Jul  1 # Chile Time
     			-4:42:46 -	SMT	1918 Sep  1 # Santiago Mean Time
     			-4:00	-	CLT	1919 Jul  1 # Chile Time
    @@ -1361,16 +1285,16 @@ Zone America/Santiago	-4:42:46 -	LMT	1890
     			-4:00	Chile	CL%sT
     Zone Pacific/Easter	-7:17:44 -	LMT	1890
     			-7:17:28 -	EMT	1932 Sep    # Easter Mean Time
    -			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter I Time
    +			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter Time
     			-6:00	Chile	EAS%sT
     #
    -# Sala y Gomez Island is like Pacific/Easter.
    -# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
    -# San Felix, and Antarctic bases, are like America/Santiago.
    +# Salas y Gómez Island is uninhabited.
    +# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
    +# and Antarctic bases, are like America/Santiago.
     
     # Colombia
     
    -# Milne gives 4:56:16.4 for Bogota time in 1899; round to nearest.  He writes,
    +# Milne gives 4:56:16.4 for Bogotá time in 1899; round to nearest.  He writes,
     # "A variation of fifteen minutes in the public clocks of Bogota is not rare."
     
     # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    @@ -1378,37 +1302,37 @@ Rule	CO	1992	only	-	May	 3	0:00	1:00	S
     Rule	CO	1993	only	-	Apr	 4	0:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	America/Bogota	-4:56:16 -	LMT	1884 Mar 13
    -			-4:56:16 -	BMT	1914 Nov 23 # Bogota Mean Time
    +			-4:56:16 -	BMT	1914 Nov 23 # Bogotá Mean Time
     			-5:00	CO	CO%sT	# Colombia Time
     # Malpelo, Providencia, San Andres
     # no information; probably like America/Bogota
     
    -# Curacao
    +# Curaçao
     
    -# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
    +# Milne gives 4:35:46.9 for Curaçao mean time; round to nearest.
     #
     # From Paul Eggert (2006-03-22):
     # Shanks & Pottenger say that The Bottom and Philipsburg have been at
     # -4:00 since standard time was introduced on 1912-03-02; and that
     # Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
     # 1912-02-02 to 1965-01-01.  The former is dubious, since S&P also say
    -# Saba Island has been like Curacao.
    +# Saba Island has been like Curaçao.
     # This all predates our 1970 cutoff, though.
     #
    -# By July 2007 Curacao and St Maarten are planned to become
    +# By July 2007 Curaçao and St Maarten are planned to become
     # associated states within the Netherlands, much like Aruba;
     # Bonaire, Saba and St Eustatius would become directly part of the
     # Netherlands as Kingdom Islands.  This won't affect their time zones
     # though, as far as we know.
     #
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12	# Willemstad
    +Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12 # Willemstad
     			-4:30	-	ANT	1965 # Netherlands Antilles Time
     			-4:00	-	AST
     
     # From Arthur David Olson (2011-06-15):
     # use links for places with new iso3166 codes.
    -# The name "Lower Prince's Quarter" is both longer than fourteen charaters
    +# The name "Lower Prince's Quarter" is both longer than fourteen characters
     # and contains an apostrophe; use "Lower_Princes" below.
     
     Link	America/Curacao	America/Lower_Princes	# Sint Maarten
    @@ -1416,7 +1340,7 @@ Link	America/Curacao	America/Kralendijk	# Caribbean Netherlands
     
     # Ecuador
     #
    -# Milne says the Sentral and South American Telegraph Company used -5:24:15.
    +# Milne says the Central and South American Telegraph Company used -5:24:15.
     #
     # From Paul Eggert (2007-03-04):
     # Apparently Ecuador had a failed experiment with DST in 1992.
    @@ -1427,10 +1351,10 @@ Link	America/Curacao	America/Kralendijk	# Caribbean Netherlands
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Guayaquil	-5:19:20 -	LMT	1890
     			-5:14:00 -	QMT	1931 # Quito Mean Time
    -			-5:00	-	ECT	     # Ecuador Time
    +			-5:00	-	ECT	# Ecuador Time
     Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
     			-5:00	-	ECT	1986
    -			-6:00	-	GALT	     # Galapagos Time
    +			-6:00	-	GALT	# Galápagos Time
     
     # Falklands
     
    @@ -1439,7 +1363,7 @@ Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
     # the IATA gives 1996-09-08.  Go with Shanks & Pottenger.
     
     # From Falkland Islands Government Office, London (2001-01-22)
    -# via Jesper Norgaard:
    +# via Jesper Nørgaard:
     # ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
     # April 2001 and advance one hour to summer time at 2 am on Sunday 2
     # September.  It is anticipated that the clocks will revert back at 2
    @@ -1488,9 +1412,7 @@ Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
     # daylight saving time.
     #
     # One source:
    -# 
     # http://www.falklandnews.com/public/story.cfm?get=5914&source=3
    -# 
     #
     # We have gotten this confirmed by a clerk of the legislative assembly:
     # Normally the clocks revert to Local Mean Time (UTC/GMT -4 hours) on the
    @@ -1531,10 +1453,10 @@ Rule	Falk	2001	2010	-	Apr	Sun>=15	2:00	0	-
     Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	S
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
    -			-3:51:24 -	SMT	1912 Mar 12  # Stanley Mean Time
    -			-4:00	Falk	FK%sT	1983 May     # Falkland Is Time
    +			-3:51:24 -	SMT	1912 Mar 12 # Stanley Mean Time
    +			-4:00	Falk	FK%sT	1983 May    # Falkland Is Time
     			-3:00	Falk	FK%sT	1985 Sep 15
    -			-4:00	Falk	FK%sT	2010 Sep 5 02:00
    +			-4:00	Falk	FK%sT	2010 Sep  5  2:00
     			-3:00	-	FKST
     
     # French Guiana
    @@ -1545,7 +1467,7 @@ Zone America/Cayenne	-3:29:20 -	LMT	1911 Jul
     
     # Guyana
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
    +Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar    # Georgetown
     			-3:45	-	GBGT	1966 May 26 # Br Guiana Time
     			-3:45	-	GYT	1975 Jul 31 # Guyana Time
     			-3:00	-	GYT	1991
    @@ -1555,8 +1477,8 @@ Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
     # Paraguay
     #
     # From Paul Eggert (2006-03-22):
    -# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
    -# and autumn transitions are from 00:00 -> 23:00.  Go with pre-1999
    +# Shanks & Pottenger say that spring transitions are 01:00 -> 02:00,
    +# and autumn transitions are 00:00 -> 23:00.  Go with pre-1999
     # editions of Shanks, and with the IATA, who say transitions occur at 00:00.
     #
     # From Waldemar Villamayor-Venialbo (2013-09-20):
    @@ -1582,9 +1504,8 @@ Rule	Para	1996	only	-	Mar	 1	0:00	0	-
     # (10-01).
     #
     # Translated by Gwillim Law (2001-02-27) from
    -# 
    -# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
    -# :
    +# Noticias, a daily paper in Asunción, Paraguay (2000-10-01):
    +# http://www.diarionoticias.com.py/011000/nacional/naciona1.htm
     # Starting at 0:00 today, the clock will be set forward 60 minutes, in
     # fulfillment of Decree No. 7,273 of the Executive Power....  The time change
     # system has been operating for several years.  Formerly there was a separate
    @@ -1605,21 +1526,18 @@ Rule	Para	1998	2001	-	Mar	Sun>=1	0:00	0	-
     Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
     Rule	Para	2002	2003	-	Sep	Sun>=1	0:00	1:00	S
     #
    -# From Jesper Norgaard Welen (2005-01-02):
    +# From Jesper Nørgaard Welen (2005-01-02):
     # There are several sources that claim that Paraguay made
     # a timezone rule change in autumn 2004.
     # From Steffen Thorsen (2005-01-05):
     # Decree 1,867 (2004-03-05)
    -# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
    -# 
    +# From Carlos Raúl Perasso via Jesper Nørgaard Welen (2006-10-13)
    +# http://www.presidencia.gov.py/decretos/D1867.pdf
     Rule	Para	2004	2009	-	Oct	Sun>=15	0:00	1:00	S
     Rule	Para	2005	2009	-	Mar	Sun>=8	0:00	0	-
    -# From Carlos Raul Perasso (2010-02-18):
    -# By decree number 3958 issued yesterday (
    -# 
    +# From Carlos Raúl Perasso (2010-02-18):
    +# By decree number 3958 issued yesterday
     # http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf
    -# 
    -# )
     # Paraguay changes its DST schedule, postponing the March rule to April and
     # modifying the October date. The decree reads:
     # ...
    @@ -1635,25 +1553,25 @@ Rule	Para	2010	2012	-	Apr	Sun>=8	0:00	0	-
     # Paraguay will end DST on 2013-03-24 00:00....
     # http://www.ande.gov.py/interna.php?id=1075
     #
    -# From Carlos Raul Perasso (2013-03-15):
    +# From Carlos Raúl Perasso (2013-03-15):
     # The change in Paraguay is now final.  Decree number 10780
     # http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.pdf
    -# From Carlos Raul Perasso (2014-02-28):
    +# From Carlos Raúl Perasso (2014-02-28):
     # Decree 1264 can be found at:
     # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
     Rule	Para	2013	max	-	Mar	Sun>=22	0:00	0	-
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Asuncion	-3:50:40 -	LMT	1890
    -			-3:50:40 -	AMT	1931 Oct 10 # Asuncion Mean Time
    -			-4:00	-	PYT	1972 Oct # Paraguay Time
    +			-3:50:40 -	AMT	1931 Oct 10 # Asunción Mean Time
    +			-4:00	-	PYT	1972 Oct    # Paraguay Time
     			-3:00	-	PYT	1974 Apr
     			-4:00	Para	PY%sT
     
     # Peru
     #
    -# 
    -# From Evelyn C. Leeper via Mark Brader (2003-10-26):
    +# From Evelyn C. Leeper via Mark Brader (2003-10-26)
    +# :
     # When we were in Peru in 1985-1986, they apparently switched over
     # sometime between December 29 and January 3 while we were on the Amazon.
     #
    @@ -1679,7 +1597,7 @@ Zone	America/Lima	-5:08:12 -	LMT	1890
     
     # South Georgia
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    -Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
    +Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890 # Grytviken
     			-2:00	-	GST	# South Georgia Time
     
     # South Sandwich Is
    @@ -1689,9 +1607,9 @@ Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Paramaribo	-3:40:40 -	LMT	1911
     			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
    -			-3:40:36 -	PMT	1945 Oct # The capital moved?
    +			-3:40:36 -	PMT	1945 Oct    # The capital moved?
     			-3:30	-	NEGT	1975 Nov 20 # Dutch Guiana Time
    -			-3:30	-	SRT	1984 Oct # Suriname Time
    +			-3:30	-	SRT	1984 Oct    # Suriname Time
     			-3:00	-	SRT
     
     # Trinidad and Tobago
    @@ -1706,7 +1624,7 @@ Link America/Port_of_Spain America/Grenada
     Link America/Port_of_Spain America/Guadeloupe
     Link America/Port_of_Spain America/Marigot	# St Martin (French part)
     Link America/Port_of_Spain America/Montserrat
    -Link America/Port_of_Spain America/St_Barthelemy
    +Link America/Port_of_Spain America/St_Barthelemy # St Barthélemy
     Link America/Port_of_Spain America/St_Kitts	# St Kitts & Nevis
     Link America/Port_of_Spain America/St_Lucia
     Link America/Port_of_Spain America/St_Thomas	# Virgin Islands (US)
    @@ -1765,7 +1683,7 @@ Rule	Uruguay	1990	1991	-	Oct	Sun>=21	 0:00	1:00	S
     Rule	Uruguay	1992	only	-	Oct	18	 0:00	1:00	S
     Rule	Uruguay	1993	only	-	Feb	28	 0:00	0	-
     # From Eduardo Cota (2004-09-20):
    -# The uruguayan government has decreed a change in the local time....
    +# The Uruguayan government has decreed a change in the local time....
     # http://www.presidencia.gub.uy/decretos/2004091502.htm
     Rule	Uruguay	2004	only	-	Sep	19	 0:00	1:00	S
     # From Steffen Thorsen (2005-03-11):
    @@ -1779,14 +1697,14 @@ Rule	Uruguay	2005	only	-	Mar	27	 2:00	0	-
     # 02:00 local time, official time in Uruguay will be at GMT -2.
     Rule	Uruguay	2005	only	-	Oct	 9	 2:00	1:00	S
     Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
    -# From Jesper Norgaard Welen (2006-09-06):
    +# From Jesper Nørgaard Welen (2006-09-06):
     # http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
     Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
     Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
    -			-3:44:44 -	MMT	1920 May  1	# Montevideo MT
    -			-3:30	Uruguay	UY%sT	1942 Dec 14	# Uruguay Time
    +			-3:44:44 -	MMT	1920 May  1 # Montevideo MT
    +			-3:30	Uruguay	UY%sT	1942 Dec 14 # Uruguay Time
     			-3:00	Uruguay	UY%sT
     
     # Venezuela
    @@ -1794,14 +1712,14 @@ Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
     # From John Stainforth (2007-11-28):
     # ... the change for Venezuela originally expected for 2007-12-31 has
     # been brought forward to 2007-12-09.  The official announcement was
    -# published today in the "Gaceta Oficial de la Republica Bolivariana
    -# de Venezuela, numero 38.819" (official document for all laws or
    +# published today in the "Gaceta Oficial de la República Bolivariana
    +# de Venezuela, número 38.819" (official document for all laws or
     # resolution publication)
     # http://www.globovision.com/news.php?nid=72208
     
     # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
     Zone	America/Caracas	-4:27:44 -	LMT	1890
     			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
    -			-4:30	-	VET	1965	     # Venezuela Time
    -			-4:00	-	VET	2007 Dec  9 03:00
    +			-4:30	-	VET	1965        # Venezuela Time
    +			-4:00	-	VET	2007 Dec  9  3:00
     			-4:30	-	VET
    diff --git a/test/sun/util/calendar/zi/tzdata/systemv b/test/sun/util/calendar/zi/tzdata/systemv
    index f909f9c76dbd4cfc8f9b8fa9ac1de182dfc61dcc..c7b9a888e8834e515a02f242fb633d2e09669f38 100644
    --- a/test/sun/util/calendar/zi/tzdata/systemv
    +++ b/test/sun/util/calendar/zi/tzdata/systemv
    @@ -21,7 +21,6 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# 
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    diff --git a/test/sun/util/calendar/zi/tzdata/zone.tab b/test/sun/util/calendar/zi/tzdata/zone.tab
    index 7cec627fd95862053bc8c9cd5e991a1309a42f6d..45351ca848654a8c4c76ad96e0e8ed6f0495371b 100644
    --- a/test/sun/util/calendar/zi/tzdata/zone.tab
    +++ b/test/sun/util/calendar/zi/tzdata/zone.tab
    @@ -21,39 +21,27 @@
     # or visit www.oracle.com if you need additional information or have any
     # questions.
     #
    -# TZ zone descriptions
    +# tz zone descriptions (deprecated version)
     #
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     #
    -# From Paul Eggert (2013-08-14):
    +# From Paul Eggert (2014-07-31):
    +# This file is intended as a backward-compatibility aid for older programs.
    +# New programs should use zone1970.tab.  This file is like zone1970.tab (see
    +# zone1970.tab's comments), but with the following additional restrictions:
     #
    -# This file contains a table where each row stands for an area that is
    -# the intersection of a region identified by a country code and of a
    -# zone where civil clocks have agreed since 1970.  The columns of the
    -# table are as follows:
    +# 1.  This file contains only ASCII characters.
    +# 2.  The first data column contains exactly one country code.
     #
    -# 1.  ISO 3166 2-character country code.  See the file 'iso3166.tab'.
    -# 2.  Latitude and longitude of the area's principal location
    -#     in ISO 6709 sign-degrees-minutes-seconds format,
    -#     either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
    -#     first latitude (+ is north), then longitude (+ is east).
    -# 3.  Zone name used in value of TZ environment variable.
    -#     Please see the 'Theory' file for how zone names are chosen.
    -#     If multiple zones overlap a country, each has a row in the
    -#     table, with column 1 being duplicated.
    -# 4.  Comments; present if and only if the country has multiple rows.
    -#
    -# Columns are separated by a single tab.
    -# The table is sorted first by country, then an order within the country that
    -# (1) makes some geographical sense, and
    -# (2) puts the most populous areas first, where that does not contradict (1).
    -#
    -# Lines beginning with '#' are comments.
    +# Because of (2), each row stands for an area that is the intersection
    +# of a region identified by a country code and of a zone where civil
    +# clocks have agreed since 1970; this is a narrower definition than
    +# that of zone1970.tab.
     #
     # This table is intended as an aid for users, to help them select time
    -# zone data appropriate for their practical needs.  It is not intended
    -# to take or endorse any position on legal or territorial claims.
    +# zone data entries appropriate for their practical needs.  It is not
    +# intended to take or endorse any position on legal or territorial claims.
     #
     #country-
     #code	coordinates	TZ			comments
    @@ -72,7 +60,7 @@ AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
     AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
     AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
     AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
    -AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
    +AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Adelie Land
     AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
     AQ	-720041+0023206	Antarctica/Troll	Troll Station, Queen Maud Land
     AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
    @@ -151,7 +139,7 @@ CA	+4901-08816	America/Nipigon	Eastern Time - Ontario & Quebec - places that did
     CA	+4823-08915	America/Thunder_Bay	Eastern Time - Thunder Bay, Ontario
     CA	+6344-06828	America/Iqaluit	Eastern Time - east Nunavut - most locations
     CA	+6608-06544	America/Pangnirtung	Eastern Time - Pangnirtung, Nunavut
    -CA	+744144-0944945	America/Resolute	Central Standard Time - Resolute, Nunavut
    +CA	+744144-0944945	America/Resolute	Central Time - Resolute, Nunavut
     CA	+484531-0913718	America/Atikokan	Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
     CA	+624900-0920459	America/Rankin_Inlet	Central Time - central Nunavut
     CA	+4953-09709	America/Winnipeg	Central Time - Manitoba & west Ontario
    @@ -176,13 +164,10 @@ CH	+4723+00832	Europe/Zurich
     CI	+0519-00402	Africa/Abidjan
     CK	-2114-15946	Pacific/Rarotonga
     CL	-3327-07040	America/Santiago	most locations
    -CL	-2709-10926	Pacific/Easter	Easter Island & Sala y Gomez
    +CL	-2709-10926	Pacific/Easter	Easter Island
     CM	+0403+00942	Africa/Douala
    -CN	+3114+12128	Asia/Shanghai	east China - Beijing, Guangdong, Shanghai, etc.
    -CN	+4545+12641	Asia/Harbin	Heilongjiang (except Mohe), Jilin
    -CN	+2934+10635	Asia/Chongqing	central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
    -CN	+4348+08735	Asia/Urumqi	most of Tibet & Xinjiang
    -CN	+3929+07559	Asia/Kashgar	west Tibet & Xinjiang
    +CN	+3114+12128	Asia/Shanghai	Beijing Time
    +CN	+4348+08735	Asia/Urumqi	Xinjiang Time
     CO	+0436-07405	America/Bogota
     CR	+0956-08405	America/Costa_Rica
     CU	+2308-08222	America/Havana
    @@ -364,24 +349,26 @@ RE	-2052+05528	Indian/Reunion
     RO	+4426+02606	Europe/Bucharest
     RS	+4450+02030	Europe/Belgrade
     RU	+5443+02030	Europe/Kaliningrad	Moscow-01 - Kaliningrad
    -RU	+5545+03735	Europe/Moscow	Moscow+00 - west Russia
    -RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
    -RU	+5312+05009	Europe/Samara	Moscow+00 - Samara, Udmurtia
    +RU	+554521+0373704	Europe/Moscow	Moscow+00 - west Russia
     RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
    +RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
    +RU	+5312+05009	Europe/Samara	Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia
     RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
     RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
     RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
    -RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
    +RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo
     RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
     RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
    +RU	+5203+11328	Asia/Chita	Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky
     RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
     RU	+623923+1353314	Asia/Khandyga	Moscow+06 - Tomponsky, Ust-Maysky
     RU	+4310+13156	Asia/Vladivostok	Moscow+07 - Amur River
     RU	+4658+14242	Asia/Sakhalin	Moscow+07 - Sakhalin Island
     RU	+643337+1431336	Asia/Ust-Nera	Moscow+07 - Oymyakonsky
    -RU	+5934+15048	Asia/Magadan	Moscow+08 - Magadan
    -RU	+5301+15839	Asia/Kamchatka	Moscow+08 - Kamchatka
    -RU	+6445+17729	Asia/Anadyr	Moscow+08 - Bering Sea
    +RU	+5934+15048	Asia/Magadan	Moscow+08 (Moscow+07 after 2014-10-26) - Magadan
    +RU	+6728+15343	Asia/Srednekolymsk	Moscow+08 - E Sakha, N Kuril Is
    +RU	+5301+15839	Asia/Kamchatka	Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka
    +RU	+6445+17729	Asia/Anadyr	Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea
     RW	-0157+03004	Africa/Kigali
     SA	+2438+04643	Asia/Riyadh
     SB	-0932+16012	Pacific/Guadalcanal
    @@ -448,13 +435,13 @@ US	+394421-1045903	America/Denver	Mountain Time
     US	+433649-1161209	America/Boise	Mountain Time - south Idaho & east Oregon
     US	+332654-1120424	America/Phoenix	Mountain Standard Time - Arizona (except Navajo)
     US	+340308-1181434	America/Los_Angeles	Pacific Time
    +US	+550737-1313435	America/Metlakatla	Pacific Standard Time - Annette Island, Alaska
     US	+611305-1495401	America/Anchorage	Alaska Time
     US	+581807-1342511	America/Juneau	Alaska Time - Alaska panhandle
     US	+571035-1351807	America/Sitka	Alaska Time - southeast Alaska panhandle
     US	+593249-1394338	America/Yakutat	Alaska Time - Alaska panhandle neck
     US	+643004-1652423	America/Nome	Alaska Time - west Alaska
     US	+515248-1763929	America/Adak	Aleutian Islands
    -US	+550737-1313435	America/Metlakatla	Metlakatla Time - Annette Island
     US	+211825-1575130	Pacific/Honolulu	Hawaii
     UY	-3453-05611	America/Montevideo
     UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
    diff --git a/test/sun/util/resources/TimeZone/Bug6317929.java b/test/sun/util/resources/TimeZone/Bug6317929.java
    index 4b047c5e4e1d3cec3e5ca5febf6a5127be89046a..1c59896f2a9021af84088deda1203a26075bb3c4 100644
    --- a/test/sun/util/resources/TimeZone/Bug6317929.java
    +++ b/test/sun/util/resources/TimeZone/Bug6317929.java
    @@ -122,11 +122,11 @@ public class Bug6317929 {
             TimeZone Currie = TimeZone.getTimeZone("Australia/Currie");
             tzLocale = locales2Test[0];
             if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
    -           ("Eastern Standard Time (New South Wales)"))
    +           ("Australian Eastern Standard Time (New South Wales)"))
                 throw new RuntimeException("\n" + tzLocale + ": LONG, " +
                                            "non-daylight saving name for " +
                                            "Australia/Currie should be " +
    -                                       "\"Eastern Standard Time " +
    +                                       "\"Australian Eastern Standard Time " +
                                            "(New South Wales)\"");
             tzLocale = locales2Test[1];
             if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals