diff --git a/jdk/make/sun/javazic/tzdata/VERSION b/jdk/make/sun/javazic/tzdata/VERSION
index 85db871ccf3..8ad1064e058 100644
--- a/jdk/make/sun/javazic/tzdata/VERSION
+++ b/jdk/make/sun/javazic/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2012i
+tzdata2013c
diff --git a/jdk/make/sun/javazic/tzdata/africa b/jdk/make/sun/javazic/tzdata/africa
index 7db9b3d269d..2f5d3c5e3fc 100644
--- a/jdk/make/sun/javazic/tzdata/africa
+++ b/jdk/make/sun/javazic/tzdata/africa
@@ -27,9 +27,9 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2013-02-21):
#
# A good source for time zone historical data outside the U.S. is
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -48,6 +48,10 @@
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
# 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
+# .
+#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
@@ -139,8 +143,12 @@ Zone Africa/Porto-Novo 0:10:28 - LMT 1912
1:00 - WAT
# Botswana
+# From Paul Eggert (2013-02-21):
+# Milne says they were regulated by the Cape Town Signal in 1899;
+# assume they switched to 2:00 when Cape Town did.
# 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
@@ -212,6 +220,11 @@ Zone Africa/Djibouti 2:52:36 - LMT 1911 Jul
# Egypt
+# Milne says Cairo used 2:05:08.9, the local mean time of the Abbasizeh
+# observatory; round to nearest. Milne also says that the official time for
+# Egypt was mean noon at the Great Pyramid, 2:04:30.5, but apparently this
+# did not apply to Cairo, Alexandria, or Port Said.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Egypt 1940 only - Jul 15 0:00 1:00 S
Rule Egypt 1940 only - Oct 1 0:00 0 -
@@ -352,7 +365,7 @@ Rule Egypt 2010 only - Sep 10 0:00 1:00 S
Rule Egypt 2010 only - Sep lastThu 23:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Cairo 2:05:00 - LMT 1900 Oct
+Zone Africa/Cairo 2:05:09 - LMT 1900 Oct
2:00 Egypt EE%sT
# Equatorial Guinea
@@ -447,6 +460,20 @@ Zone Africa/Monrovia -0:43:08 - LMT 1882
# Libya
+# From Even Scharning (2012-11-10):
+# Libya set their time one hour back at 02:00 on Saturday November 10.
+# http://www.libyaherald.com/2012/11/04/clocks-to-go-back-an-hour-on-saturday/
+# Here is an official source [in Arabic]: http://ls.ly/fb6Yc
+#
+# Steffen Thorsen forwarded a translation (2012-11-10) in
+# http://mm.icann.org/pipermail/tz/2012-November/018451.html
+#
+# From Tim Parenti (2012-11-11):
+# Treat the 2012-11-10 change as a zone change from UTC+2 to UTC+1.
+# The DST rules planned for 2013 and onward roughly mirror those of Europe
+# (either two days before them or five days after them, so as to fall on
+# lastFri instead of lastSun).
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Libya 1951 only - Oct 14 2:00 1:00 S
Rule Libya 1952 only - Jan 1 0:00 0 -
@@ -461,17 +488,21 @@ Rule Libya 1986 only - Apr 4 0:00 1:00 S
Rule Libya 1986 only - Oct 3 0:00 0 -
Rule Libya 1987 1989 - Apr 1 0:00 1:00 S
Rule Libya 1987 1989 - Oct 1 0:00 0 -
+Rule Libya 1997 only - Apr 4 0:00 1:00 S
+Rule Libya 1997 only - Oct 4 0:00 0 -
+Rule Libya 2013 max - Mar lastFri 1:00 1:00 S
+Rule Libya 2013 max - Oct lastFri 2:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Tripoli 0:52:44 - LMT 1920
1:00 Libya CE%sT 1959
2:00 - EET 1982
1:00 Libya CE%sT 1990 May 4
-# The following entries are from Shanks & Pottenger;
+# The 1996 and 1997 entries are from Shanks & Pottenger;
# the IATA SSIM data contain some obvious errors.
2:00 - EET 1996 Sep 30
- 1:00 - CET 1997 Apr 4
- 1:00 1:00 CEST 1997 Oct 4
- 2:00 - EET
+ 1:00 Libya CE%sT 1997 Oct 4
+ 2:00 - EET 2012 Nov 10 2:00
+ 1:00 Libya CE%sT
# Madagascar
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -838,6 +869,41 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou
# 3:00 am Friday, July 20, 2012 and will again be advanced by 60 minutes
# August 20, 2012 from 2:00 am.
+# From Paul Eggert (2013-03-06):
+# Morocco's daylight-saving transitions due to Ramadan seem to be
+# 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
+# .
+#
+# To estimate what the Moroccan government will do in future years,
+# transition dates for 2013 through 2021 were determined by running
+# the following program under GNU Emacs 24.3:
+#
+# (let ((islamic-year 1434))
+# (while (< islamic-year 1444)
+# (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)))))
+# (setq islamic-year (+ 1 islamic-year))))
+#
+# with the results hand-edited for 2020-2022, when the normal spring-forward
+# date falls during the estimated Ramadan.
+#
+# From 2023 through 2038 Ramadan is not predicted to overlap with
+# daylight saving time. Starting in 2039 there will be overlap again,
+# but 32-bit time_t values roll around in 2038 so for now do not worry
+# about dates after 2038.
+
# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Morocco 1939 only - Sep 12 0:00 1:00 S
@@ -863,10 +929,28 @@ 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 max - Apr lastSun 2:00 1:00 S
+Rule Morocco 2012 2019 - Apr lastSun 2:00 1:00 S
Rule Morocco 2012 max - Sep lastSun 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 9 3:00 0 -
+Rule Morocco 2013 only - Aug 8 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 - May 24 2:00 1:00 S
+Rule Morocco 2021 only - May 13 2:00 1:00 S
+Rule Morocco 2022 only - May 3 2:00 1:00 S
+Rule Morocco 2023 max - Apr lastSun 2:00 1:00 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
diff --git a/jdk/make/sun/javazic/tzdata/antarctica b/jdk/make/sun/javazic/tzdata/antarctica
index 64b71d5c052..daa03ea830c 100644
--- a/jdk/make/sun/javazic/tzdata/antarctica
+++ b/jdk/make/sun/javazic/tzdata/antarctica
@@ -73,38 +73,8 @@ Rule ChileAQ 2009 only - Mar Sun>=9 3:00u 0 -
Rule ChileAQ 2010 only - Apr Sun>=1 3:00u 0 -
Rule ChileAQ 2011 only - May Sun>=2 3:00u 0 -
Rule ChileAQ 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule ChileAQ 2012 only - Apr Sun>=23 3:00u 0 -
-Rule ChileAQ 2012 only - Sep Sun>=2 4:00u 1:00 S
-Rule ChileAQ 2013 max - Mar Sun>=9 3:00u 0 -
-Rule ChileAQ 2013 max - Oct Sun>=9 4:00u 1:00 S
-
-# These rules are stolen from the `australasia' file.
-Rule AusAQ 1917 only - Jan 1 0:01 1:00 -
-Rule AusAQ 1917 only - Mar 25 2:00 0 -
-Rule AusAQ 1942 only - Jan 1 2:00 1:00 -
-Rule AusAQ 1942 only - Mar 29 2:00 0 -
-Rule AusAQ 1942 only - Sep 27 2:00 1:00 -
-Rule AusAQ 1943 1944 - Mar lastSun 2:00 0 -
-Rule AusAQ 1943 only - Oct 3 2:00 1:00 -
-Rule ATAQ 1967 only - Oct Sun>=1 2:00s 1:00 -
-Rule ATAQ 1968 only - Mar lastSun 2:00s 0 -
-Rule ATAQ 1968 1985 - Oct lastSun 2:00s 1:00 -
-Rule ATAQ 1969 1971 - Mar Sun>=8 2:00s 0 -
-Rule ATAQ 1972 only - Feb lastSun 2:00s 0 -
-Rule ATAQ 1973 1981 - Mar Sun>=1 2:00s 0 -
-Rule ATAQ 1982 1983 - Mar lastSun 2:00s 0 -
-Rule ATAQ 1984 1986 - Mar Sun>=1 2:00s 0 -
-Rule ATAQ 1986 only - Oct Sun>=15 2:00s 1:00 -
-Rule ATAQ 1987 1990 - Mar Sun>=15 2:00s 0 -
-Rule ATAQ 1987 only - Oct Sun>=22 2:00s 1:00 -
-Rule ATAQ 1988 1990 - Oct lastSun 2:00s 1:00 -
-Rule ATAQ 1991 1999 - Oct Sun>=1 2:00s 1:00 -
-Rule ATAQ 1991 2005 - Mar lastSun 2:00s 0 -
-Rule ATAQ 2000 only - Aug lastSun 2:00s 1:00 -
-Rule ATAQ 2001 max - Oct Sun>=1 2:00s 1:00 -
-Rule ATAQ 2006 only - Apr Sun>=1 2:00s 0 -
-Rule ATAQ 2007 only - Mar lastSun 2:00s 0 -
-Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 -
+Rule ChileAQ 2012 max - Apr Sun>=23 3:00u 0 -
+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
@@ -147,10 +117,7 @@ Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 -
#
# From Steffen Thorsen (2010-03-10):
-# We got these changes from the Australian Antarctic Division:
-# - Macquarie Island will stay on UTC+11 for winter and therefore not
-# switch back from daylight savings time when other parts of Australia do
-# on 4 April.
+# We got these changes from the Australian Antarctic Division: ...
#
# - Casey station reverted to its normal time of UTC+8 on 5 March 2010.
# The change to UTC+11 is being considered as a regular summer thing but
@@ -161,9 +128,6 @@ Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 -
#
# - Mawson station stays on UTC+5.
#
-# In addition to the Rule changes for Casey/Davis, it means that Macquarie
-# will no longer be like Hobart and will have to have its own Zone created.
-#
# Background:
#
# http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
@@ -190,12 +154,6 @@ Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
6:00 - MAWT 2009 Oct 18 2:00
# Mawson Time
5:00 - MAWT
-Zone Antarctica/Macquarie 0 - zzz 1911
- 10:00 - EST 1916 Oct 1 2:00
- 10:00 1:00 EST 1917 Feb
- 10:00 AusAQ EST 1967
- 10:00 ATAQ EST 2010 Apr 4 3:00
- 11:00 - MIST # Macquarie Island Time
# References:
#
# Casey Weather (1998-02-26)
diff --git a/jdk/make/sun/javazic/tzdata/asia b/jdk/make/sun/javazic/tzdata/asia
index 9ef3ef8df54..7818c029a60 100644
--- a/jdk/make/sun/javazic/tzdata/asia
+++ b/jdk/make/sun/javazic/tzdata/asia
@@ -27,9 +27,9 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2013-02-21):
#
# A good source for time zone historical data outside the U.S. is
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -48,6 +48,10 @@
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
# 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
+# .
+#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
@@ -302,9 +306,12 @@ Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
8:00 - BNT
# Burma / Myanmar
+
+# 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:36 - RMT 1920 # Rangoon Mean Time?
+ 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
@@ -407,7 +414,8 @@ Zone Asia/Harbin 8:26:44 - LMT 1928 # or Haerbin
8:00 PRC C%sT
# Zhongyuan Time ("Central plain Time")
# most of China
-Zone Asia/Shanghai 8:05:52 - LMT 1928
+# 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)
@@ -504,6 +512,10 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar
8:00 PRC C%sT
+# Hong Kong (Xianggang)
+
+# Milne gives 7:36:41.7; round this.
+
# From Lee Yiu Chung (2009-10-24):
# I found there are some mistakes for the...DST rule for Hong
# Kong. [According] to the DST record from Hong Kong Observatory (actually,
@@ -570,7 +582,6 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar
# The Japanese surrender of Hong Kong was signed 1945-09-15.
# For lack of anything better, use start of those days as the transition times.
-# Hong Kong (Xianggang)
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule HK 1941 only - Apr 1 3:30 1:00 S
Rule HK 1941 only - Sep 30 3:30 0 -
@@ -592,7 +603,7 @@ Rule HK 1973 only - Dec 30 3:30 1:00 S
Rule HK 1979 only - May Sun>=8 3:30 1:00 S
Rule HK 1979 only - Oct Sun>=16 3:30 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30
+Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30
8:00 HK HK%sT 1941 Dec 25
9:00 - JST 1945 Sep 15
8:00 HK HK%sT
@@ -669,6 +680,9 @@ Zone Asia/Macau 7:34:20 - LMT 1912
###############################################################################
# Cyprus
+#
+# Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT.
+#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Cyprus 1975 only - Apr 13 0:00 1:00 S
Rule Cyprus 1975 only - Oct 12 0:00 0 -
@@ -1222,7 +1236,6 @@ Rule Zion 2012 only - Mar Fri>=26 2:00 1:00 D
Rule Zion 2012 only - Sep 23 2:00 0 S
# From Ephraim Silverberg (2012-10-18):
-
# Yesterday, the Interior Ministry Committee, after more than a year
# past, approved sending the proposed June 2011 changes to the Time
# Decree Law back to the Knesset for second and third (final) votes
@@ -1235,6 +1248,10 @@ Rule Zion 2012 only - Sep 23 2:00 0 S
# later (i.e. at 02:00 the first Monday after October 2).
# [Rosh Hashana holidays are factored in until 2100.]
+# From Ephraim Silverberg (2012-11-05):
+# The Knesset passed today (in second and final readings) the amendment to the
+# Time Decree Law making the changes ... law.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Zion 2013 max - Mar Fri>=23 2:00 1:00 D
Rule Zion 2013 2026 - Oct Sun>=2 2:00 0 S
@@ -1824,8 +1841,11 @@ Zone Asia/Kathmandu 5:41:16 - LMT 1920
5:45 - NPT # Nepal Time
# Oman
+
+# Milne says 3:54:24 was the meridian of the Muscat Tidal Observatory.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Muscat 3:54:20 - LMT 1920
+Zone Asia/Muscat 3:54:24 - LMT 1920
4:00 - GST
# Pakistan
@@ -2072,8 +2092,7 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# occurred before our cutoff date of 1970.
# However, as we get more information, we may need to add entries
# for parts of the West Bank as they transitioned from Israel's rules
-# to Palestine's rules. If you have more info about this, please
-# send it to tz@elsie.nci.nih.gov for incorporation into future editions.
+# to Palestine's rules.
# From IINS News Service - Israel - 1998-03-23 10:38:07 Israel time,
# forwarded by Ephraim Silverberg:
@@ -2295,11 +2314,20 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
#
-# From Arthur David Olson (2012-03-27):
-# The timeanddate article for 2012 says that "the end date has not yet been
-# announced" and that "Last year, both...paused daylight saving time during...
-# Ramadan. It is not yet known [for] 2012."
-# For now, assume both switch back on the last Friday in September. XXX
+# From Steffen Thorsen (2013-03-26):
+# The following news sources tells that Palestine will "start daylight saving
+# time from midnight on Friday, March 29, 2013" (translated).
+# [These are in Arabic and are for Gaza and for Ramallah, respectively.]
+# http://www.samanews.com/index.php?act=Show&id=154120
+# http://safa.ps/details/news/99844/%D8%B1%D8%A7%D9%85-%D8%A7%D9%84%D9%84%D9%87-%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-29-%D8%A7%D9%84%D8%AC%D8%A7%D8%B1%D9%8A.html
+
+# From Paul Eggert (2013-04-15):
+# For future dates, guess the last Thursday in March at 24:00 through
+# the first Friday on or after September 21 at 01:00. This is consistent with
+# the predictions in today's editions of the following URLs,
+# which are for Gaza and Hebron respectively:
+# http://www.timeanddate.com/worldclock/timezone.html?n=702
+# http://www.timeanddate.com/worldclock/timezone.html?n=2364
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
@@ -2313,19 +2341,20 @@ Rule Palestine 1999 2005 - Apr Fri>=15 0:00 1:00 S
Rule Palestine 1999 2003 - Oct Fri>=15 0:00 0 -
Rule Palestine 2004 only - Oct 1 1:00 0 -
Rule Palestine 2005 only - Oct 4 2:00 0 -
-Rule Palestine 2006 2008 - Apr 1 0:00 1:00 S
+Rule Palestine 2006 2007 - Apr 1 0:00 1:00 S
Rule Palestine 2006 only - Sep 22 0:00 0 -
Rule Palestine 2007 only - Sep Thu>=8 2:00 0 -
-Rule Palestine 2008 only - Aug lastFri 0:00 0 -
-Rule Palestine 2009 only - Mar lastFri 0:00 1:00 S
-Rule Palestine 2009 only - Sep Fri>=1 2:00 0 -
-Rule Palestine 2010 only - Mar lastSat 0:01 1:00 S
+Rule Palestine 2008 2009 - Mar lastFri 0:00 1:00 S
+Rule Palestine 2008 only - Sep 1 0:00 0 -
+Rule Palestine 2009 only - Sep Fri>=1 1:00 0 -
+Rule Palestine 2010 only - Mar 26 0:00 1:00 S
Rule Palestine 2010 only - Aug 11 0:00 0 -
-
-# From Arthur David Olson (2011-09-20):
-# 2011 transitions per http://www.timeanddate.com as of 2011-09-20.
-# From Paul Eggert (2012-10-12):
-# 2012 transitions per http://www.timeanddate.com as of 2012-10-12.
+Rule Palestine 2011 only - Apr 1 0:01 1:00 S
+Rule Palestine 2011 only - Aug 1 0:00 0 -
+Rule Palestine 2011 only - Aug 30 0:00 1:00 S
+Rule Palestine 2011 only - Sep 30 0:00 0 -
+Rule Palestine 2012 max - Mar lastThu 24:00 1:00 S
+Rule Palestine 2012 max - Sep Fri>=21 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@@ -2333,26 +2362,20 @@ 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 2011 Apr 2 12:01
- 2:00 1:00 EEST 2011 Aug 1
- 2:00 - EET 2012 Mar 30
- 2:00 1:00 EEST 2012 Sep 21 1:00
- 2:00 - EET
+ 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 Palestine EE%sT 2011 Aug 1
+ 2:00 - EET 2012
+ 2:00 Palestine EE%sT
Zone Asia/Hebron 2:20:23 - LMT 1900 Oct
2:00 Zion EET 1948 May 15
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
- 2:00 1:00 EEST 2008 Sep
- 2:00 Palestine EE%sT 2011 Apr 1 12:01
- 2:00 1:00 EEST 2011 Aug 1
- 2:00 - EET 2011 Aug 30
- 2:00 1:00 EEST 2011 Sep 30 3:00
- 2:00 - EET 2012 Mar 30
- 2:00 1:00 EEST 2012 Sep 21 1:00
- 2:00 - EET
+ 2:00 Palestine EE%sT
# Paracel Is
# no information
@@ -2421,6 +2444,13 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
# no information
# Sri Lanka
+
+# From Paul Eggert (2013-02-21):
+# Milne says "Madras mean time use from May 1, 1898. Prior to this Colombo
+# mean time, 5h. 4m. 21.9s. F., was used." But 5:04:21.9 differs considerably
+# from Colombo's meridian 5:19:24, so for now ignore Milne and stick with
+# Shanks and Pottenger.
+
# 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,
@@ -2720,6 +2750,12 @@ Zone Asia/Tashkent 4:37:12 - LMT 1924 May 2
# Vietnam
+# From Paul Eggert (2013-02-21):
+# Milne gives 7:16:56 for the meridian of Saigon in 1899, as being
+# used in Lower Laos, Cambodia, and Annam. But this is quite a ways
+# from Saigon's location. For now, ignore this and stick with Shanks
+# 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.
@@ -2733,6 +2769,10 @@ Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jun 9
7:00 - ICT
# Yemen
+
+# Milne says 2:59:54 was the meridian of the saluting battery at Aden,
+# and that Yemen was at 1:55:56, the meridian of the Hagia Sophia.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Aden 3:00:48 - LMT 1950
+Zone Asia/Aden 2:59:54 - LMT 1950
3:00 - AST
diff --git a/jdk/make/sun/javazic/tzdata/australasia b/jdk/make/sun/javazic/tzdata/australasia
index 7f83448f3fb..db954a81dcd 100644
--- a/jdk/make/sun/javazic/tzdata/australasia
+++ b/jdk/make/sun/javazic/tzdata/australasia
@@ -241,9 +241,26 @@ Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb
# no times are set
#
# Macquarie
-# permanent occupation (scientific station) since 1948;
-# sealing and penguin oil station operated 1888/1917
-# like Australia/Hobart
+# 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
+#
+# .
+# Guess that it was like Australia/Hobart while inhabited before 2010.
+#
+# From Steffen Thorsen (2010-03-10):
+# We got these changes from the Australian Antarctic Division:
+# - Macquarie Island will stay on UTC+11 for winter and therefore not
+# switch back from daylight savings time when other parts of Australia do
+# on 4 April.
+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
+ 0 - zzz 1948 Mar 25
+ 10:00 Aus EST 1967
+ 10:00 AT EST 2010 Apr 4 3:00
+ 11:00 - MIST # Macquarie I Standard Time
# Christmas
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -269,6 +286,9 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
6:30 - CCT # Cocos Islands Time
# Fiji
+
+# Milne gives 11:55:44 for Suva.
+
# From Alexander Krivenyshev (2009-11-10):
# According to Fiji Broadcasting Corporation, Fiji plans to re-introduce DST
# from November 29th 2009 to April 25th 2010.
@@ -362,7 +382,7 @@ Rule Fiji 2010 max - Oct Sun>=18 2:00 1:00 S
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
Rule Fiji 2012 max - Jan Sun>=18 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Fiji 11:53:40 - 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
@@ -803,9 +823,9 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2013-02-21):
# 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).
@@ -823,6 +843,10 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
# 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
+# .
+#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
diff --git a/jdk/make/sun/javazic/tzdata/europe b/jdk/make/sun/javazic/tzdata/europe
index 9a0d0b9db94..268504d0983 100644
--- a/jdk/make/sun/javazic/tzdata/europe
+++ b/jdk/make/sun/javazic/tzdata/europe
@@ -27,7 +27,7 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
# From Paul Eggert (2006-03-22):
# A good source for time zone historical data outside the U.S. is
@@ -53,6 +53,12 @@
# William Willett, The Waste of Daylight, 19th edition
# (1914-03)
#
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# . He writes:
+# "It is requested that corrections and additions to these tables
+# 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),
#
# History of Summer Time
@@ -689,6 +695,8 @@ Zone Europe/Andorra 0:06:04 - LMT 1901
# Austria
+# Milne says Vienna time was 1:05:21.
+
# From Paul Eggert (2006-03-22): Shanks & Pottenger give 1918-06-16 and
# 1945-11-18, but the Austrian Federal Office of Metrology and
# Surveying (BEV) gives 1918-09-16 and for Vienna gives the "alleged"
@@ -706,7 +714,7 @@ Rule Austria 1948 only - Apr 18 2:00s 1:00 S
Rule Austria 1980 only - Apr 6 0:00 1:00 S
Rule Austria 1980 only - Sep 28 0:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Vienna 1:05:20 - LMT 1893 Apr
+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
@@ -1262,6 +1270,21 @@ Zone Europe/Berlin 0:53:28 - LMT 1893 Apr
1:00 Germany CE%sT 1980
1:00 EU CE%sT
+# From Tobias Conradi (2011-09-12):
+# Busingen , 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:
+# 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.
+
+Link Europe/Zurich Europe/Busingen
+
# Georgia
# Please see the "asia" file for Asia/Tbilisi.
# Herodotus (Histories, IV.45) says Georgia north of the Phasis (now Rioni)
@@ -2066,6 +2089,70 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# 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).
+
+# From Arthur David Olson (2012-05-09):
+# Regarding the instant when clocks in time-zone-shifting parts of Russia
+# 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:
+# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which
+# 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).
+#
+# None of the sources indicates a time of day for changing clocks.
+#
+# Go with 2011-09-13 0:00s.
+
# 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,
@@ -2293,14 +2380,32 @@ Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15
# [parts of] Respublika Sakha (Yakutiya).
# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Bulunskij, Verkhoyanskij, Tomponskij, Ust'-Majskij,
-# Ust'-Yanskij.
+# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
Zone Asia/Vladivostok 8:47:44 - 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
+
+# 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 2004
+ 10:00 Russia VLA%sT 2011 Mar 27 2:00s
+ 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725?
+ 10:00 - YAKT
+
#
# Sakhalinskaya oblast'.
# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
@@ -2319,14 +2424,26 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
# From Oscar van Vlijmen (2009-11-29):
# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
-# Nizhnekolymskij, Ojmyakonskij, Srednekolymskij.
+# Nizhnekolymskij, ... Srednekolymskij.
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
-#
+
+# From Arthur David Olson (2012-05-09):
+# Ojmyakonskij and the Kuril Islands switched from
+# Magadan time to Vladivostok time in 2011.
+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
+
# From Oscar van Vlijmen (2001-08-25): [This region consists of]
# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
#
diff --git a/jdk/make/sun/javazic/tzdata/northamerica b/jdk/make/sun/javazic/tzdata/northamerica
index c3033267404..858bf811ac9 100644
--- a/jdk/make/sun/javazic/tzdata/northamerica
+++ b/jdk/make/sun/javazic/tzdata/northamerica
@@ -29,7 +29,7 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
# From Paul Eggert (1999-03-22):
# A reliable and entertaining source about time zones is
@@ -1042,6 +1042,9 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
# William Willett, The Waste of Daylight, 19th edition
# (1914-03)
#
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# .
+#
# See the `europe' file for Greenland.
# Canada
@@ -2577,6 +2580,8 @@ Zone America/Antigua -4:07:12 - LMT 1912 Mar 2
# Bahamas
#
+# For 1899 Milne gives -5:09:29.5; round that.
+#
# From Sue Williams (2006-12-07):
# The Bahamas announced about a month ago that they plan to change their DST
# rules to sync with the U.S. starting in 2007....
@@ -2586,11 +2591,14 @@ Zone America/Antigua -4:07:12 - LMT 1912 Mar 2
Rule Bahamas 1964 1975 - Oct lastSun 2:00 0 S
Rule Bahamas 1964 1975 - Apr lastSun 2:00 1:00 D
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Nassau -5:09:24 - LMT 1912 Mar 2
+Zone America/Nassau -5:09:30 - LMT 1912 Mar 2
-5:00 Bahamas E%sT 1976
-5:00 US E%sT
# Barbados
+
+# For 1899 Milne gives -3:58:29.2; round that.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Barb 1977 only - Jun 12 2:00 1:00 D
Rule Barb 1977 1978 - Oct Sun>=1 2:00 0 S
@@ -2598,8 +2606,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:28 - LMT 1924 # Bridgetown
- -3:58:28 - 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
@@ -2617,6 +2625,9 @@ Zone America/Belize -5:52:48 - LMT 1912 Apr
# Bermuda
+# For 1899 Milne gives -4:19:18.3 as the meridian of the clock tower,
+# Bermuda dockyard, Ireland I; round that.
+
# From Dan Jones, reporting in The Royal Gazette (2006-06-26):
# Next year, however, clocks in the US will go forward on the second Sunday
@@ -2626,7 +2637,7 @@ 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:04 - LMT 1930 Jan 1 2:00 # Hamilton
+Zone Atlantic/Bermuda -4:19:18 - LMT 1930 Jan 1 2:00 # Hamilton
-4:00 - AST 1974 Apr 28 2:00
-4:00 Bahamas A%sT 1976
-4:00 US A%sT
@@ -2638,6 +2649,9 @@ Zone America/Cayman -5:25:32 - LMT 1890 # Georgetown
-5:00 - EST
# Costa Rica
+
+# Milne gives -5:36:13.3 as San Jose 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
Rule CR 1979 1980 - Jun Sun>=1 0:00 0 S
@@ -2648,14 +2662,19 @@ 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'.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Costa_Rica -5:36:20 - LMT 1890 # San Jose
- -5:36:20 - SJMT 1921 Jan 15 # San Jose Mean Time
+Zone America/Costa_Rica -5:36:13 - LMT 1890 # San Jose
+ -5:36:13 - SJMT 1921 Jan 15 # San Jose Mean Time
-6:00 CR C%sT
# Coco
# no information; probably like America/Costa_Rica
# Cuba
+# From Paul Eggert (2013-02-21):
+# Milne gives -5:28:50.45 for the observatory at Havana, -5:29:23.57
+# for the port, and -5:30 for meteorological observations.
+# For now, stick with Shanks & Pottenger.
+
# From Arthur David Olson (1999-03-29):
# The 1999-03-28 exhibition baseball game held in Havana, Cuba, between
# the Cuban National Team and the Baltimore Orioles was carried live on
@@ -3004,24 +3023,21 @@ Zone America/Guatemala -6:02:04 - LMT 1918 Oct 5
# apparently using the same start and end date as USA/Canada.
# So this means they have already changed their time.
#
-# (Sources in French):
-#
# http://www.alterpresse.org/spip.php?article12510
-#
-#
# http://radiovision2000haiti.net/home/?p=13253
-#
#
-# Our coverage:
-#
-# http://www.timeanddate.com/news/time/haiti-dst-2012.html
-#
-
# From Arthur David Olson (2012-03-11):
# The alterpresse.org source seems to show a US-style leap from 2:00 a.m. to
# 3:00 a.m. rather than the traditional Haitian jump at midnight.
-# Assume a US-style fall back as well XXX.
-# Do not yet assume that the change carries forward past 2012 XXX.
+# Assume a US-style fall back as well.
+
+# From Steffen Thorsen (2013-03-10):
+# It appears that Haiti is observing DST this year as well, same rules
+# as US/Canada. They did it last year as well, and it looks like they
+# are going to observe DST every year now...
+#
+# http://radiovision2000haiti.net/public/haiti-avis-changement-dheure-dimanche/
+# http://www.canalplushaiti.net/?p=6714
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Haiti 1983 only - May 8 0:00 1:00 D
@@ -3033,8 +3049,8 @@ Rule Haiti 1988 1997 - Apr Sun>=1 1:00s 1:00 D
Rule Haiti 1988 1997 - Oct lastSun 1:00s 0 S
Rule Haiti 2005 2006 - Apr Sun>=1 0:00 1:00 D
Rule Haiti 2005 2006 - Oct lastSun 0:00 0 S
-Rule Haiti 2012 only - Mar Sun>=8 2:00 1:00 D
-Rule Haiti 2012 only - Nov Sun>=1 2:00 0 S
+Rule Haiti 2012 max - Mar Sun>=8 2:00 1:00 D
+Rule Haiti 2012 max - Nov Sun>=1 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Port-au-Prince -4:49:20 - LMT 1890
-4:49 - PPMT 1917 Jan 24 12:00 # P-a-P MT
diff --git a/jdk/make/sun/javazic/tzdata/southamerica b/jdk/make/sun/javazic/tzdata/southamerica
index 0d6797eab6b..d1865d3f19b 100644
--- a/jdk/make/sun/javazic/tzdata/southamerica
+++ b/jdk/make/sun/javazic/tzdata/southamerica
@@ -27,13 +27,17 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
# From Paul Eggert (2006-03-22):
# 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).
#
+# For data circa 1899, a common source is:
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# .
+#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
@@ -404,21 +408,11 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
#
# is the official page for the Province Government).
#
-# There's also a note in only one of the major national papers (La Nación) at
-#
+# There's also a note in only one of the major national papers ...
# http://www.lanacion.com.ar/nota.asp?nota_id=1107912
-#
#
-# The press release says:
-# (...) anunció que el próximo domingo a las 00:00 los puntanos deberán
-# atrasar una hora sus relojes.
-#
-# A partir de entonces, San Luis establecerá el huso horario propio de
-# la Provincia. De esta manera, durante el periodo del calendario anual
-# 2009, el cambio horario quedará comprendido entre las 00:00 del tercer
-# domingo de marzo y las 24:00 del segundo sábado de octubre.
-# Quick&dirty translation
-# (...) announced that next Sunday, at 00:00, Puntanos (the San Luis
+# The press release says [quick and dirty translation]:
+# ... announced that next Sunday, at 00:00, Puntanos (the San Luis
# inhabitants) will have to turn back one hour their clocks
#
# Since then, San Luis will establish its own Province timezone. Thus,
@@ -480,6 +474,9 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
# rules...San Luis is still using "Western ARgentina Time" and it got
# stuck on Summer daylight savings time even though the summer is over.
+# From Paul Eggert (2013-02-21):
+# Milne says Cordoba time was -4:16:48.2. Round to the nearest second.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
#
# Buenos Aires (BA), Capital Federal (CF),
@@ -835,9 +832,9 @@ Zone America/La_Paz -4:32:36 - LMT 1890
# 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 Brandão at
+# I just send a e-mail to Zulmira Brandao at
# http://pcdsh01.on.br/ the
-# oficial agency about time in Brazil, and she confirmed that the old rule is
+# official agency about time in Brazil, and she confirmed that the old rule is
# still in force.
# From Guilherme Bernardes Rodrigues (2011-10-14)
@@ -1266,9 +1263,13 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
# b. Saturday, September 1, 2012, clocks should go forward 60 minutes; that is,
# at 23:59:59, instead of passing to 0:00, the time should be adjusted to be
# 01:00 on September 2.
-#
-# Note that...this is yet another "temporary" change that will be reevaluated
-# AGAIN in 2013.
+
+# From Steffen Thorsen (2013-02-15):
+# According to several news sources, Chile has extended DST this year,
+# they will end DST later and start DST earlier than planned. They
+# hope to save energy. The new end date is 2013-04-28 00:00 and new
+# 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
# NOTE: ChileAQ rules for Antarctic bases are stored separately in the
# 'antarctica' file.
@@ -1311,10 +1312,8 @@ Rule Chile 2009 only - Mar Sun>=9 3:00u 0 -
Rule Chile 2010 only - Apr Sun>=1 3:00u 0 -
Rule Chile 2011 only - May Sun>=2 3:00u 0 -
Rule Chile 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule Chile 2012 only - Apr Sun>=23 3:00u 0 -
-Rule Chile 2012 only - Sep Sun>=2 4:00u 1:00 S
-Rule Chile 2013 max - Mar Sun>=9 3:00u 0 -
-Rule Chile 2013 max - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 2012 max - Apr Sun>=23 3:00u 0 -
+Rule Chile 2012 max - Sep Sun>=2 4:00u 1:00 S
# IATA SSIM anomalies: (1992-02) says 1992-03-14;
# (1996-09) says 1998-03-08. Ignore these.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -1336,17 +1335,23 @@ Zone Pacific/Easter -7:17:44 - LMT 1890
# San Felix, and Antarctic bases, are like America/Santiago.
# Colombia
+
+# Milne gives 4:56:16.4 for Bogota 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
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:20 - LMT 1884 Mar 13
- -4:56:20 - BMT 1914 Nov 23 # Bogota Mean Time
+Zone America/Bogota -4:56:16 - LMT 1884 Mar 13
+ -4:56:16 - BMT 1914 Nov 23 # Bogota Mean Time
-5:00 CO CO%sT # Colombia Time
# Malpelo, Providencia, San Andres
# no information; probably like America/Bogota
# Curacao
+
+# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
#
# From Paul Eggert (2006-03-22):
# Shanks & Pottenger say that The Bottom and Philipsburg have been at
@@ -1363,7 +1368,7 @@ Zone America/Bogota -4:56:20 - LMT 1884 Mar 13
# though, as far as we know.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Curacao -4:35:44 - 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
@@ -1377,6 +1382,8 @@ Link America/Curacao America/Kralendijk # Bonaire, Sint Estatius and Saba
# Ecuador
#
+# Milne says the Sentral 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.
# (2007-02-27) and
@@ -1582,7 +1589,16 @@ Rule Para 2005 2009 - Mar Sun>=8 0:00 0 -
# forward 60 minutes, in all the territory of the Paraguayan Republic.
# ...
Rule Para 2010 max - Oct Sun>=1 0:00 1:00 S
-Rule Para 2010 max - Apr Sun>=8 0:00 0 -
+Rule Para 2010 2012 - Apr Sun>=8 0:00 0 -
+#
+# From Steffen Thorsen (2013-03-07):
+# 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):
+# The change in Paraguay is now final. Decree number 10780
+# http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.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
diff --git a/jdk/make/sun/javazic/tzdata/zone.tab b/jdk/make/sun/javazic/tzdata/zone.tab
index ef380cd19fb..cbcdc075bf7 100644
--- a/jdk/make/sun/javazic/tzdata/zone.tab
+++ b/jdk/make/sun/javazic/tzdata/zone.tab
@@ -65,7 +65,6 @@ 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 -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I
-AQ -5430+15857 Antarctica/Macquarie Macquarie Island Station, Macquarie Island
AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF)
AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN)
@@ -81,6 +80,7 @@ AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
AS -1416-17042 Pacific/Pago_Pago
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
+AU -5430+15857 Antarctica/Macquarie Macquarie Island
AU -4253+14719 Australia/Hobart Tasmania - most locations
AU -3956+14352 Australia/Currie Tasmania - King Island
AU -3749+14458 Australia/Melbourne Victoria
@@ -182,7 +182,8 @@ CW +1211-06900 America/Curacao
CX -1025+10543 Indian/Christmas
CY +3510+03322 Asia/Nicosia
CZ +5005+01426 Europe/Prague
-DE +5230+01322 Europe/Berlin
+DE +5230+01322 Europe/Berlin most locations
+DE +4742+00841 Europe/Busingen Busingen
DJ +1136+04309 Africa/Djibouti
DK +5540+01235 Europe/Copenhagen
DM +1518-06124 America/Dominica
@@ -364,8 +365,10 @@ RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk
RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River
RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal
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
diff --git a/jdk/make/sun/nio/cs/Makefile b/jdk/make/sun/nio/cs/Makefile
index 73fe55fbd08..3b45c774fe0 100644
--- a/jdk/make/sun/nio/cs/Makefile
+++ b/jdk/make/sun/nio/cs/Makefile
@@ -87,9 +87,6 @@ build: $(FILES_genout_extcs) $(CHARSETS_JAR)
#
# Extra rules to build character converters.
-SERVICE_DESCRIPTION = java.nio.charset.spi.CharsetProvider
-SERVICE_DESCRIPTION_PATH = META-INF/services/$(SERVICE_DESCRIPTION)
-
GENCSDATASRC = $(BUILDDIR)/tools/CharsetMapping
GENCSSRCDIR = $(BUILDDIR)/tools/src/build/tools/charsetmapping
GENCSEXT = $(GENSRCDIR)/sun/nio/cs/ext
@@ -118,10 +115,6 @@ $(FILES_genout_extcs): \
$(GENCSSRCDIR)/HKSCS.java
$(BOOT_JAVA_CMD) -jar $(CHARSETMAPPING_JARFILE) $(GENCSDATASRC) $(GENCSEXT) dbcs
-$(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH): \
- $(SHARE_SRC)/classes/sun/nio/cs/ext/$(SERVICE_DESCRIPTION_PATH)
- $(install-file)
-
# no compression unless requested
ifndef COMPRESS_JARS
CREATE_JAR_OPTS_NOMANIFEST = cf0
@@ -129,10 +122,9 @@ else
CREATE_JAR_OPTS_NOMANIFEST = cf
endif
-$(CHARSETS_JAR): $(FILES_class) $(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH) $(FILES_DAT)
+$(CHARSETS_JAR): $(FILES_class) $(FILES_DAT)
$(BOOT_JAR_CMD) $(CREATE_JAR_OPTS_NOMANIFEST) $(CHARSETS_JAR) \
-C $(CLASSDESTDIR) sun \
- -C $(CLASSDESTDIR) $(SERVICE_DESCRIPTION_PATH) \
$(BOOT_JAR_JFLAGS)
@$(java-vm-cleanup)
diff --git a/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java b/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java
index f1185f18978..9cbf02a9c3b 100644
--- a/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java
+++ b/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java
@@ -34,6 +34,8 @@ import java.nio.file.Path;
import java.util.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
/**
@@ -234,6 +236,17 @@ public class CLDRConverter {
}
}
+ /**
+ * Configure the parser to allow access to DTDs on the file system.
+ */
+ private static void enableFileAccess(SAXParser parser) throws SAXNotSupportedException {
+ try {
+ parser.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "file");
+ } catch (SAXNotRecognizedException ignore) {
+ // property requires >= JAXP 1.5
+ }
+ }
+
private static List readBundleList() throws Exception {
ResourceBundle.Control defCon = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
List retList = new ArrayList<>();
@@ -279,6 +292,7 @@ public class CLDRConverter {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
SAXParser parser = factory.newSAXParser();
+ enableFileAccess(parser);
LDMLParseHandler handler = new LDMLParseHandler(id);
File file = new File(SOURCE_FILE_DIR + File.separator + id + ".xml");
if (!file.exists()) {
@@ -314,6 +328,7 @@ public class CLDRConverter {
SAXParserFactory factorySuppl = SAXParserFactory.newInstance();
factorySuppl.setValidating(true);
SAXParser parserSuppl = factorySuppl.newSAXParser();
+ enableFileAccess(parserSuppl);
handlerSuppl = new SupplementDataParseHandler();
File fileSupply = new File(SPPL_SOURCE_FILE);
parserSuppl.parse(fileSupply, handlerSuppl);
@@ -322,6 +337,7 @@ public class CLDRConverter {
SAXParserFactory numberingParser = SAXParserFactory.newInstance();
numberingParser.setValidating(true);
SAXParser parserNumbering = numberingParser.newSAXParser();
+ enableFileAccess(parserNumbering);
handlerNumbering = new NumberingSystemsParseHandler();
File fileNumbering = new File(NUMBERING_SOURCE_FILE);
parserNumbering.parse(fileNumbering, handlerNumbering);
@@ -330,6 +346,7 @@ public class CLDRConverter {
SAXParserFactory metazonesParser = SAXParserFactory.newInstance();
metazonesParser.setValidating(true);
SAXParser parserMetaZones = metazonesParser.newSAXParser();
+ enableFileAccess(parserMetaZones);
handlerMetaZones = new MetaZonesParseHandler();
File fileMetaZones = new File(METAZONES_SOURCE_FILE);
parserNumbering.parse(fileMetaZones, handlerMetaZones);
diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk
index 8127b054459..764e63486f5 100644
--- a/jdk/makefiles/CreateJars.gmk
+++ b/jdk/makefiles/CreateJars.gmk
@@ -201,7 +201,6 @@ RT_JAR_EXCLUDES += \
META-INF/services/com.sun.jdi.connect.spi.TransportService \
META-INF/services/com.sun.tools.attach.spi.AttachProvider \
META-INF/services/com.sun.tools.xjc.Plugin \
- META-INF/services/java.nio.charset.spi.CharsetProvider \
META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor \
org/relaxng/datatype \
sun/awt/HKSCS.class \
@@ -428,8 +427,7 @@ $(eval $(call SetupArchive,BUILD_CHARSETS_JAR,,\
SUFFIXES:=.class .dat,\
INCLUDES:=sun/nio/cs/ext,\
EXTRA_FILES := sun/awt/HKSCS.class \
- $(CHARSETS_EXTRA_FILES) \
- META-INF/services/java.nio.charset.spi.CharsetProvider, \
+ $(CHARSETS_EXTRA_FILES), \
JAR:=$(IMAGES_OUTPUTDIR)/lib/charsets.jar, \
SKIP_METAINF := true, \
CHECK_COMPRESS_JAR:=true))
diff --git a/jdk/src/share/classes/java/lang/ProcessBuilder.java b/jdk/src/share/classes/java/lang/ProcessBuilder.java
index 64f56d77829..b467f45c351 100644
--- a/jdk/src/share/classes/java/lang/ProcessBuilder.java
+++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java
@@ -29,7 +29,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.FileOutputStream;
import java.security.AccessControlException;
import java.util.Arrays;
import java.util.ArrayList;
@@ -1024,10 +1023,10 @@ public final class ProcessBuilder
dir,
redirects,
redirectErrorStream);
- } catch (IOException e) {
+ } catch (IOException | IllegalArgumentException e) {
String exceptionInfo = ": " + e.getMessage();
Throwable cause = e;
- if (security != null) {
+ if ((e instanceof IOException) && security != null) {
// Can not disclose the fail reason for read-protected files.
try {
security.checkRead(prog);
diff --git a/jdk/src/share/classes/java/lang/StringBuffer.java b/jdk/src/share/classes/java/lang/StringBuffer.java
index f31a53c98e6..8ead0721ffd 100644
--- a/jdk/src/share/classes/java/lang/StringBuffer.java
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, 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
@@ -25,6 +25,7 @@
package java.lang;
+import java.util.Arrays;
/**
* A thread-safe, mutable sequence of characters.
@@ -98,6 +99,12 @@ package java.lang;
implements java.io.Serializable, CharSequence
{
+ /**
+ * A cache of the last value returned by toString. Cleared
+ * whenever the StringBuffer is modified.
+ */
+ private transient char[] toStringCache;
+
/** use serialVersionUID from JDK 1.0.2 for interoperability */
static final long serialVersionUID = 3388685877147921107L;
@@ -183,6 +190,7 @@ package java.lang;
*/
@Override
public synchronized void setLength(int newLength) {
+ toStringCache = null;
super.setLength(newLength);
}
@@ -247,17 +255,20 @@ package java.lang;
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
+ toStringCache = null;
value[index] = ch;
}
@Override
public synchronized StringBuffer append(Object obj) {
+ toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
@Override
public synchronized StringBuffer append(String str) {
+ toStringCache = null;
super.append(str);
return this;
}
@@ -287,6 +298,7 @@ package java.lang;
* @since 1.4
*/
public synchronized StringBuffer append(StringBuffer sb) {
+ toStringCache = null;
super.append(sb);
return this;
}
@@ -296,6 +308,7 @@ package java.lang;
*/
@Override
synchronized StringBuffer append(AbstractStringBuilder asb) {
+ toStringCache = null;
super.append(asb);
return this;
}
@@ -325,6 +338,7 @@ package java.lang;
public StringBuffer append(CharSequence s) {
// Note, synchronization achieved via invocations of other StringBuffer methods after
// narrowing of s to specific type
+ // Ditto for toStringCache clearing
super.append(s);
return this;
}
@@ -336,12 +350,14 @@ package java.lang;
@Override
public synchronized StringBuffer append(CharSequence s, int start, int end)
{
+ toStringCache = null;
super.append(s, start, end);
return this;
}
@Override
public synchronized StringBuffer append(char[] str) {
+ toStringCache = null;
super.append(str);
return this;
}
@@ -351,24 +367,28 @@ package java.lang;
*/
@Override
public synchronized StringBuffer append(char[] str, int offset, int len) {
+ toStringCache = null;
super.append(str, offset, len);
return this;
}
@Override
public synchronized StringBuffer append(boolean b) {
+ toStringCache = null;
super.append(b);
return this;
}
@Override
public synchronized StringBuffer append(char c) {
+ toStringCache = null;
super.append(c);
return this;
}
@Override
public synchronized StringBuffer append(int i) {
+ toStringCache = null;
super.append(i);
return this;
}
@@ -378,24 +398,28 @@ package java.lang;
*/
@Override
public synchronized StringBuffer appendCodePoint(int codePoint) {
+ toStringCache = null;
super.appendCodePoint(codePoint);
return this;
}
@Override
public synchronized StringBuffer append(long lng) {
+ toStringCache = null;
super.append(lng);
return this;
}
@Override
public synchronized StringBuffer append(float f) {
+ toStringCache = null;
super.append(f);
return this;
}
@Override
public synchronized StringBuffer append(double d) {
+ toStringCache = null;
super.append(d);
return this;
}
@@ -406,6 +430,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer delete(int start, int end) {
+ toStringCache = null;
super.delete(start, end);
return this;
}
@@ -416,6 +441,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer deleteCharAt(int index) {
+ toStringCache = null;
super.deleteCharAt(index);
return this;
}
@@ -426,6 +452,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
+ toStringCache = null;
super.replace(start, end, str);
return this;
}
@@ -465,6 +492,7 @@ package java.lang;
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
+ toStringCache = null;
super.insert(index, str, offset, len);
return this;
}
@@ -474,6 +502,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
+ toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}
@@ -483,6 +512,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer insert(int offset, String str) {
+ toStringCache = null;
super.insert(offset, str);
return this;
}
@@ -492,6 +522,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer insert(int offset, char[] str) {
+ toStringCache = null;
super.insert(offset, str);
return this;
}
@@ -504,6 +535,7 @@ package java.lang;
public StringBuffer insert(int dstOffset, CharSequence s) {
// Note, synchronization achieved via invocations of other StringBuffer methods
// after narrowing of s to specific type
+ // Ditto for toStringCache clearing
super.insert(dstOffset, s);
return this;
}
@@ -516,6 +548,7 @@ package java.lang;
public synchronized StringBuffer insert(int dstOffset, CharSequence s,
int start, int end)
{
+ toStringCache = null;
super.insert(dstOffset, s, start, end);
return this;
}
@@ -527,6 +560,7 @@ package java.lang;
public StringBuffer insert(int offset, boolean b) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of b to String by super class method
+ // Ditto for toStringCache clearing
super.insert(offset, b);
return this;
}
@@ -536,6 +570,7 @@ package java.lang;
*/
@Override
public synchronized StringBuffer insert(int offset, char c) {
+ toStringCache = null;
super.insert(offset, c);
return this;
}
@@ -547,6 +582,7 @@ package java.lang;
public StringBuffer insert(int offset, int i) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of i to String by super class method
+ // Ditto for toStringCache clearing
super.insert(offset, i);
return this;
}
@@ -558,6 +594,7 @@ package java.lang;
public StringBuffer insert(int offset, long l) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of l to String by super class method
+ // Ditto for toStringCache clearing
super.insert(offset, l);
return this;
}
@@ -569,6 +606,7 @@ package java.lang;
public StringBuffer insert(int offset, float f) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of f to String by super class method
+ // Ditto for toStringCache clearing
super.insert(offset, f);
return this;
}
@@ -580,6 +618,7 @@ package java.lang;
public StringBuffer insert(int offset, double d) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of d to String by super class method
+ // Ditto for toStringCache clearing
super.insert(offset, d);
return this;
}
@@ -623,13 +662,17 @@ package java.lang;
*/
@Override
public synchronized StringBuffer reverse() {
+ toStringCache = null;
super.reverse();
return this;
}
@Override
public synchronized String toString() {
- return new String(value, 0, count);
+ if (toStringCache == null) {
+ toStringCache = Arrays.copyOfRange(value, 0, count);
+ }
+ return new String(toStringCache, true);
}
/**
diff --git a/jdk/src/share/classes/java/net/HttpURLConnection.java b/jdk/src/share/classes/java/net/HttpURLConnection.java
index d52c26789fa..193b9cef1c1 100644
--- a/jdk/src/share/classes/java/net/HttpURLConnection.java
+++ b/jdk/src/share/classes/java/net/HttpURLConnection.java
@@ -50,6 +50,18 @@ import java.util.Date;
* Proxy settings as well as
* various other settings .
*
+ *
+ * Security permissions
+ *
+ * If a security manager is installed, and if a method is called which results in an
+ * attempt to open a connection, the caller must possess either:-
+ *
a "connect" {@link SocketPermission} to the host/port combination of the
+ * destination URL or
+ * a {@link HttpURLPermission} that permits this request.
+ *
+ * If automatic redirection is enabled, and this request is redirected to another
+ * destination, then the caller must also have permission to connect to the
+ * redirected host/URL.
*
* @see java.net.HttpURLConnection#disconnect()
* @since JDK1.1
diff --git a/jdk/src/share/classes/java/net/HttpURLPermission.java b/jdk/src/share/classes/java/net/HttpURLPermission.java
new file mode 100644
index 00000000000..52d6e79344a
--- /dev/null
+++ b/jdk/src/share/classes/java/net/HttpURLPermission.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2013, 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.net;
+
+import java.io.ObjectInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.security.Permission;
+
+/**
+ * Represents permission to access a resource or set of resources defined by a
+ * given http or https url, and for a given set of user-settable request methods
+ * and request headers. The name of the permission is the url string.
+ * The actions string is a concatenation of the request methods and headers.
+ * The range of method and header names is not restricted by this class.
+ *
The url
+ * The url string is also used to instantiate a {@link URI} object which is
+ * used for comparison with other HttpURLPermission instances. Therefore, any
+ * references in this specification to url, mean this URI object.
+ * The path component of the url comprises a sequence of path segments, separated
+ * by '/' characters. The path is specified in a similar way to the path
+ * in {@link java.io.FilePermission}. There are three different ways
+ * as the following examples show:
+ *
+ * Example url Description
+ * http://www.oracle.com/a/b/c.html
+ * A url which identifies a specific (single) resource
+ *
+ * http://www.oracle.com/a/b/*
+ * The '*' character refers to all resources in the same "directory" - in
+ * other words all resources with the same number of path components, and
+ * which only differ in the final path component, represented by the '*'.
+ *
+ *
+ * http://www.oracle.com/a/b/-
+ * The '-' character refers to all resources recursively below the
+ * preceding path (eg. http://www.oracle.com/a/b/c/d/e.html matches this
+ * example).
+ *
+ *
+ *
+ *
+ * The '*' and '-' may only be specified in the final segment of a path and must be
+ * the only character in that segment. Any query or fragment components of the
+ * url are ignored when constructing HttpURLPermissions.
+ *
+ * As a special case, urls of the form, "http:*" or "https:*" are accepted to
+ * mean any url of the given scheme.
+ *
The actions string
+ * The actions string of a HttpURLPermission is a concatenation of the method list
+ * and the request headers list . These are lists of the permitted HTTP request
+ * methods and permitted request headers of the permission (respectively). The two lists
+ * are separated by a colon ':' character and elements of each list are comma separated.
+ * Some examples are:
+ *
+ * "POST,GET,DELETE"
+ * "GET:X-Foo-Request,X-Bar-Request"
+ * "POST,GET:Header1,Header2"
+ *
+ * The first example specifies the methods: POST, GET and DELETE, but no request headers.
+ * The second example specifies one request method and two headers. The third
+ * example specifies two request methods, and two headers.
+ *
+ * The colon separator need not be present if the request headers list is empty.
+ * No white-space is permitted in the actions string. The action strings supplied to
+ * the HttpURLPermission constructors are case-insensitive and are normalized by converting
+ * method names to upper-case and header names to the form defines in RFC2616 (lower case
+ * with initial letter of each word capitalized). Either list can contain a wild-card '*'
+ * character which signifies all request methods or headers respectively.
+ *
+ * Note. Depending on the context of use, some request methods and headers may be permitted
+ * at all times, and others may not be permitted at any time. For example, the
+ * HTTP protocol handler might disallow certain headers such as Content-Length
+ * from being set by application code, regardless of whether the security policy
+ * in force, permits it.
+ *
+ * @since 1.8
+ */
+public final class HttpURLPermission extends Permission {
+
+ private static final long serialVersionUID = -2702463814894478682L;
+
+ private transient URI uri;
+ private transient List methods;
+ private transient List requestHeaders;
+
+ // serialized field
+ private String actions;
+
+ /**
+ * Creates a new HttpURLPermission from a url string and which permits the given
+ * request methods and user-settable request headers.
+ * The name of the permission is its url string. Only the scheme, authority
+ * and path components of the url are used. Any fragment or query
+ * components are ignored. The permissions action string is as specified above.
+ *
+ * @param url the url string
+ *
+ * @param actions the actions string
+ *
+ * @throws IllegalArgumentException if url does not result in a valid {@link URI},
+ * its scheme is not http or https, or if actions contains white-space.
+ */
+ public HttpURLPermission(String url, String actions) {
+ super(url);
+ init(actions);
+ }
+
+ private void init(String actions) {
+ URI uri = parseURI(getName());
+ int colon = actions.indexOf(':');
+ if (actions.lastIndexOf(':') != colon) {
+ throw new IllegalArgumentException("invalid actions string");
+ }
+
+ String methods, headers;
+ if (colon == -1) {
+ methods = actions;
+ headers = "";
+ } else {
+ methods = actions.substring(0, colon);
+ headers = actions.substring(colon+1);
+ }
+
+ List l = normalizeMethods(methods);
+ Collections.sort(l);
+ this.methods = Collections.unmodifiableList(l);
+
+ l = normalizeHeaders(headers);
+ Collections.sort(l);
+ this.requestHeaders = Collections.unmodifiableList(l);
+
+ this.actions = actions();
+ this.uri = uri;
+ }
+
+ /**
+ * Creates a HttpURLPermission with the given url string and unrestricted
+ * methods and request headers by invoking the two argument
+ * constructor as follows: HttpURLPermission(url, "*:*")
+ *
+ * @throws IllegalArgumentException if url does not result in a valid {@link URI}
+ */
+ public HttpURLPermission(String url) {
+ this(url, "*:*");
+ }
+
+ /**
+ * Returns the normalized method list and request
+ * header list, in the form:
+ *
+ * "method-names : header-names"
+ *
+ *
+ * where method-names is the list of methods separated by commas
+ * and header-names is the list of permitted headers separated by commas.
+ * There is no white space in the returned String. If header-names is empty
+ * then the colon separator will not be present.
+ */
+ public String getActions() {
+ return actions;
+ }
+
+ /**
+ * Checks if this HttpURLPermission implies the given permission.
+ * Specifically, the following checks are done as if in the
+ * following sequence:
+ *
*
* All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
@@ -1007,7 +1004,6 @@ public final class LocalTime
case MINUTES: return plusMinutes(amountToAdd);
case HOURS: return plusHours(amountToAdd);
case HALF_DAYS: return plusHours((amountToAdd % 2) * 12);
- case DAYS: return this;
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
}
@@ -1291,19 +1287,19 @@ public final class LocalTime
}
/**
- * Calculates the period between this time and another time in
- * terms of the specified unit.
+ * Calculates the amount of time until another time in terms of the specified unit.
*
- * This calculates the period between two times in terms of a single unit.
+ * This calculates the amount of time between two {@code LocalTime}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified time.
* The result will be negative if the end is before the start.
* The {@code Temporal} passed to this method must be a {@code LocalTime}.
- * For example, the period in hours between two times can be calculated
+ * For example, the amount in hours between two times can be calculated
* using {@code startTime.periodUntil(endTime, HOURS)}.
*
* The calculation returns a whole number, representing the number of
* complete units between the two times.
- * For example, the period in hours between 11:30 and 13:29 will only
+ * For example, the amount in hours between 11:30 and 13:29 will only
* be one hour as it is one minute short of two hours.
*
* There are two equivalent ways of using this method.
@@ -1329,9 +1325,9 @@ public final class LocalTime
* This instance is immutable and unaffected by this method call.
*
* @param endTime the end time, which must be a {@code LocalTime}, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this time and the end time
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this time and the end time
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@@ -1339,7 +1335,7 @@ public final class LocalTime
public long periodUntil(Temporal endTime, TemporalUnit unit) {
if (endTime instanceof LocalTime == false) {
Objects.requireNonNull(endTime, "endTime");
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
LocalTime end = (LocalTime) endTime;
if (unit instanceof ChronoUnit) {
diff --git a/jdk/src/share/classes/java/time/Month.java b/jdk/src/share/classes/java/time/Month.java
index 175d0517e2b..272e8f96b36 100644
--- a/jdk/src/share/classes/java/time/Month.java
+++ b/jdk/src/share/classes/java/time/Month.java
@@ -97,7 +97,7 @@ import java.util.Locale;
* As such, this enum may be used by any calendar system that has the month-of-year
* concept defined exactly equivalent to the ISO-8601 calendar system.
*
- *
Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/MonthDay.java b/jdk/src/share/classes/java/time/MonthDay.java
index 276e869d10e..4204ef74a7d 100644
--- a/jdk/src/share/classes/java/time/MonthDay.java
+++ b/jdk/src/share/classes/java/time/MonthDay.java
@@ -111,7 +111,7 @@ import java.util.Objects;
* However, any application that makes use of historical dates, and requires them
* to be accurate will find the ISO-8601 approach unsuitable.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/OffsetDateTime.java b/jdk/src/share/classes/java/time/OffsetDateTime.java
index aa4c7281c95..b053085a9f5 100644
--- a/jdk/src/share/classes/java/time/OffsetDateTime.java
+++ b/jdk/src/share/classes/java/time/OffsetDateTime.java
@@ -111,7 +111,7 @@ import java.util.Objects;
* in simpler applications. This class may be used when modeling date-time concepts in
* more detail, or when communicating to a database or in a network protocol.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -1521,10 +1521,10 @@ public final class OffsetDateTime
}
/**
- * Calculates the period between this date-time and another date-time in
- * terms of the specified unit.
+ * Calculates the amount of time until another date-time in terms of the specified unit.
*
- * This calculates the period between two date-times in terms of a single unit.
+ * This calculates the amount of time between two {@code OffsetDateTime}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified date-time.
* The result will be negative if the end is before the start.
* For example, the period in days between two date-times can be calculated
@@ -1564,9 +1564,9 @@ public final class OffsetDateTime
* This instance is immutable and unaffected by this method call.
*
* @param endDateTime the end date-time, which must be an {@code OffsetDateTime}, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this date-time and the end date-time
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this date-time and the end date-time
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@@ -1574,7 +1574,7 @@ public final class OffsetDateTime
public long periodUntil(Temporal endDateTime, TemporalUnit unit) {
if (endDateTime instanceof OffsetDateTime == false) {
Objects.requireNonNull(endDateTime, "endDateTime");
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
if (unit instanceof ChronoUnit) {
OffsetDateTime end = (OffsetDateTime) endDateTime;
diff --git a/jdk/src/share/classes/java/time/OffsetTime.java b/jdk/src/share/classes/java/time/OffsetTime.java
index c6afcb26e49..ff990696942 100644
--- a/jdk/src/share/classes/java/time/OffsetTime.java
+++ b/jdk/src/share/classes/java/time/OffsetTime.java
@@ -102,7 +102,7 @@ import java.util.Objects;
* For example, the value "13:45.30.123456789+02:00" can be stored
* in an {@code OffsetTime}.
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -1077,10 +1077,10 @@ public final class OffsetTime
}
/**
- * Calculates the period between this time and another time in
- * terms of the specified unit.
+ * Calculates the amount of time until another time in terms of the specified unit.
*
- * This calculates the period between two times in terms of a single unit.
+ * This calculates the amount of time between two {@code OffsetTime}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified time.
* The result will be negative if the end is before the start.
* For example, the period in hours between two times can be calculated
@@ -1118,9 +1118,9 @@ public final class OffsetTime
* This instance is immutable and unaffected by this method call.
*
* @param endTime the end time, which must be an {@code OffsetTime}, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this time and the end time
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this time and the end time
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@@ -1128,7 +1128,7 @@ public final class OffsetTime
public long periodUntil(Temporal endTime, TemporalUnit unit) {
if (endTime instanceof OffsetTime == false) {
Objects.requireNonNull(endTime, "endTime");
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
if (unit instanceof ChronoUnit) {
OffsetTime end = (OffsetTime) endTime;
diff --git a/jdk/src/share/classes/java/time/Period.java b/jdk/src/share/classes/java/time/Period.java
index 85980d9d874..b2748f089ce 100644
--- a/jdk/src/share/classes/java/time/Period.java
+++ b/jdk/src/share/classes/java/time/Period.java
@@ -119,7 +119,7 @@ import java.util.regex.Pattern;
* The months and years fields may be {@linkplain #normalized() normalized}.
* The normalization assumes a 12 month year, so is not appropriate for all calendar systems.
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/Ser.java b/jdk/src/share/classes/java/time/Ser.java
index 401a7cd832a..607198952c1 100644
--- a/jdk/src/share/classes/java/time/Ser.java
+++ b/jdk/src/share/classes/java/time/Ser.java
@@ -66,7 +66,7 @@ import java.io.StreamCorruptedException;
/**
* The shared serialization delegate for this package.
*
- * Implementation notes
+ * @implNote
* This class wraps the object being serialized, and takes a byte representing the type of the class to
* be serialized. This byte can also be used for versioning the serialization format. In this case another
* byte flag would be used in order to specify an alternative version of the type format.
diff --git a/jdk/src/share/classes/java/time/Year.java b/jdk/src/share/classes/java/time/Year.java
index 2ef92b53885..c2d9974d79a 100644
--- a/jdk/src/share/classes/java/time/Year.java
+++ b/jdk/src/share/classes/java/time/Year.java
@@ -115,7 +115,7 @@ import java.util.Objects;
* However, any application that makes use of historical dates, and requires them
* to be accurate will find the ISO-8601 approach unsuitable.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -813,10 +813,10 @@ public final class Year
}
/**
- * Calculates the period between this year and another year in
- * terms of the specified unit.
+ * Calculates the amount of time until another year in terms of the specified unit.
*
- * This calculates the period between two years in terms of a single unit.
+ * This calculates the amount of time between two {@code Year}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified year.
* The result will be negative if the end is before the start.
* The {@code Temporal} passed to this method must be a {@code Year}.
@@ -851,9 +851,9 @@ public final class Year
* This instance is immutable and unaffected by this method call.
*
* @param endYear the end year, which must be a {@code Year}, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this year and the end year
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this year and the end year
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@@ -861,7 +861,7 @@ public final class Year
public long periodUntil(Temporal endYear, TemporalUnit unit) {
if (endYear instanceof Year == false) {
Objects.requireNonNull(endYear, "endYear");
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
Year end = (Year) endYear;
if (unit instanceof ChronoUnit) {
diff --git a/jdk/src/share/classes/java/time/YearMonth.java b/jdk/src/share/classes/java/time/YearMonth.java
index 312a36cd3f7..855774eed1a 100644
--- a/jdk/src/share/classes/java/time/YearMonth.java
+++ b/jdk/src/share/classes/java/time/YearMonth.java
@@ -110,7 +110,7 @@ import java.util.Objects;
* However, any application that makes use of historical dates, and requires them
* to be accurate will find the ISO-8601 approach unsuitable.
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -944,10 +944,10 @@ public final class YearMonth
}
/**
- * Calculates the period between this year-month and another year-month in
- * terms of the specified unit.
+ * Calculates the amount of time until another year-month in terms of the specified unit.
*
- * This calculates the period between two year-months in terms of a single unit.
+ * This calculates the amount of time between two {@code YearMonth}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified year-month.
* The result will be negative if the end is before the start.
* The {@code Temporal} passed to this method must be a {@code YearMonth}.
@@ -982,9 +982,9 @@ public final class YearMonth
* This instance is immutable and unaffected by this method call.
*
* @param endYearMonth the end year-month, which must be a {@code YearMonth}, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this year-month and the end year-month
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this year-month and the end year-month
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@@ -992,7 +992,7 @@ public final class YearMonth
public long periodUntil(Temporal endYearMonth, TemporalUnit unit) {
if (endYearMonth instanceof YearMonth == false) {
Objects.requireNonNull(endYearMonth, "endYearMonth");
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
YearMonth end = (YearMonth) endYearMonth;
if (unit instanceof ChronoUnit) {
diff --git a/jdk/src/share/classes/java/time/ZoneId.java b/jdk/src/share/classes/java/time/ZoneId.java
index 38a2a7ca289..026f73ef512 100644
--- a/jdk/src/share/classes/java/time/ZoneId.java
+++ b/jdk/src/share/classes/java/time/ZoneId.java
@@ -157,7 +157,7 @@ import java.util.TimeZone;
* This approach is designed to allow a {@link ZonedDateTime} to be loaded and
* queried, but not modified, on a Java Runtime with incomplete time-zone information.
*
- *
Specification for implementors
+ * @implSpec
* This abstract class has two implementations, both of which are immutable and thread-safe.
* One implementation models region-based IDs, the other is {@code ZoneOffset} modelling
* offset-based IDs. This difference is visible in serialization.
diff --git a/jdk/src/share/classes/java/time/ZoneOffset.java b/jdk/src/share/classes/java/time/ZoneOffset.java
index 00f5dce485f..4bbc4e4fa84 100644
--- a/jdk/src/share/classes/java/time/ZoneOffset.java
+++ b/jdk/src/share/classes/java/time/ZoneOffset.java
@@ -114,7 +114,7 @@ import java.util.concurrent.ConcurrentMap;
* Implementations may choose to cache certain common offsets, however
* applications must not rely on such caching.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/ZoneRegion.java b/jdk/src/share/classes/java/time/ZoneRegion.java
index 912ee0499d3..af6a5405a69 100644
--- a/jdk/src/share/classes/java/time/ZoneRegion.java
+++ b/jdk/src/share/classes/java/time/ZoneRegion.java
@@ -83,7 +83,7 @@ import java.util.regex.Pattern;
* By contrast, the region identifier is well-defined and long-lived.
* This separation also allows rules to be shared between regions if appropriate.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/ZonedDateTime.java b/jdk/src/share/classes/java/time/ZonedDateTime.java
index f5115c66873..e7ed5551d33 100644
--- a/jdk/src/share/classes/java/time/ZonedDateTime.java
+++ b/jdk/src/share/classes/java/time/ZonedDateTime.java
@@ -142,7 +142,7 @@ import java.util.Objects;
* a vital, but secondary, piece of information, used to ensure that the class
* represents an instant, especially during a daylight savings overlap.
*
- * Specification for implementors
+ * @implSpec
* A {@code ZonedDateTime} holds state equivalent to three separate objects,
* a {@code LocalDateTime}, a {@code ZoneId} and the resolved {@code ZoneOffset}.
* The offset and local date-time are used to define an instant when necessary.
@@ -1983,10 +1983,10 @@ public final class ZonedDateTime
}
/**
- * Calculates the period between this date-time and another date-time in
- * terms of the specified unit.
+ * Calculates the amount of time until another date-time in terms of the specified unit.
*
- * This calculates the period between two date-times in terms of a single unit.
+ * This calculates the amount of time between two {@code ZonedDateTime}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified date-time.
* The result will be negative if the end is before the start.
* For example, the period in days between two date-times can be calculated
@@ -2040,9 +2040,9 @@ public final class ZonedDateTime
* This instance is immutable and unaffected by this method call.
*
* @param endDateTime the end date-time, which must be a {@code ZonedDateTime}, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this date-time and the end date-time
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this date-time and the end date-time
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
@@ -2050,7 +2050,7 @@ public final class ZonedDateTime
public long periodUntil(Temporal endDateTime, TemporalUnit unit) {
if (endDateTime instanceof ZonedDateTime == false) {
Objects.requireNonNull(endDateTime, "endDateTime");
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
if (unit instanceof ChronoUnit) {
ZonedDateTime end = (ZonedDateTime) endDateTime;
diff --git a/jdk/src/share/classes/java/time/chrono/ChronoDateImpl.java b/jdk/src/share/classes/java/time/chrono/ChronoDateImpl.java
index 26203faa0af..14e2bf58f2a 100644
--- a/jdk/src/share/classes/java/time/chrono/ChronoDateImpl.java
+++ b/jdk/src/share/classes/java/time/chrono/ChronoDateImpl.java
@@ -130,7 +130,7 @@ import java.util.Objects;
* The subclass must function according to the {@code Chronology} class description and must provide its
* {@link java.time.chrono.Chronology#getId() chronlogy ID} and {@link Chronology#getCalendarType() calendar type}.
*
- * Specification for implementors
+ * @implSpec
* This abstract class must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Subclasses should be Serializable wherever possible.
@@ -325,11 +325,11 @@ abstract class ChronoDateImpl>
Objects.requireNonNull(endDateTime, "endDateTime");
Objects.requireNonNull(unit, "unit");
if (endDateTime instanceof ChronoLocalDate == false) {
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
ChronoLocalDate> end = (ChronoLocalDate>) endDateTime;
if (getChronology().equals(end.getChronology()) == false) {
- throw new DateTimeException("Unable to calculate period between two different chronologies");
+ throw new DateTimeException("Unable to calculate amount as objects have different chronologies");
}
if (unit instanceof ChronoUnit) {
switch ((ChronoUnit) unit) {
diff --git a/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java b/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java
index 4f648c93725..31c08260d6e 100644
--- a/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java
+++ b/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java
@@ -234,7 +234,7 @@ import java.util.Objects;
* Use {@link TemporalAccessor} if read-only access is required, or use {@link Temporal}
* if read-write access is required.
*
- * Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Subclasses should be Serializable wherever possible.
@@ -257,6 +257,7 @@ public interface ChronoLocalDate>
* This allows dates in different calendar systems to be compared based
* on the position of the date on the local time-line.
* The underlying comparison is equivalent to comparing the epoch-day.
+ * @return a comparator that compares in time-line order ignoring the chronology
*
* @see #isAfter
* @see #isBefore
@@ -510,17 +511,17 @@ public interface ChronoLocalDate>
}
/**
- * Calculates the period between this date and another date in
- * terms of the specified unit.
+ * Calculates the amount of time until another date in terms of the specified unit.
*
- * This calculates the period between two dates in terms of a single unit.
+ * This calculates the amount of time between two {@code ChronoLocalDate}
+ * objects in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified date.
* The result will be negative if the end is before the start.
* The {@code Temporal} passed to this method must be a
* {@code ChronoLocalDate} in the same chronology.
* The calculation returns a whole number, representing the number of
* complete units between the two dates.
- * For example, the period in days between two dates can be calculated
+ * For example, the amount in days between two dates can be calculated
* using {@code startDate.periodUntil(endDate, DAYS)}.
*
* There are two equivalent ways of using this method.
@@ -548,9 +549,9 @@ public interface ChronoLocalDate>
*
* @param endDate the end date, which must be a {@code ChronoLocalDate}
* in the same chronology, not null
- * @param unit the unit to measure the period in, not null
- * @return the amount of the period between this date and the end date
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this date and the end date
+ * @throws DateTimeException if the amount cannot be calculated
* @throws ArithmeticException if numeric overflow occurs
*/
@Override // override for Javadoc
diff --git a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
index d706db128f3..f0a893a4c95 100644
--- a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
+++ b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
@@ -106,7 +106,7 @@ import java.util.Objects;
* Ensure that the discussion in {@code ChronoLocalDate} has been read and understood
* before using this interface.
*
- * Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Subclasses should be Serializable wherever possible.
@@ -127,6 +127,8 @@ public interface ChronoLocalDateTime>
* on the position of the date-time on the local time-line.
* The underlying comparison is equivalent to comparing the epoch-day and nano-of-day.
*
+ * @return a comparator that compares in time-line order ignoring the chronology
+ *
* @see #isAfter
* @see #isBefore
* @see #isEqual
diff --git a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
index fd6e7c05c46..1f7195bc6f7 100644
--- a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
+++ b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
@@ -92,7 +92,7 @@ import java.util.Objects;
* It does not store or represent a time-zone. For example, the value
* "2nd October 2007 at 13:45.30.123456789" can be stored in an {@code ChronoLocalDateTime}.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @param the concrete type for the date of this date-time
@@ -353,12 +353,12 @@ final class ChronoLocalDateTimeImpl>
@Override
public long periodUntil(Temporal endDateTime, TemporalUnit unit) {
if (endDateTime instanceof ChronoLocalDateTime == false) {
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
@SuppressWarnings("unchecked")
ChronoLocalDateTime end = (ChronoLocalDateTime) endDateTime;
if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) {
- throw new DateTimeException("Unable to calculate period between two different chronologies");
+ throw new DateTimeException("Unable to calculate amount as objects have different chronologies");
}
if (unit instanceof ChronoUnit) {
ChronoUnit f = (ChronoUnit) unit;
diff --git a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java
index 4307c104ab4..d838a36ec29 100644
--- a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java
+++ b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java
@@ -107,7 +107,7 @@ import java.util.Objects;
* Ensure that the discussion in {@code ChronoLocalDate} has been read and understood
* before using this interface.
*
- * Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Subclasses should be Serializable wherever possible.
@@ -128,6 +128,8 @@ public interface ChronoZonedDateTime>
* on the position of the date-time on the instant time-line.
* The underlying comparison is equivalent to comparing the epoch-second and nano-of-second.
*
+ * @return a comparator that compares in time-line order ignoring the chronology
+ *
* @see #isAfter
* @see #isBefore
* @see #isEqual
diff --git a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
index 0061eebdffc..835ec932184 100644
--- a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
+++ b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
@@ -95,7 +95,7 @@ import java.util.Objects;
* the local time-line overlaps, typically as a result of the end of daylight time.
* Information about the local-time can be obtained using methods on the time-zone.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @param the concrete type for the date of this date-time
@@ -287,12 +287,12 @@ final class ChronoZonedDateTimeImpl>
@Override
public long periodUntil(Temporal endDateTime, TemporalUnit unit) {
if (endDateTime instanceof ChronoZonedDateTime == false) {
- throw new DateTimeException("Unable to calculate period between objects of two different types");
+ throw new DateTimeException("Unable to calculate amount as objects are of two different types");
}
@SuppressWarnings("unchecked")
ChronoZonedDateTime end = (ChronoZonedDateTime) endDateTime;
if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) {
- throw new DateTimeException("Unable to calculate period between two different chronologies");
+ throw new DateTimeException("Unable to calculate amount as objects have different chronologies");
}
if (unit instanceof ChronoUnit) {
end = end.withZoneSameInstant(offset);
diff --git a/jdk/src/share/classes/java/time/chrono/Chronology.java b/jdk/src/share/classes/java/time/chrono/Chronology.java
index 6c61c32e9c0..e5daae76464 100644
--- a/jdk/src/share/classes/java/time/chrono/Chronology.java
+++ b/jdk/src/share/classes/java/time/chrono/Chronology.java
@@ -176,7 +176,7 @@ import sun.util.logging.PlatformLogger;
* CLDR specification then the calendar type is the concatenation of the
* CLDR type and, if applicable, the CLDR variant,
*
- * Specification for implementors
+ * @implSpec
* This class must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Subclasses should be Serializable wherever possible.
@@ -338,16 +338,13 @@ public abstract class Chronology implements Comparable {
*
* The {@code Locale} class also supports an extension mechanism that
* can be used to identify a calendar system. The mechanism is a form
- * of key-value pairs, where the calendar system has the key "ca"
- * and an optional variant key "cv".
+ * of key-value pairs, where the calendar system has the key "ca".
* For example, the locale "en-JP-u-ca-japanese" represents the English
* language as used in Japan with the Japanese calendar system.
*
* This method finds the desired calendar system by in a manner equivalent
* to passing "ca" to {@link Locale#getUnicodeLocaleType(String)}.
* If the "ca" key is not present, then {@code IsoChronology} is returned.
- * The variant, if present, is appended to the "ca" value separated by "-"
- * and the concatenated value is used to find the calendar system by type.
*
* Note that the behavior of this method differs from the older
* {@link java.util.Calendar#getInstance(Locale)} method.
@@ -374,10 +371,6 @@ public abstract class Chronology implements Comparable {
if (type == null || "iso".equals(type) || "iso8601".equals(type)) {
return IsoChronology.INSTANCE;
}
- String variant = locale.getUnicodeLocaleType("cv");
- if (variant != null && !variant.isEmpty()) {
- type = type + '-' + variant;
- }
// Not pre-defined; lookup by the type
do {
Chronology chrono = CHRONOS_BY_TYPE.get(type);
@@ -563,7 +556,7 @@ public abstract class Chronology implements Comparable {
* and the variant, if applicable, is appended separated by "-".
* The calendar type is used to lookup the {@code Chronology} using {@link #of(String)}.
*
- * @return the calendar system type, null if the calendar is not defined
+ * @return the calendar system type, null if the calendar is not defined by CLDR/LDML
* @see #getId()
*/
public abstract String getCalendarType();
diff --git a/jdk/src/share/classes/java/time/chrono/Era.java b/jdk/src/share/classes/java/time/chrono/Era.java
index a26953ee11a..330346dcc36 100644
--- a/jdk/src/share/classes/java/time/chrono/Era.java
+++ b/jdk/src/share/classes/java/time/chrono/Era.java
@@ -93,7 +93,7 @@ import java.util.Locale;
*
* Instances of {@code Era} may be compared using the {@code ==} operator.
*
- *
Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations must be singletons - final, immutable and thread-safe.
* It is recommended to use an enum whenever possible.
diff --git a/jdk/src/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/share/classes/java/time/chrono/HijrahChronology.java
index 5d53855d723..63dfc1c213b 100644
--- a/jdk/src/share/classes/java/time/chrono/HijrahChronology.java
+++ b/jdk/src/share/classes/java/time/chrono/HijrahChronology.java
@@ -133,9 +133,10 @@ import sun.util.logging.PlatformLogger;
* Chronology chrono = Chronology.ofLocale(locale);
*
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
- * Implementation Note for Hijrah Calendar Variant Configuration
+ *
+ * @implNote
* Each Hijrah variant is configured individually. Each variant is defined by a
* property resource that defines the {@code ID}, the {@code calendar type},
* the start of the calendar, the alignment with the
@@ -229,6 +230,11 @@ public final class HijrahChronology extends Chronology implements Serializable {
* {@link Chronology#getAvailableChronologies}.
*/
public static final HijrahChronology INSTANCE;
+ /**
+ * Flag to indicate the initialization of configuration data is complete.
+ * @see #checkCalendarInit()
+ */
+ private volatile boolean initComplete;
/**
* Array of epoch days indexed by Hijrah Epoch month.
* Computed by {@link #loadCalendarData}.
@@ -285,7 +291,8 @@ public final class HijrahChronology extends Chronology implements Serializable {
private static final String PROP_TYPE_SUFFIX = ".type";
/**
- * Name data.
+ * Static initialization of the predefined calendars found in the
+ * lib/calendars.properties file.
*/
static {
try {
@@ -299,8 +306,7 @@ public final class HijrahChronology extends Chronology implements Serializable {
// Register it by its aliases
Chronology.registerChrono(INSTANCE, "Hijrah");
Chronology.registerChrono(INSTANCE, "islamic");
-
- } catch (Exception ex) {
+ } catch (DateTimeException ex) {
// Absence of Hijrah calendar is fatal to initializing this class.
PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
logger.severe("Unable to initialize Hijrah calendar: Hijrah-umalqura", ex);
@@ -327,7 +333,7 @@ public final class HijrahChronology extends Chronology implements Serializable {
// Create and register the variant
HijrahChronology chrono = new HijrahChronology(id);
Chronology.registerChrono(chrono);
- } catch (Exception ex) {
+ } catch (DateTimeException ex) {
// Log error and continue
PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
logger.severe("Unable to initialize Hijrah calendar: " + id, ex);
@@ -343,22 +349,39 @@ public final class HijrahChronology extends Chronology implements Serializable {
* The property names are {@code "calendar.hijrah." + id}
* and {@code "calendar.hijrah." + id + ".type"}
* @param id the id of the calendar
- * @throws Exception if the resource can not be accessed or
- * the format is invalid
+ * @throws DateTimeException if the calendar type is missing from the properties file.
+ * @throws IllegalArgumentException if the id is empty
*/
- private HijrahChronology(String id) throws Exception {
+ private HijrahChronology(String id) throws DateTimeException {
if (id.isEmpty()) {
throw new IllegalArgumentException("calendar id is empty");
}
+ String propName = PROP_PREFIX + id + PROP_TYPE_SUFFIX;
+ String calType = calendarProperties.getProperty(propName);
+ if (calType == null || calType.isEmpty()) {
+ throw new DateTimeException("calendarType is missing or empty for: " + propName);
+ }
this.typeId = id;
- this.calendarType = calendarProperties.getProperty(PROP_PREFIX + id + PROP_TYPE_SUFFIX);
+ this.calendarType = calType;
+ }
- try {
- String resource = calendarProperties.getProperty(PROP_PREFIX + id);
- Objects.requireNonNull(resource, "Resource missing for calendar");
- loadCalendarData(resource);
- } catch (Exception ex) {
- throw new Exception("Unable to initialize HijrahCalendar: " + id, ex);
+ /**
+ * Check and ensure that the calendar data has been initialized.
+ * The initialization check is performed at the boundary between
+ * public and package methods. If a public calls another public method
+ * a check is not necessary in the caller.
+ * The constructors of HijrahDate call {@link #getEpochDay} or
+ * {@link #getHijrahDateInfo} so every call from HijrahDate to a
+ * HijrahChronology via package private methods has been checked.
+ *
+ * @throws DateTimeException if the calendar data configuration is
+ * malformed or IOExceptions occur loading the data
+ */
+ private void checkCalendarInit() {
+ // Keep this short so it can be inlined for performance
+ if (initComplete == false) {
+ loadCalendarData();
+ initComplete = true;
}
}
@@ -509,6 +532,7 @@ public final class HijrahChronology extends Chronology implements Serializable {
//-----------------------------------------------------------------------
@Override
public boolean isLeapYear(long prolepticYear) {
+ checkCalendarInit();
int epochMonth = yearToEpochMonth((int) prolepticYear);
if (epochMonth < 0 || epochMonth > maxEpochDay) {
throw new DateTimeException("Hijrah date out of range");
@@ -543,6 +567,7 @@ public final class HijrahChronology extends Chronology implements Serializable {
//-----------------------------------------------------------------------
@Override
public ValueRange range(ChronoField field) {
+ checkCalendarInit();
if (field instanceof ChronoField) {
ChronoField f = field;
switch (f) {
@@ -595,6 +620,7 @@ public final class HijrahChronology extends Chronology implements Serializable {
* @return int[0] = YEAR, int[1] = MONTH, int[2] = DATE
*/
int[] getHijrahDateInfo(int epochDay) {
+ checkCalendarInit(); // ensure that the chronology is initialized
if (epochDay < minEpochDay || epochDay >= maxEpochDay) {
throw new DateTimeException("Hijrah date out of range");
}
@@ -621,6 +647,7 @@ public final class HijrahChronology extends Chronology implements Serializable {
* @return the epoch day
*/
long getEpochDay(int prolepticYear, int monthOfYear, int dayOfMonth) {
+ checkCalendarInit(); // ensure that the chronology is initialized
checkValidMonth(monthOfYear);
int epochMonth = yearToEpochMonth(prolepticYear) + (monthOfYear - 1);
if (epochMonth < 0 || epochMonth >= hijrahEpochMonthStartDays.length) {
@@ -846,84 +873,90 @@ public final class HijrahChronology extends Chronology implements Serializable {
}
/**
- * Loads and processes the Hijrah calendar properties file.
+ * Loads and processes the Hijrah calendar properties file for this calendarType.
* The starting Hijrah date and the corresponding ISO date are
* extracted and used to calculate the epochDate offset.
* The version number is identified and ignored.
* Everything else is the data for a year with containing the length of each
* of 12 months.
*
- * @param resourceName containing the properties defining the calendar, not null
- * @throws IllegalArgumentException if any of the values are malformed
- * @throws NumberFormatException if numbers, including properties that should
- * be years are invalid
- * @throws IOException if access to the property resource fails.
+ * @throws DateTimeException if initialization of the calendar data from the
+ * resource fails
*/
- private void loadCalendarData(String resourceName) throws Exception {
- Properties props = readConfigProperties(resourceName);
+ private void loadCalendarData() {
+ try {
+ String resourceName = calendarProperties.getProperty(PROP_PREFIX + typeId);
+ Objects.requireNonNull(resourceName, "Resource missing for calendar: " + PROP_PREFIX + typeId);
+ Properties props = readConfigProperties(resourceName);
- Map years = new HashMap<>();
- int minYear = Integer.MAX_VALUE;
- int maxYear = Integer.MIN_VALUE;
- String id = null;
- String type = null;
- String version = null;
- int isoStart = 0;
- for (Map.Entry entry : props.entrySet()) {
- String key = (String) entry.getKey();
- switch (key) {
- case KEY_ID:
- id = (String)entry.getValue();
- break;
- case KEY_TYPE:
- type = (String)entry.getValue();
- break;
- case KEY_VERSION:
- version = (String)entry.getValue();
- break;
- case KEY_ISO_START: {
- int[] ymd = parseYMD((String) entry.getValue());
- isoStart = (int) LocalDate.of(ymd[0], ymd[1], ymd[2]).toEpochDay();
- break;
- }
- default:
- try {
- // Everything else is either a year or invalid
- int year = Integer.valueOf(key);
- int[] months = parseMonths((String) entry.getValue());
- years.put(year, months);
- maxYear = Math.max(maxYear, year);
- minYear = Math.min(minYear, year);
- } catch (NumberFormatException nfe) {
- throw new IllegalArgumentException("bad key: " + key);
+ Map years = new HashMap<>();
+ int minYear = Integer.MAX_VALUE;
+ int maxYear = Integer.MIN_VALUE;
+ String id = null;
+ String type = null;
+ String version = null;
+ int isoStart = 0;
+ for (Map.Entry entry : props.entrySet()) {
+ String key = (String) entry.getKey();
+ switch (key) {
+ case KEY_ID:
+ id = (String)entry.getValue();
+ break;
+ case KEY_TYPE:
+ type = (String)entry.getValue();
+ break;
+ case KEY_VERSION:
+ version = (String)entry.getValue();
+ break;
+ case KEY_ISO_START: {
+ int[] ymd = parseYMD((String) entry.getValue());
+ isoStart = (int) LocalDate.of(ymd[0], ymd[1], ymd[2]).toEpochDay();
+ break;
}
+ default:
+ try {
+ // Everything else is either a year or invalid
+ int year = Integer.valueOf(key);
+ int[] months = parseMonths((String) entry.getValue());
+ years.put(year, months);
+ maxYear = Math.max(maxYear, year);
+ minYear = Math.min(minYear, year);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("bad key: " + key);
+ }
+ }
}
- }
- if (!getId().equals(id)) {
- throw new IllegalArgumentException("Configuration is for a different calendar: " + id);
- }
- if (!getCalendarType().equals(type)) {
- throw new IllegalArgumentException("Configuration is for a different calendar type: " + type);
- }
- if (version == null || version.isEmpty()) {
- throw new IllegalArgumentException("Configuration does not contain a version");
- }
- if (isoStart == 0) {
- throw new IllegalArgumentException("Configuration does not contain a ISO start date");
- }
+ if (!getId().equals(id)) {
+ throw new IllegalArgumentException("Configuration is for a different calendar: " + id);
+ }
+ if (!getCalendarType().equals(type)) {
+ throw new IllegalArgumentException("Configuration is for a different calendar type: " + type);
+ }
+ if (version == null || version.isEmpty()) {
+ throw new IllegalArgumentException("Configuration does not contain a version");
+ }
+ if (isoStart == 0) {
+ throw new IllegalArgumentException("Configuration does not contain a ISO start date");
+ }
- // Now create and validate the array of epochDays indexed by epochMonth
- hijrahStartEpochMonth = minYear * 12;
- minEpochDay = isoStart;
- hijrahEpochMonthStartDays = createEpochMonths(minEpochDay, minYear, maxYear, years);
- maxEpochDay = hijrahEpochMonthStartDays[hijrahEpochMonthStartDays.length - 1];
+ // Now create and validate the array of epochDays indexed by epochMonth
+ hijrahStartEpochMonth = minYear * 12;
+ minEpochDay = isoStart;
+ hijrahEpochMonthStartDays = createEpochMonths(minEpochDay, minYear, maxYear, years);
+ maxEpochDay = hijrahEpochMonthStartDays[hijrahEpochMonthStartDays.length - 1];
- // Compute the min and max year length in days.
- for (int year = minYear; year < maxYear; year++) {
- int length = getYearLength(year);
- minYearLength = Math.min(minYearLength, length);
- maxYearLength = Math.max(maxYearLength, length);
+ // Compute the min and max year length in days.
+ for (int year = minYear; year < maxYear; year++) {
+ int length = getYearLength(year);
+ minYearLength = Math.min(minYearLength, length);
+ maxYearLength = Math.max(maxYearLength, length);
+ }
+ } catch (Exception ex) {
+ // Log error and throw a DateTimeException
+ PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
+ logger.severe("Unable to initialize Hijrah calendar proxy: " + typeId, ex);
+ throw new DateTimeException("Unable to initialize HijrahCalendar: " + typeId, ex);
}
}
diff --git a/jdk/src/share/classes/java/time/chrono/HijrahDate.java b/jdk/src/share/classes/java/time/chrono/HijrahDate.java
index fc9bd5b0e8e..3c01e94b980 100644
--- a/jdk/src/share/classes/java/time/chrono/HijrahDate.java
+++ b/jdk/src/share/classes/java/time/chrono/HijrahDate.java
@@ -102,7 +102,7 @@ import java.time.temporal.ValueRange;
* to create new HijrahDate instances.
* Alternatively, the {@link #withVariant} method can be used to convert
* to a new HijrahChronology.
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/HijrahEra.java b/jdk/src/share/classes/java/time/chrono/HijrahEra.java
index 66622b567a4..1e99d6062ab 100644
--- a/jdk/src/share/classes/java/time/chrono/HijrahEra.java
+++ b/jdk/src/share/classes/java/time/chrono/HijrahEra.java
@@ -81,7 +81,7 @@ import java.time.temporal.ValueRange;
* Do not use {@code ordinal()} to obtain the numeric representation of {@code HijrahEra}.
* Use {@code getValue()} instead.
*
- * Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/IsoChronology.java b/jdk/src/share/classes/java/time/chrono/IsoChronology.java
index 3624e8d418e..66b0dc10d23 100644
--- a/jdk/src/share/classes/java/time/chrono/IsoChronology.java
+++ b/jdk/src/share/classes/java/time/chrono/IsoChronology.java
@@ -121,7 +121,7 @@ import java.util.Objects;
* leap-year - Leap years occur every 4 years, except where the year is divisble by 100 and not divisble by 400.
*
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -588,7 +588,12 @@ public final class IsoChronology extends Chronology implements Serializable {
int moy = MONTH_OF_YEAR.checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR));
int dom = DAY_OF_MONTH.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH));
if (resolverStyle == ResolverStyle.SMART) { // previous valid
- dom = Math.min(dom, Month.of(moy).length(Year.isLeap(y)));
+ if (moy == 4 || moy == 6 || moy == 9 || moy == 11) {
+ dom = Math.min(dom, 30);
+ } else if (moy == 2) {
+ dom = Math.min(dom, Month.FEBRUARY.length(Year.isLeap(y)));
+
+ }
}
return LocalDate.of(y, moy, dom);
}
diff --git a/jdk/src/share/classes/java/time/chrono/IsoEra.java b/jdk/src/share/classes/java/time/chrono/IsoEra.java
index 445aa45478e..15fa2e4cc6d 100644
--- a/jdk/src/share/classes/java/time/chrono/IsoEra.java
+++ b/jdk/src/share/classes/java/time/chrono/IsoEra.java
@@ -97,7 +97,7 @@ import java.time.DateTimeException;
* Do not use {@code ordinal()} to obtain the numeric representation of {@code IsoEra}.
* Use {@code getValue()} instead.
*
- * Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java b/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java
index 1d07a36929d..1aead71b8ad 100644
--- a/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java
+++ b/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java
@@ -85,7 +85,7 @@ import sun.util.calendar.LocalGregorianCalendar;
* Only Meiji (1865-04-07 - 1868-09-07) and later eras are supported.
* Older eras are handled as an unknown era where the year-of-era is the ISO year.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -197,7 +197,7 @@ public final class JapaneseChronology extends Chronology implements Serializable
*/
@Override
public JapaneseDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
- return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
+ return JapaneseDate.ofYearDay((JapaneseEra) era, yearOfEra, dayOfYear);
}
/**
@@ -251,16 +251,19 @@ public final class JapaneseChronology extends Chronology implements Serializable
}
@Override
+ @SuppressWarnings("unchecked")
public ChronoLocalDateTime localDateTime(TemporalAccessor temporal) {
return (ChronoLocalDateTime)super.localDateTime(temporal);
}
@Override
+ @SuppressWarnings("unchecked")
public ChronoZonedDateTime zonedDateTime(TemporalAccessor temporal) {
return (ChronoZonedDateTime)super.zonedDateTime(temporal);
}
@Override
+ @SuppressWarnings("unchecked")
public ChronoZonedDateTime zonedDateTime(Instant instant, ZoneId zone) {
return (ChronoZonedDateTime)super.zonedDateTime(instant, zone);
}
@@ -286,19 +289,27 @@ public final class JapaneseChronology extends Chronology implements Serializable
if (era instanceof JapaneseEra == false) {
throw new ClassCastException("Era must be JapaneseEra");
}
+
+ if (era == JapaneseEra.SEIREKI) {
+ JapaneseEra nextEra = JapaneseEra.values()[1];
+ int nextEraYear = nextEra.getPrivateEra().getSinceDate().getYear();
+ if (yearOfEra >= nextEraYear || yearOfEra < Year.MIN_VALUE) {
+ throw new DateTimeException("Invalid yearOfEra value");
+ }
+ return yearOfEra;
+ }
+
JapaneseEra jera = (JapaneseEra) era;
int gregorianYear = jera.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
if (yearOfEra == 1) {
return gregorianYear;
}
- LocalGregorianCalendar.Date jdate = JCAL.newCalendarDate(null);
- jdate.setEra(jera.getPrivateEra()).setDate(yearOfEra, 1, 1);
- if (!JapaneseChronology.JCAL.validate(jdate)) {
- throw new DateTimeException("Invalid yearOfEra value");
- }
- JCAL.normalize(jdate);
- if (jdate.getNormalizedYear() == gregorianYear) {
- return gregorianYear;
+ if (gregorianYear >= Year.MIN_VALUE && gregorianYear <= Year.MAX_VALUE) {
+ LocalGregorianCalendar.Date jdate = JCAL.newCalendarDate(null);
+ jdate.setEra(jera.getPrivateEra()).setDate(yearOfEra, 1, 1);
+ if (JapaneseChronology.JCAL.validate(jdate)) {
+ return gregorianYear;
+ }
}
throw new DateTimeException("Invalid yearOfEra value");
}
@@ -322,13 +333,20 @@ public final class JapaneseChronology extends Chronology implements Serializable
@Override
public List eras() {
- return Arrays.asList(JapaneseEra.values());
+ return Arrays.asList(JapaneseEra.values());
+ }
+
+ JapaneseEra getCurrentEra() {
+ // Assume that the last JapaneseEra is the current one.
+ JapaneseEra[] eras = JapaneseEra.values();
+ return eras[eras.length - 1];
}
//-----------------------------------------------------------------------
@Override
public ValueRange range(ChronoField field) {
switch (field) {
+ case YEAR:
case DAY_OF_MONTH:
case DAY_OF_WEEK:
case MICRO_OF_DAY:
@@ -345,27 +363,23 @@ public final class JapaneseChronology extends Chronology implements Serializable
case NANO_OF_SECOND:
case CLOCK_HOUR_OF_DAY:
case CLOCK_HOUR_OF_AMPM:
- case EPOCH_DAY: // TODO: if year is restricted, then so is epoch-day
+ case EPOCH_DAY:
+ case PROLEPTIC_MONTH:
+ case MONTH_OF_YEAR:
return field.range();
+ case ERA:
+ return ValueRange.of(JapaneseEra.SEIREKI.getValue(),
+ getCurrentEra().getValue());
}
Calendar jcal = Calendar.getInstance(LOCALE);
int fieldIndex;
switch (field) {
- case ERA:
- return ValueRange.of(JapaneseEra.SEIREKI.getValue(),
- jcal.getMaximum(Calendar.ERA) - JapaneseEra.ERA_OFFSET);
- case YEAR:
- case YEAR_OF_ERA:
- // TODO: this is not right
+ case YEAR_OF_ERA: {
+ int startYear = getCurrentEra().getPrivateEra().getSinceDate().getYear();
return ValueRange.of(Year.MIN_VALUE, jcal.getGreatestMinimum(Calendar.YEAR),
- jcal.getLeastMaximum(Calendar.YEAR), Year.MAX_VALUE);
- case PROLEPTIC_MONTH:
- // TODO: should be the range of months bound by the valid range of years
- return ValueRange.of((jcal.getGreatestMinimum(Calendar.YEAR) - 1) * 12,
- (jcal.getLeastMaximum(Calendar.YEAR)) * 12);
- case MONTH_OF_YEAR:
- return ValueRange.of(jcal.getMinimum(Calendar.MONTH) + 1, jcal.getGreatestMinimum(Calendar.MONTH) + 1,
- jcal.getLeastMaximum(Calendar.MONTH) + 1, jcal.getMaximum(Calendar.MONTH) + 1);
+ jcal.getLeastMaximum(Calendar.YEAR) + 1, // +1 due to the different definitions
+ Year.MAX_VALUE - startYear);
+ }
case DAY_OF_YEAR:
fieldIndex = Calendar.DAY_OF_YEAR;
break;
diff --git a/jdk/src/share/classes/java/time/chrono/JapaneseDate.java b/jdk/src/share/classes/java/time/chrono/JapaneseDate.java
index 7ba7fd37401..646315b3d80 100644
--- a/jdk/src/share/classes/java/time/chrono/JapaneseDate.java
+++ b/jdk/src/share/classes/java/time/chrono/JapaneseDate.java
@@ -83,6 +83,7 @@ import java.time.temporal.ValueRange;
import java.util.Calendar;
import java.util.Objects;
+import sun.util.calendar.CalendarDate;
import sun.util.calendar.LocalGregorianCalendar;
/**
@@ -101,7 +102,7 @@ import sun.util.calendar.LocalGregorianCalendar;
* Calling {@code japaneseDate.get(ERA)} will return 2, corresponding to
* {@code JapaneseChronology.ERA_HEISEI}.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -234,6 +235,24 @@ public final class JapaneseDate
return of(prolepticYear, date.getMonthValue(), date.getDayOfMonth());
}
+ static JapaneseDate ofYearDay(JapaneseEra era, int yearOfEra, int dayOfYear) {
+ CalendarDate firstDay = era.getPrivateEra().getSinceDate();
+ LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null);
+ jdate.setEra(era.getPrivateEra());
+ if (yearOfEra == 1) {
+ jdate.setDate(yearOfEra, firstDay.getMonth(), firstDay.getDayOfMonth() + dayOfYear - 1);
+ } else {
+ jdate.setDate(yearOfEra, 1, dayOfYear);
+ }
+ JapaneseChronology.JCAL.normalize(jdate);
+ if (era.getPrivateEra() != jdate.getEra() || yearOfEra != jdate.getYear()) {
+ throw new DateTimeException("Invalid parameters");
+ }
+ LocalDate localdate = LocalDate.of(jdate.getNormalizedYear(),
+ jdate.getMonth(), jdate.getDayOfMonth());
+ return new JapaneseDate(era, yearOfEra, localdate);
+ }
+
/**
* Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
* system from the era, year-of-era, month-of-year and day-of-month fields.
diff --git a/jdk/src/share/classes/java/time/chrono/JapaneseEra.java b/jdk/src/share/classes/java/time/chrono/JapaneseEra.java
index f89de19a271..17635793b08 100644
--- a/jdk/src/share/classes/java/time/chrono/JapaneseEra.java
+++ b/jdk/src/share/classes/java/time/chrono/JapaneseEra.java
@@ -91,7 +91,7 @@ import sun.util.calendar.CalendarDate;
* and the year of era of Seireki is proleptic Gregorian year.
* (The Julian to Gregorian transition is not supported.)
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/MinguoChronology.java b/jdk/src/share/classes/java/time/chrono/MinguoChronology.java
index f977b496e0f..1c9c2e34c16 100644
--- a/jdk/src/share/classes/java/time/chrono/MinguoChronology.java
+++ b/jdk/src/share/classes/java/time/chrono/MinguoChronology.java
@@ -95,7 +95,7 @@ import java.util.Locale;
* are never out of step.
*
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/MinguoDate.java b/jdk/src/share/classes/java/time/chrono/MinguoDate.java
index 07ce800ab06..b6a5582ef98 100644
--- a/jdk/src/share/classes/java/time/chrono/MinguoDate.java
+++ b/jdk/src/share/classes/java/time/chrono/MinguoDate.java
@@ -89,7 +89,7 @@ import java.util.Objects;
* This calendar system is primarily used in the Republic of China, often known as Taiwan.
* Dates are aligned such that {@code 0001-01-01 (Minguo)} is {@code 1912-01-01 (ISO)}.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/MinguoEra.java b/jdk/src/share/classes/java/time/chrono/MinguoEra.java
index 0563515834d..edf1ad5610a 100644
--- a/jdk/src/share/classes/java/time/chrono/MinguoEra.java
+++ b/jdk/src/share/classes/java/time/chrono/MinguoEra.java
@@ -102,7 +102,7 @@ import java.time.DateTimeException;
* Do not use {@code ordinal()} to obtain the numeric representation of {@code MinguoEra}.
* Use {@code getValue()} instead.
*
- * Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/Ser.java b/jdk/src/share/classes/java/time/chrono/Ser.java
index 5fec32da1a3..ff59aec4190 100644
--- a/jdk/src/share/classes/java/time/chrono/Ser.java
+++ b/jdk/src/share/classes/java/time/chrono/Ser.java
@@ -68,7 +68,7 @@ import java.time.LocalDateTime;
/**
* The shared serialization delegate for this package.
*
- * Implementation notes
+ * @implNote
* This class wraps the object being serialized, and takes a byte representing the type of the class to
* be serialized. This byte can also be used for versioning the serialization format. In this case another
* byte flag would be used in order to specify an alternative version of the type format.
diff --git a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java
index aee743526ab..27c98a6f079 100644
--- a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java
+++ b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java
@@ -96,7 +96,7 @@ import java.util.Locale;
* are never out of step.
*
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java
index b879a14e586..973c7b8ab0f 100644
--- a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java
+++ b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java
@@ -89,7 +89,7 @@ import java.util.Objects;
* This calendar system is primarily used in Thailand.
* Dates are aligned such that {@code 2484-01-01 (Buddhist)} is {@code 1941-01-01 (ISO)}.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java
index d1fb55fc740..d91eb81d79d 100644
--- a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java
+++ b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java
@@ -102,7 +102,7 @@ import java.time.DateTimeException;
* Do not use {@code ordinal()} to obtain the numeric representation of {@code ThaiBuddhistEra}.
* Use {@code getValue()} instead.
*
- * Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/share/classes/java/time/format/DateTimeFormatter.java
index 5c6bb2336b1..158c741dff4 100644
--- a/jdk/src/share/classes/java/time/format/DateTimeFormatter.java
+++ b/jdk/src/share/classes/java/time/format/DateTimeFormatter.java
@@ -77,6 +77,7 @@ import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.time.DateTimeException;
+import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.chrono.Chronology;
@@ -121,7 +122,7 @@ import java.util.Set;
*
*
* In addition to the format, formatters can be created with desired Locale,
- * Chronology, ZoneId, and formatting symbols.
+ * Chronology, ZoneId, and DecimalStyle.
*
* The {@link #withLocale withLocale} method returns a new formatter that
* overrides the locale. The locale affects some aspects of formatting and
@@ -138,8 +139,8 @@ import java.util.Set;
* with the requested ZoneId before formatting. During parsing the ZoneId is
* applied before the value is returned.
*
- * The {@link #withSymbols withSymbols} method returns a new formatter that
- * overrides the {@link DateTimeFormatSymbols}. The symbols are used for
+ * The {@link #withDecimalStyle withDecimalStyle} method returns a new formatter that
+ * overrides the {@link DecimalStyle}. The DecimalStyle symbols are used for
* formatting and parsing.
*
* Some applications may need to use the older {@link Format java.text.Format}
@@ -417,7 +418,65 @@ import java.util.Set;
* that you want to output directly to ensure that future changes do not break
* your application.
*
- *
Specification for implementors
+ * Resolving
+ * Parsing is implemented as a two-phase operation.
+ * First, the text is parsed using the layout defined by the formatter, producing
+ * a {@code Map} of field to value, a {@code ZoneId} and a {@code Chronology}.
+ * Second, the parsed data is resolved , by validating, combining and
+ * simplifying the various fields into more useful ones.
+ *
+ * Five parsing methods are supplied by this class.
+ * Four of these perform both the parse and resolve phases.
+ * The fifth method, {@link #parseUnresolved(CharSequence, ParsePosition)},
+ * only performs the first phase, leaving the result unresolved.
+ * As such, it is essentially a low-level operation.
+ *
+ * The resolve phase is controlled by two parameters, set on this class.
+ *
+ * The {@link ResolverStyle} is an enum that offers three different approaches,
+ * strict, smart and lenient. The smart option is the default.
+ * It can be set using {@link #withResolverStyle(ResolverStyle)}.
+ *
+ * The {@link #withResolverFields(TemporalField...)} parameter allows the
+ * set of fields that will be resolved to be filtered before resolving starts.
+ * For example, if the formatter has parsed a year, month, day-of-month
+ * and day-of-year, then there are two approaches to resolve a date:
+ * (year + month + day-of-month) and (year + day-of-year).
+ * The resolver fields allows one of the two approaches to be selected.
+ * If no resolver fields are set then both approaches must result in the same date.
+ *
+ * Resolving separate fields to form a complete date and time is a complex
+ * process with behaviour distributed across a number of classes.
+ * It follows these steps:
+ *
+ * The chronology is determined.
+ * The chronology of the result is either the chronology that was parsed,
+ * or if no chronology was parsed, it is the chronology set on this class,
+ * or if that is null, it is {@code IsoChronology}.
+ * The {@code ChronoField} date fields are resolved.
+ * This is achieved using {@link Chronology#resolveDate(Map, ResolverStyle)}.
+ * Documentation about field resolution is located in the implementation
+ * of {@code Chronology}.
+ * The {@code ChronoField} time fields are resolved.
+ * This is documented on {@link ChronoField} and is the same for all chronologies.
+ * Any fields that are not {@code ChronoField} are processed.
+ * This is achieved using {@link TemporalField#resolve(TemporalAccessor, long, ResolverStyle)}.
+ * Documentation about field resolution is located in the implementation
+ * of {@code TemporalField}.
+ * The {@code ChronoField} date and time fields are re-resolved.
+ * This allows fields in step four to produce {@code ChronoField} values
+ * and have them be processed into dates and times.
+ * A {@code LocalTime} is formed if there is at least an hour-of-day available.
+ * This involves providing default values for minute, second and fraction of second.
+ * Any remaining unresolved fields are cross-checked against any
+ * date and/or time that was resolved. Thus, an earlier stage would resolve
+ * (year + month + day-of-month) to a date, and this stage would check that
+ * day-of-week was valid for the date.
+ * If an {@linkplain #parsedExcessDays() excess number of days}
+ * was parsed then it is added to the date if a date is available.
+ *
+ *
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -435,7 +494,7 @@ public final class DateTimeFormatter {
/**
* The symbols to use for formatting, not null.
*/
- private final DateTimeFormatSymbols symbols;
+ private final DecimalStyle decimalStyle;
/**
* The resolver style to use, not null.
*/
@@ -1040,6 +1099,11 @@ public final class DateTimeFormatter {
*
* This returns an immutable formatter capable of formatting and parsing
* the ISO-8601 instant format.
+ * When formatting, the second-of-minute is always output.
+ * The nano-of-second outputs zero, three, six or nine digits digits as necessary.
+ * When parsing, time to at least the seconds field is required.
+ * Fractional seconds from zero to nine are parsed.
+ * The localized decimal style is not used.
*
* This is a special case formatter intended to allow a human readable form
* of an {@link java.time.Instant}. The {@code Instant} class is designed to
@@ -1201,25 +1265,117 @@ public final class DateTimeFormatter {
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
}
+ //-----------------------------------------------------------------------
+ /**
+ * A query that provides access to the excess days that were parsed.
+ *
+ * This returns a singleton {@linkplain TemporalQuery query} that provides
+ * access to additional information from the parse. The query always returns
+ * a non-null period, with a zero period returned instead of null.
+ *
+ * There are two situations where this query may return a non-zero period.
+ *
+ * If the {@code ResolverStyle} is {@code LENIENT} and a time is parsed
+ * without a date, then the complete result of the parse consists of a
+ * {@code LocalTime} and an excess {@code Period} in days.
+ *
+ *
If the {@code ResolverStyle} is {@code SMART} and a time is parsed
+ * without a date where the time is 24:00:00, then the complete result of
+ * the parse consists of a {@code LocalTime} of 00:00:00 and an excess
+ * {@code Period} of one day.
+ *
+ *
+ * In both cases, if a complete {@code ChronoLocalDateTime} or {@code Instant}
+ * is parsed, then the excess days are added to the date part.
+ * As a result, this query will return a zero period.
+ *
+ * The {@code SMART} behaviour handles the common "end of day" 24:00 value.
+ * Processing in {@code LENIENT} mode also produces the same result:
+ *
+ * Text to parse Parsed object Excess days
+ * "2012-12-03T00:00" LocalDateTime.of(2012, 12, 3, 0, 0) ZERO
+ * "2012-12-03T24:00" LocalDateTime.of(2012, 12, 4, 0, 0) ZERO
+ * "00:00" LocalTime.of(0, 0) ZERO
+ * "24:00" LocalTime.of(0, 0) Period.ofDays(1)
+ *
+ * The query can be used as follows:
+ *
+ * TemporalAccessor parsed = formatter.parse(str);
+ * LocalTime time = parsed.query(LocalTime::from);
+ * Period extraDays = parsed.query(DateTimeFormatter.parsedExcessDays());
+ *
+ */
+ public static final TemporalQuery parsedExcessDays() {
+ return PARSED_EXCESS_DAYS;
+ }
+ private static final TemporalQuery PARSED_EXCESS_DAYS = t -> {
+ if (t instanceof Parsed) {
+ return ((Parsed) t).excessDays;
+ } else {
+ return Period.ZERO;
+ }
+ };
+
+ /**
+ * A query that provides access to whether a leap-second was parsed.
+ *
+ * This returns a singleton {@linkplain TemporalQuery query} that provides
+ * access to additional information from the parse. The query always returns
+ * a non-null boolean, true if parsing saw a leap-second, false if not.
+ *
+ * Instant parsing handles the special "leap second" time of '23:59:60'.
+ * Leap seconds occur at '23:59:60' in the UTC time-zone, but at other
+ * local times in different time-zones. To avoid this potential ambiguity,
+ * the handling of leap-seconds is limited to
+ * {@link DateTimeFormatterBuilder#appendInstant()}, as that method
+ * always parses the instant with the UTC zone offset.
+ *
+ * If the time '23:59:60' is received, then a simple conversion is applied,
+ * replacing the second-of-minute of 60 with 59. This query can be used
+ * on the parse result to determine if the leap-second adjustment was made.
+ * The query will return one second of excess if it did adjust to remove
+ * the leap-second, and zero if not. Note that applying a leap-second
+ * smoothing mechanism, such as UTC-SLS, is the responsibility of the
+ * application, as follows:
+ *
+ * TemporalAccessor parsed = formatter.parse(str);
+ * Instant instant = parsed.query(Instant::from);
+ * if (parsed.query(DateTimeFormatter.parsedLeapSecond())) {
+ * // validate leap-second is correct and apply correct smoothing
+ * }
+ *
+ */
+ public static final TemporalQuery parsedLeapSecond() {
+ return PARSED_LEAP_SECOND;
+ }
+ private static final TemporalQuery PARSED_LEAP_SECOND = t -> {
+ if (t instanceof Parsed) {
+ return ((Parsed) t).leapSecond;
+ } else {
+ return Boolean.FALSE;
+ }
+ };
+
+ //-----------------------------------------------------------------------
/**
* Constructor.
*
* @param printerParser the printer/parser to use, not null
* @param locale the locale to use, not null
- * @param symbols the symbols to use, not null
+ * @param decimalStyle the DecimalStyle to use, not null
* @param resolverStyle the resolver style to use, not null
* @param resolverFields the fields to use during resolving, null for all fields
* @param chrono the chronology to use, null for no override
* @param zone the zone to use, null for no override
*/
DateTimeFormatter(CompositePrinterParser printerParser,
- Locale locale, DateTimeFormatSymbols symbols,
+ Locale locale, DecimalStyle decimalStyle,
ResolverStyle resolverStyle, Set resolverFields,
Chronology chrono, ZoneId zone) {
this.printerParser = Objects.requireNonNull(printerParser, "printerParser");
this.resolverFields = resolverFields;
this.locale = Objects.requireNonNull(locale, "locale");
- this.symbols = Objects.requireNonNull(symbols, "symbols");
+ this.decimalStyle = Objects.requireNonNull(decimalStyle, "decimalStyle");
this.resolverStyle = Objects.requireNonNull(resolverStyle, "resolverStyle");
this.chrono = chrono;
this.zone = zone;
@@ -1253,32 +1409,32 @@ public final class DateTimeFormatter {
if (this.locale.equals(locale)) {
return this;
}
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
//-----------------------------------------------------------------------
/**
- * Gets the set of symbols to be used during formatting.
+ * Gets the DecimalStyle to be used during formatting.
*
* @return the locale of this formatter, not null
*/
- public DateTimeFormatSymbols getSymbols() {
- return symbols;
+ public DecimalStyle getDecimalStyle() {
+ return decimalStyle;
}
/**
- * Returns a copy of this formatter with a new set of symbols.
+ * Returns a copy of this formatter with a new DecimalStyle.
*
* This instance is immutable and unaffected by this method call.
*
- * @param symbols the new symbols, not null
- * @return a formatter based on this formatter with the requested symbols, not null
+ * @param decimalStyle the new DecimalStyle, not null
+ * @return a formatter based on this formatter with the requested DecimalStyle, not null
*/
- public DateTimeFormatter withSymbols(DateTimeFormatSymbols symbols) {
- if (this.symbols.equals(symbols)) {
+ public DateTimeFormatter withDecimalStyle(DecimalStyle decimalStyle) {
+ if (this.decimalStyle.equals(decimalStyle)) {
return this;
}
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
//-----------------------------------------------------------------------
@@ -1332,7 +1488,7 @@ public final class DateTimeFormatter {
if (Objects.equals(this.chrono, chrono)) {
return this;
}
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
//-----------------------------------------------------------------------
@@ -1389,7 +1545,7 @@ public final class DateTimeFormatter {
if (Objects.equals(this.zone, zone)) {
return this;
}
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
//-----------------------------------------------------------------------
@@ -1431,7 +1587,7 @@ public final class DateTimeFormatter {
if (Objects.equals(this.resolverStyle, resolverStyle)) {
return this;
}
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
//-----------------------------------------------------------------------
@@ -1495,7 +1651,7 @@ public final class DateTimeFormatter {
return this;
}
fields = Collections.unmodifiableSet(fields);
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, fields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, fields, chrono, zone);
}
/**
@@ -1543,7 +1699,7 @@ public final class DateTimeFormatter {
return this;
}
resolverFields = Collections.unmodifiableSet(new HashSet<>(resolverFields));
- return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone);
+ return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
//-----------------------------------------------------------------------
diff --git a/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java
index d209f5c8baf..cec07840439 100644
--- a/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -77,6 +77,7 @@ import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.ParsePosition;
import java.time.DateTimeException;
+import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -142,7 +143,7 @@ import sun.util.locale.provider.TimeZoneNameUtility;
* can be used, see {@link #appendPattern(String)}.
* In practice, this simply parses the pattern and calls other methods on the builder.
*
- *
Specification for implementors
+ * @implSpec
* This class is a mutable builder intended for use from a single thread.
*
* @since 1.8
@@ -186,6 +187,44 @@ public final class DateTimeFormatterBuilder {
*/
private int valueParserIndex = -1;
+ /**
+ * Gets the formatting pattern for date and time styles for a locale and chronology.
+ * The locale and chronology are used to lookup the locale specific format
+ * for the requested dateStyle and/or timeStyle.
+ *
+ * @param dateStyle the FormatStyle for the date
+ * @param timeStyle the FormatStyle for the time
+ * @param chrono the Chronology, non-null
+ * @param locale the locale, non-null
+ * @return the locale and Chronology specific formatting pattern
+ * @throws IllegalArgumentException if both dateStyle and timeStyle are null
+ */
+ public static String getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle,
+ Chronology chrono, Locale locale) {
+ Objects.requireNonNull(locale, "locale");
+ Objects.requireNonNull(chrono, "chrono");
+ if (dateStyle == null && timeStyle == null) {
+ throw new IllegalArgumentException("Either dateStyle or timeStyle must be non-null");
+ }
+ LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale);
+ String pattern = lr.getJavaTimeDateTimePattern(
+ convertStyle(timeStyle), convertStyle(dateStyle), chrono.getCalendarType());
+ return pattern;
+ }
+
+ /**
+ * Converts the given FormatStyle to the java.text.DateFormat style.
+ *
+ * @param style the FormatStyle style
+ * @return the int style, or -1 if style is null, indicating un-required
+ */
+ private static int convertStyle(FormatStyle style) {
+ if (style == null) {
+ return -1;
+ }
+ return style.ordinal(); // indices happen to align
+ }
+
/**
* Constructs a new instance of the builder.
*/
@@ -344,7 +383,7 @@ public final class DateTimeFormatterBuilder {
*/
public DateTimeFormatterBuilder appendValue(TemporalField field) {
Objects.requireNonNull(field, "field");
- active.valueParserIndex = appendInternal(new NumberPrinterParser(field, 1, 19, SignStyle.NORMAL));
+ appendValue(new NumberPrinterParser(field, 1, 19, SignStyle.NORMAL));
return this;
}
@@ -360,15 +399,15 @@ public final class DateTimeFormatterBuilder {
* If the value of the field is negative then an exception is thrown during formatting.
*
* This method supports a special technique of parsing known as 'adjacent value parsing'.
- * This technique solves the problem where a variable length value is followed by one or more
+ * This technique solves the problem where a value, variable or fixed width, is followed by one or more
* fixed length values. The standard parser is greedy, and thus it would normally
* steal the digits that are needed by the fixed width value parsers that follow the
* variable width one.
*
* No action is required to initiate 'adjacent value parsing'.
- * When a call to {@code appendValue} with a variable width is made, the builder
+ * When a call to {@code appendValue} is made, the builder
* enters adjacent value parsing setup mode. If the immediately subsequent method
- * call or calls on the same builder are to this method, then the parser will reserve
+ * call or calls on the same builder are for a fixed width value, then the parser will reserve
* space so that the fixed width values can be parsed.
*
* For example, consider {@code builder.appendValue(YEAR).appendValue(MONTH_OF_YEAR, 2);}
@@ -381,7 +420,7 @@ public final class DateTimeFormatterBuilder {
* nothing for the month.
*
* Adjacent value parsing applies to each set of fixed width not-negative values in the parser
- * that immediately follow any kind of variable width value.
+ * that immediately follow any kind of value, variable or fixed width.
* Calling any other append method will end the setup of adjacent value parsing.
* Thus, in the unlikely event that you need to avoid adjacent value parsing behavior,
* simply add the {@code appendValue} to another {@code DateTimeFormatterBuilder}
@@ -402,7 +441,8 @@ public final class DateTimeFormatterBuilder {
throw new IllegalArgumentException("The width must be from 1 to 19 inclusive but was " + width);
}
NumberPrinterParser pp = new NumberPrinterParser(field, width, width, SignStyle.NOT_NEGATIVE);
- return appendFixedWidth(width, pp);
+ appendValue(pp);
+ return this;
}
/**
@@ -420,8 +460,10 @@ public final class DateTimeFormatterBuilder {
* This behavior can be affected by 'adjacent value parsing'.
* See {@link #appendValue(java.time.temporal.TemporalField, int)} for full details.
*
- * In strict parsing mode, the minimum number of parsed digits is {@code minWidth}.
- * In lenient parsing mode, the minimum number of parsed digits is one.
+ * In strict parsing mode, the minimum number of parsed digits is {@code minWidth}
+ * and the maximum is {@code maxWidth}.
+ * In lenient parsing mode, the minimum number of parsed digits is one
+ * and the maximum is 19 (except as limited by adjacent value parsing).
*
* If this method is invoked with equal minimum and maximum widths and a sign style of
* {@code NOT_NEGATIVE} then it delegates to {@code appendValue(TemporalField,int)}.
@@ -452,17 +494,13 @@ public final class DateTimeFormatterBuilder {
maxWidth + " < " + minWidth);
}
NumberPrinterParser pp = new NumberPrinterParser(field, minWidth, maxWidth, signStyle);
- if (minWidth == maxWidth) {
- appendInternal(pp);
- } else {
- active.valueParserIndex = appendInternal(pp);
- }
+ appendValue(pp);
return this;
}
//-----------------------------------------------------------------------
/**
- * Appends the reduced value of a date-time field to the formatter.
+ * Appends the reduced value of a date-time field with fixed width to the formatter.
*
* This is typically used for formatting and parsing a two digit year.
* The {@code width} is the printed and parsed width.
@@ -471,51 +509,116 @@ public final class DateTimeFormatterBuilder {
* For formatting, the width is used to determine the number of characters to format.
* The rightmost characters are output to match the width, left padding with zero.
*
- * For parsing, exactly the number of characters specified by the width are parsed.
- * This is incomplete information however, so the base value is used to complete the parse.
- * The base value is the first valid value in a range of ten to the power of width.
+ * For strict parsing, the number of characters allowed by the width are parsed.
+ * For lenient parsing, the number of characters must be at least 1 and less than 10.
+ * If the number of digits parsed is equal to {@code width} and the value is positive,
+ * the value of the field is computed to be the first number greater than
+ * or equal to the {@code baseValue} with the same least significant characters,
+ * otherwise the value parsed is the field value.
+ * This allows a reduced value to be entered for values in range of the baseValue
+ * and width and absolute values can be entered for values outside the range.
*
* For example, a base value of {@code 1980} and a width of {@code 2} will have
* valid values from {@code 1980} to {@code 2079}.
* During parsing, the text {@code "12"} will result in the value {@code 2012} as that
- * is the value within the range where the last two digits are "12".
- *
- * This is a fixed width parser operating using 'adjacent value parsing'.
- * See {@link #appendValue(java.time.temporal.TemporalField, int)} for full details.
+ * is the value within the range where the last two characters are "12".
+ * Compare with lenient parsing the text {@code "1915"} that will result in the
+ * value {@code 1915}.
*
* @param field the field to append, not null
- * @param width the width of the printed and parsed field, from 1 to 18
+ * @param width the field width of the printed and parsed field, from 1 to 10
+ * @param baseValue the base value of the range of valid values
+ * @return this, for chaining, not null
+ * @throws IllegalArgumentException if the width or base value is invalid
+ * @see #appendValueReduced(java.time.temporal.TemporalField, int, int, int)
+ */
+ public DateTimeFormatterBuilder appendValueReduced(TemporalField field,
+ int width, int baseValue) {
+ return appendValueReduced(field, width, width, baseValue);
+ }
+
+ /**
+ * Appends the reduced value of a date-time field with a flexible width to the formatter.
+ *
+ * This is typically used for formatting and parsing a two digit year
+ * but allowing for the year value to be up to maxWidth.
+ *
+ * For formatting, the {@code width} and {@code maxWidth} are used to
+ * determine the number of characters to format.
+ * If the value of the field is within the range of the {@code baseValue} using
+ * {@code width} characters then the reduced value is formatted otherwise the value is
+ * truncated to fit {@code maxWidth}.
+ * The rightmost characters are output to match the width, left padding with zero.
+ *
+ * For strict parsing, the number of characters allowed by {@code width} to {@code maxWidth} are parsed.
+ * For lenient parsing, the number of characters must be at least 1 and less than 10.
+ * If the number of digits parsed is equal to {@code width} and the value is positive,
+ * the value of the field is computed to be the first number greater than
+ * or equal to the {@code baseValue} with the same least significant characters,
+ * otherwise the value parsed is the field value.
+ * This allows a reduced value to be entered for values in range of the baseValue
+ * and width and absolute values can be entered for values outside the range.
+ *
+ * For example, a base value of {@code 1980} and a width of {@code 2} will have
+ * valid values from {@code 1980} to {@code 2079}.
+ * During parsing, the text {@code "12"} will result in the value {@code 2012} as that
+ * is the value within the range where the last two characters are "12".
+ * Compare with parsing the text {@code "1915"} that will result in the
+ * value {@code 1915}.
+ *
+ * @param field the field to append, not null
+ * @param width the field width of the printed and parsed field, from 1 to 10
+ * @param maxWidth the maximum field width of the printed field, from 1 to 10
* @param baseValue the base value of the range of valid values
* @return this, for chaining, not null
* @throws IllegalArgumentException if the width or base value is invalid
*/
- public DateTimeFormatterBuilder appendValueReduced(
- TemporalField field, int width, int baseValue) {
+ public DateTimeFormatterBuilder appendValueReduced(TemporalField field,
+ int width, int maxWidth, int baseValue) {
Objects.requireNonNull(field, "field");
- ReducedPrinterParser pp = new ReducedPrinterParser(field, width, baseValue);
- appendFixedWidth(width, pp);
+ ReducedPrinterParser pp = new ReducedPrinterParser(field, width, maxWidth, baseValue);
+ appendValue(pp);
return this;
}
/**
- * Appends a fixed width printer-parser.
+ * Appends a fixed or variable width printer-parser handling adjacent value mode.
+ * If a PrinterParser is not active then the new PrinterParser becomes
+ * the active PrinterParser.
+ * Otherwise, the active PrinterParser is modified depending on the new PrinterParser.
+ * If the new PrinterParser is fixed width and has sign style {@code NOT_NEGATIVE}
+ * then its width is added to the active PP and
+ * the new PrinterParser is forced to be fixed width.
+ * If the new PrinterParser is variable width, the active PrinterParser is changed
+ * to be fixed width and the new PrinterParser becomes the active PP.
*
- * @param width the width
* @param pp the printer-parser, not null
* @return this, for chaining, not null
*/
- private DateTimeFormatterBuilder appendFixedWidth(int width, NumberPrinterParser pp) {
+ private DateTimeFormatterBuilder appendValue(NumberPrinterParser pp) {
if (active.valueParserIndex >= 0) {
+ final int activeValueParser = active.valueParserIndex;
+
// adjacent parsing mode, update setting in previous parsers
- NumberPrinterParser basePP = (NumberPrinterParser) active.printerParsers.get(active.valueParserIndex);
- basePP = basePP.withSubsequentWidth(width);
- int activeValueParser = active.valueParserIndex;
- active.printerParsers.set(active.valueParserIndex, basePP);
- appendInternal(pp.withFixedWidth());
- active.valueParserIndex = activeValueParser;
+ NumberPrinterParser basePP = (NumberPrinterParser) active.printerParsers.get(activeValueParser);
+ if (pp.minWidth == pp.maxWidth && pp.signStyle == SignStyle.NOT_NEGATIVE) {
+ // Append the width to the subsequentWidth of the active parser
+ basePP = basePP.withSubsequentWidth(pp.maxWidth);
+ // Append the new parser as a fixed width
+ appendInternal(pp.withFixedWidth());
+ // Retain the previous active parser
+ active.valueParserIndex = activeValueParser;
+ } else {
+ // Modify the active parser to be fixed width
+ basePP = basePP.withFixedWidth();
+ // The new parser becomes the mew active parser
+ active.valueParserIndex = appendInternal(pp);
+ }
+ // Replace the modified parser with the updated one
+ active.printerParsers.set(activeValueParser, basePP);
} else {
- // not adjacent parsing
- appendInternal(pp);
+ // The new Parser becomes the active parser
+ active.valueParserIndex = appendInternal(pp);
}
return this;
}
@@ -657,11 +760,24 @@ public final class DateTimeFormatterBuilder {
//-----------------------------------------------------------------------
/**
- * Appends an instant using ISO-8601 to the formatter.
+ * Appends an instant using ISO-8601 to the formatter, formatting fractional
+ * digits in groups of three.
*
* Instants have a fixed output format.
- * They are converted to a date-time with a zone-offset of UTC and printed
+ * They are converted to a date-time with a zone-offset of UTC and formatted
* using the standard ISO-8601 format.
+ * With this method, formatting nano-of-second outputs zero, three, six
+ * or nine digits digits as necessary.
+ * The localized decimal style is not used.
+ *
+ * The instant is obtained using {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS}
+ * and optionally (@code NANO_OF_SECOND). The value of {@code INSTANT_SECONDS}
+ * may be outside the maximum range of {@code LocalDateTime}.
+ *
+ * The {@linkplain ResolverStyle resolver style} has no effect on instant parsing.
+ * The end-of-day time of '24:00' is handled as midnight at the start of the following day.
+ * The leap-second time of '23:59:59' is handled to some degree, see
+ * {@link DateTimeFormatter#parsedLeapSecond()} for full details.
*
* An alternative to this method is to format/parse the instant as a single
* epoch-seconds value. That is achieved using {@code appendValue(INSTANT_SECONDS)}.
@@ -669,10 +785,54 @@ public final class DateTimeFormatterBuilder {
* @return this, for chaining, not null
*/
public DateTimeFormatterBuilder appendInstant() {
- appendInternal(new InstantPrinterParser());
+ appendInternal(new InstantPrinterParser(-2));
return this;
}
+ /**
+ * Appends an instant using ISO-8601 to the formatter with control over
+ * the number of fractional digits.
+ *
+ * Instants have a fixed output format, although this method provides some
+ * control over the fractional digits. They are converted to a date-time
+ * with a zone-offset of UTC and printed using the standard ISO-8601 format.
+ * The localized decimal style is not used.
+ *
+ * The {@code fractionalDigits} parameter allows the output of the fractional
+ * second to be controlled. Specifying zero will cause no fractional digits
+ * to be output. From 1 to 9 will output an increasing number of digits, using
+ * zero right-padding if necessary. The special value -1 is used to output as
+ * many digits as necessary to avoid any trailing zeroes.
+ *
+ * When parsing in strict mode, the number of parsed digits must match the
+ * fractional digits. When parsing in lenient mode, any number of fractional
+ * digits from zero to nine are accepted.
+ *
+ * The instant is obtained using {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS}
+ * and optionally (@code NANO_OF_SECOND). The value of {@code INSTANT_SECONDS}
+ * may be outside the maximum range of {@code LocalDateTime}.
+ *
+ * The {@linkplain ResolverStyle resolver style} has no effect on instant parsing.
+ * The end-of-day time of '24:00' is handled as midnight at the start of the following day.
+ * The leap-second time of '23:59:59' is handled to some degree, see
+ * {@link DateTimeFormatter#parsedLeapSecond()} for full details.
+ *
+ * An alternative to this method is to format/parse the instant as a single
+ * epoch-seconds value. That is achieved using {@code appendValue(INSTANT_SECONDS)}.
+ *
+ * @param fractionalDigits the number of fractional second digits to format with,
+ * from 0 to 9, or -1 to use as many digits as necessary
+ * @return this, for chaining, not null
+ */
+ public DateTimeFormatterBuilder appendInstant(int fractionalDigits) {
+ if (fractionalDigits < -1 || fractionalDigits > 9) {
+ throw new IllegalArgumentException("The fractional digits must be from -1 to 9 inclusive but was " + fractionalDigits);
+ }
+ appendInternal(new InstantPrinterParser(fractionalDigits));
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
/**
* Appends the zone offset, such as '+01:00', to the formatter.
*
@@ -1049,7 +1209,7 @@ public final class DateTimeFormatterBuilder {
*
* The calendar system name will be output during a format.
* If the chronology cannot be obtained then an exception will be thrown.
- * The calendar system name is obtained from the formatting symbols.
+ * The calendar system name is obtained from the Chronology.
*
* @param textStyle the text style to use, not null
* @return this, for chaining, not null
@@ -1838,7 +1998,7 @@ public final class DateTimeFormatterBuilder {
* using the default locale.
*
* This will create a formatter with the {@linkplain Locale#getDefault(Locale.Category) default FORMAT locale}.
- * Numbers will be printed and parsed using the standard non-localized set of symbols.
+ * Numbers will be printed and parsed using the standard DecimalStyle.
* The resolver style will be {@link ResolverStyle#SMART SMART}.
*
* Calling this method will end any open optional sections by repeatedly
@@ -1858,7 +2018,7 @@ public final class DateTimeFormatterBuilder {
* using the specified locale.
*
* This will create a formatter with the specified locale.
- * Numbers will be printed and parsed using the standard non-localized set of symbols.
+ * Numbers will be printed and parsed using the standard DecimalStyle.
* The resolver style will be {@link ResolverStyle#SMART SMART}.
*
* Calling this method will end any open optional sections by repeatedly
@@ -1898,7 +2058,7 @@ public final class DateTimeFormatterBuilder {
optionalEnd();
}
CompositePrinterParser pp = new CompositePrinterParser(printerParsers, false);
- return new DateTimeFormatter(pp, locale, DateTimeFormatSymbols.STANDARD,
+ return new DateTimeFormatter(pp, locale, DecimalStyle.STANDARD,
resolverStyle, null, chrono, null);
}
@@ -1921,7 +2081,7 @@ public final class DateTimeFormatterBuilder {
* for the next parser. If an error occurs, the returned index will be negative
* and will have the error position encoded using the complement operator.
*
- *
Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
*
@@ -2282,24 +2442,25 @@ public final class DateTimeFormatterBuilder {
/**
* Array of 10 to the power of n.
*/
- static final int[] EXCEED_POINTS = new int[] {
- 0,
- 10,
- 100,
- 1000,
- 10000,
- 100000,
- 1000000,
- 10000000,
- 100000000,
- 1000000000,
+ static final long[] EXCEED_POINTS = new long[] {
+ 0L,
+ 10L,
+ 100L,
+ 1000L,
+ 10000L,
+ 100000L,
+ 1000000L,
+ 10000000L,
+ 100000000L,
+ 1000000000L,
+ 10000000000L,
};
final TemporalField field;
final int minWidth;
- private final int maxWidth;
+ final int maxWidth;
private final SignStyle signStyle;
- private final int subsequentWidth;
+ final int subsequentWidth;
/**
* Constructor.
@@ -2328,7 +2489,7 @@ public final class DateTimeFormatterBuilder {
* @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater,
* -1 if fixed width due to active adjacent parsing
*/
- private NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle, int subsequentWidth) {
+ protected NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle, int subsequentWidth) {
// validated by caller
this.field = field;
this.minWidth = minWidth;
@@ -2343,6 +2504,9 @@ public final class DateTimeFormatterBuilder {
* @return a new updated printer-parser, not null
*/
NumberPrinterParser withFixedWidth() {
+ if (subsequentWidth == -1) {
+ return this;
+ }
return new NumberPrinterParser(field, minWidth, maxWidth, signStyle, -1);
}
@@ -2363,24 +2527,24 @@ public final class DateTimeFormatterBuilder {
return false;
}
long value = getValue(valueLong);
- DateTimeFormatSymbols symbols = context.getSymbols();
+ DecimalStyle decimalStyle = context.getDecimalStyle();
String str = (value == Long.MIN_VALUE ? "9223372036854775808" : Long.toString(Math.abs(value)));
if (str.length() > maxWidth) {
throw new DateTimeException("Field " + field.getName() +
" cannot be printed as the value " + value +
" exceeds the maximum print width of " + maxWidth);
}
- str = symbols.convertNumberToI18N(str);
+ str = decimalStyle.convertNumberToI18N(str);
if (value >= 0) {
switch (signStyle) {
case EXCEEDS_PAD:
if (minWidth < 19 && value >= EXCEED_POINTS[minWidth]) {
- buf.append(symbols.getPositiveSign());
+ buf.append(decimalStyle.getPositiveSign());
}
break;
case ALWAYS:
- buf.append(symbols.getPositiveSign());
+ buf.append(decimalStyle.getPositiveSign());
break;
}
} else {
@@ -2388,7 +2552,7 @@ public final class DateTimeFormatterBuilder {
case NORMAL:
case EXCEEDS_PAD:
case ALWAYS:
- buf.append(symbols.getNegativeSign());
+ buf.append(decimalStyle.getNegativeSign());
break;
case NOT_NEGATIVE:
throw new DateTimeException("Field " + field.getName() +
@@ -2397,7 +2561,7 @@ public final class DateTimeFormatterBuilder {
}
}
for (int i = 0; i < minWidth - str.length(); i++) {
- buf.append(symbols.getZeroDigit());
+ buf.append(decimalStyle.getZeroDigit());
}
buf.append(str);
return true;
@@ -2426,13 +2590,13 @@ public final class DateTimeFormatterBuilder {
char sign = text.charAt(position); // IOOBE if invalid position
boolean negative = false;
boolean positive = false;
- if (sign == context.getSymbols().getPositiveSign()) {
+ if (sign == context.getDecimalStyle().getPositiveSign()) {
if (signStyle.parse(true, context.isStrict(), minWidth == maxWidth) == false) {
return ~position;
}
positive = true;
position++;
- } else if (sign == context.getSymbols().getNegativeSign()) {
+ } else if (sign == context.getDecimalStyle().getNegativeSign()) {
if (signStyle.parse(false, context.isStrict(), minWidth == maxWidth) == false) {
return ~position;
}
@@ -2448,7 +2612,7 @@ public final class DateTimeFormatterBuilder {
if (minEndPos > length) {
return ~position;
}
- int effMaxWidth = maxWidth + Math.max(subsequentWidth, 0);
+ int effMaxWidth = (context.isStrict() || isFixedWidth() ? maxWidth : 9) + Math.max(subsequentWidth, 0);
long total = 0;
BigInteger totalBig = null;
int pos = position;
@@ -2456,7 +2620,7 @@ public final class DateTimeFormatterBuilder {
int maxEndPos = Math.min(pos + effMaxWidth, length);
while (pos < maxEndPos) {
char ch = text.charAt(pos++);
- int digit = context.getSymbols().convertToDigit(ch);
+ int digit = context.getDecimalStyle().convertToDigit(ch);
if (digit < 0) {
pos--;
if (pos < minEndPos) {
@@ -2550,62 +2714,110 @@ public final class DateTimeFormatterBuilder {
*/
static final class ReducedPrinterParser extends NumberPrinterParser {
private final int baseValue;
- private final int range;
/**
* Constructor.
*
* @param field the field to format, validated not null
- * @param width the field width, from 1 to 18
+ * @param minWidth the minimum field width, from 1 to 10
+ * @param maxWidth the maximum field width, from 1 to 10
* @param baseValue the base value
*/
- ReducedPrinterParser(TemporalField field, int width, int baseValue) {
- super(field, width, width, SignStyle.NOT_NEGATIVE);
- if (width < 1 || width > 18) {
- throw new IllegalArgumentException("The width must be from 1 to 18 inclusive but was " + width);
+ ReducedPrinterParser(TemporalField field, int minWidth, int maxWidth,
+ int baseValue) {
+ this(field, minWidth, maxWidth, baseValue, 0);
+ if (minWidth < 1 || minWidth > 10) {
+ throw new IllegalArgumentException("The minWidth must be from 1 to 10 inclusive but was " + minWidth);
+ }
+ if (maxWidth < 1 || maxWidth > 10) {
+ throw new IllegalArgumentException("The maxWidth must be from 1 to 10 inclusive but was " + minWidth);
+ }
+ if (maxWidth < minWidth) {
+ throw new IllegalArgumentException("Maximum width must exceed or equal the minimum width but " +
+ maxWidth + " < " + minWidth);
}
if (field.range().isValidValue(baseValue) == false) {
throw new IllegalArgumentException("The base value must be within the range of the field");
}
- this.baseValue = baseValue;
- this.range = EXCEED_POINTS[width];
- if ((((long) baseValue) + range) > Integer.MAX_VALUE) {
+ if ((((long) baseValue) + EXCEED_POINTS[maxWidth]) > Integer.MAX_VALUE) {
throw new DateTimeException("Unable to add printer-parser as the range exceeds the capacity of an int");
}
}
+ /**
+ * Constructor.
+ * The arguments have already been checked.
+ *
+ * @param field the field to format, validated not null
+ * @param minWidth the minimum field width, from 1 to 10
+ * @param maxWidth the maximum field width, from 1 to 10
+ * @param baseValue the base value
+ * @param subsequentWidth the subsequentWidth for this instance
+ */
+ private ReducedPrinterParser(TemporalField field, int minWidth, int maxWidth,
+ int baseValue, int subsequentWidth) {
+ super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
+ this.baseValue = baseValue;
+ }
+
@Override
long getValue(long value) {
- return Math.abs(value % range);
+ long absValue = Math.abs(value);
+ if (value >= baseValue && value < baseValue + EXCEED_POINTS[minWidth]) {
+ // Use the reduced value if it fits in minWidth
+ return absValue % EXCEED_POINTS[minWidth];
+ }
+ // Otherwise truncate to fit in maxWidth
+ return absValue % EXCEED_POINTS[maxWidth];
}
@Override
int setValue(DateTimeParseContext context, long value, int errorPos, int successPos) {
- int lastPart = baseValue % range;
- if (baseValue > 0) {
- value = baseValue - lastPart + value;
- } else {
- value = baseValue - lastPart - value;
- }
- if (value < baseValue) {
- value += range;
+ int parseLen = successPos - errorPos;
+ if (parseLen == minWidth && value >= 0) {
+ long range = EXCEED_POINTS[minWidth];
+ long lastPart = baseValue % range;
+ long basePart = baseValue - lastPart;
+ if (baseValue > 0) {
+ value = basePart + value;
+ } else {
+ value = basePart - value;
+ }
+ if (basePart != 0 && value < baseValue) {
+ value += range;
+ }
}
return context.setParsedField(field, value, errorPos, successPos);
}
+ /**
+ * Returns a new instance with fixed width flag set.
+ *
+ * @return a new updated printer-parser, not null
+ */
@Override
- NumberPrinterParser withFixedWidth() {
- return this;
+ ReducedPrinterParser withFixedWidth() {
+ if (subsequentWidth == -1) {
+ return this;
+ }
+ return new ReducedPrinterParser(field, minWidth, maxWidth, baseValue, -1);
}
+ /**
+ * Returns a new instance with an updated subsequent width.
+ *
+ * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater
+ * @return a new updated printer-parser, not null
+ */
@Override
- boolean isFixedWidth() {
- return true;
+ ReducedPrinterParser withSubsequentWidth(int subsequentWidth) {
+ return new ReducedPrinterParser(field, minWidth, maxWidth, baseValue,
+ this.subsequentWidth + subsequentWidth);
}
@Override
public String toString() {
- return "ReducedValue(" + field.getName() + "," + minWidth + "," + baseValue + ")";
+ return "ReducedValue(" + field.getName() + "," + minWidth + "," + maxWidth + "," + baseValue + ")";
}
}
@@ -2654,24 +2866,24 @@ public final class DateTimeFormatterBuilder {
if (value == null) {
return false;
}
- DateTimeFormatSymbols symbols = context.getSymbols();
+ DecimalStyle decimalStyle = context.getDecimalStyle();
BigDecimal fraction = convertToFraction(value);
if (fraction.scale() == 0) { // scale is zero if value is zero
if (minWidth > 0) {
if (decimalPoint) {
- buf.append(symbols.getDecimalSeparator());
+ buf.append(decimalStyle.getDecimalSeparator());
}
for (int i = 0; i < minWidth; i++) {
- buf.append(symbols.getZeroDigit());
+ buf.append(decimalStyle.getZeroDigit());
}
}
} else {
int outputScale = Math.min(Math.max(fraction.scale(), minWidth), maxWidth);
fraction = fraction.setScale(outputScale, RoundingMode.FLOOR);
String str = fraction.toPlainString().substring(2);
- str = symbols.convertNumberToI18N(str);
+ str = decimalStyle.convertNumberToI18N(str);
if (decimalPoint) {
- buf.append(symbols.getDecimalSeparator());
+ buf.append(decimalStyle.getDecimalSeparator());
}
buf.append(str);
}
@@ -2688,7 +2900,7 @@ public final class DateTimeFormatterBuilder {
return (effectiveMin > 0 ? ~position : position);
}
if (decimalPoint) {
- if (text.charAt(position) != context.getSymbols().getDecimalSeparator()) {
+ if (text.charAt(position) != context.getDecimalStyle().getDecimalSeparator()) {
// valid if whole field is optional, invalid if minimum width
return (effectiveMin > 0 ? ~position : position);
}
@@ -2703,7 +2915,7 @@ public final class DateTimeFormatterBuilder {
int pos = position;
while (pos < maxEndPos) {
char ch = text.charAt(pos++);
- int digit = context.getSymbols().convertToDigit(ch);
+ int digit = context.getDecimalStyle().convertToDigit(ch);
if (digit < 0) {
if (pos < minEndPos) {
return ~position; // need at least min width digits
@@ -2883,43 +3095,50 @@ public final class DateTimeFormatterBuilder {
// seconds per day = 86400
private static final long SECONDS_PER_10000_YEARS = 146097L * 25L * 86400L;
private static final long SECONDS_0000_TO_1970 = ((146097L * 5L) - (30L * 365L + 7L)) * 86400L;
- private static final CompositePrinterParser PARSER = new DateTimeFormatterBuilder()
- .parseCaseInsensitive()
- .append(DateTimeFormatter.ISO_LOCAL_DATE).appendLiteral('T')
- .append(DateTimeFormatter.ISO_LOCAL_TIME).appendLiteral('Z')
- .toFormatter().toPrinterParser(false);
+ private final int fractionalDigits;
- InstantPrinterParser() {
+ InstantPrinterParser(int fractionalDigits) {
+ this.fractionalDigits = fractionalDigits;
}
@Override
public boolean format(DateTimePrintContext context, StringBuilder buf) {
// use INSTANT_SECONDS, thus this code is not bound by Instant.MAX
Long inSecs = context.getValue(INSTANT_SECONDS);
- Long inNanos = context.getValue(NANO_OF_SECOND);
- if (inSecs == null || inNanos == null) {
+ Long inNanos = null;
+ if (context.getTemporal().isSupported(NANO_OF_SECOND)) {
+ inNanos = context.getTemporal().getLong(NANO_OF_SECOND);
+ }
+ if (inSecs == null) {
return false;
}
long inSec = inSecs;
- int inNano = NANO_OF_SECOND.checkValidIntValue(inNanos);
+ int inNano = NANO_OF_SECOND.checkValidIntValue(inNanos != null ? inNanos : 0);
+ // format mostly using LocalDateTime.toString
if (inSec >= -SECONDS_0000_TO_1970) {
// current era
long zeroSecs = inSec - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970;
long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1;
long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS);
- LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, inNano, ZoneOffset.UTC);
+ LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC);
if (hi > 0) {
buf.append('+').append(hi);
}
- buf.append(ldt).append('Z');
+ buf.append(ldt);
+ if (ldt.getSecond() == 0) {
+ buf.append(":00");
+ }
} else {
// before current era
long zeroSecs = inSec + SECONDS_0000_TO_1970;
long hi = zeroSecs / SECONDS_PER_10000_YEARS;
long lo = zeroSecs % SECONDS_PER_10000_YEARS;
- LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, inNano, ZoneOffset.UTC);
+ LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC);
int pos = buf.length();
- buf.append(ldt).append('Z');
+ buf.append(ldt);
+ if (ldt.getSecond() == 0) {
+ buf.append(":00");
+ }
if (hi < 0) {
if (ldt.getYear() == -10_000) {
buf.replace(pos, pos + 2, Long.toString(hi - 1));
@@ -2930,14 +3149,38 @@ public final class DateTimeFormatterBuilder {
}
}
}
+ // add fraction
+ if ((fractionalDigits < 0 && inNano > 0) || fractionalDigits > 0) {
+ buf.append('.');
+ int div = 100_000_000;
+ for (int i = 0; ((fractionalDigits == -1 && inNano > 0) ||
+ (fractionalDigits == -2 && (inNano > 0 || (i % 3) != 0)) ||
+ i < fractionalDigits); i++) {
+ int digit = inNano / div;
+ buf.append((char) (digit + '0'));
+ inNano = inNano - (digit * div);
+ div = div / 10;
+ }
+ }
+ buf.append('Z');
return true;
}
@Override
public int parse(DateTimeParseContext context, CharSequence text, int position) {
// new context to avoid overwriting fields like year/month/day
+ int minDigits = (fractionalDigits < 0 ? 0 : fractionalDigits);
+ int maxDigits = (fractionalDigits < 0 ? 9 : fractionalDigits);
+ CompositePrinterParser parser = new DateTimeFormatterBuilder()
+ .append(DateTimeFormatter.ISO_LOCAL_DATE).appendLiteral('T')
+ .appendValue(HOUR_OF_DAY, 2).appendLiteral(':')
+ .appendValue(MINUTE_OF_HOUR, 2).appendLiteral(':')
+ .appendValue(SECOND_OF_MINUTE, 2)
+ .appendFraction(NANO_OF_SECOND, minDigits, maxDigits, true)
+ .appendLiteral('Z')
+ .toFormatter().toPrinterParser(false);
DateTimeParseContext newContext = context.copy();
- int pos = PARSER.parse(newContext, text, position);
+ int pos = parser.parse(newContext, text, position);
if (pos < 0) {
return pos;
}
@@ -2952,10 +3195,18 @@ public final class DateTimeFormatterBuilder {
Long nanoVal = newContext.getParsed(NANO_OF_SECOND);
int sec = (secVal != null ? secVal.intValue() : 0);
int nano = (nanoVal != null ? nanoVal.intValue() : 0);
+ int days = 0;
+ if (hour == 24 && min == 0 && sec == 0 && nano == 0) {
+ hour = 0;
+ days = 1;
+ } else if (hour == 23 && min == 59 && sec == 60) {
+ context.setParsedLeapSecond();
+ sec = 59;
+ }
int year = (int) yearParsed % 10_000;
long instantSecs;
try {
- LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, min, sec, 0);
+ LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, min, sec, 0).plusDays(days);
instantSecs = ldt.toEpochSecond(ZoneOffset.UTC);
instantSecs += Math.multiplyExact(yearParsed / 10_000L, SECONDS_PER_10000_YEARS);
} catch (RuntimeException ex) {
@@ -4017,9 +4268,7 @@ public final class DateTimeFormatterBuilder {
String key = chrono.getId() + '|' + locale.toString() + '|' + dateStyle + timeStyle;
DateTimeFormatter formatter = FORMATTER_CACHE.get(key);
if (formatter == null) {
- LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale);
- String pattern = lr.getJavaTimeDateTimePattern(
- convertStyle(timeStyle), convertStyle(dateStyle), chrono.getCalendarType());
+ String pattern = getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale);
formatter = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale);
DateTimeFormatter old = FORMATTER_CACHE.putIfAbsent(key, formatter);
if (old != null) {
@@ -4029,19 +4278,6 @@ public final class DateTimeFormatterBuilder {
return formatter;
}
- /**
- * Converts the given FormatStyle to the java.text.DateFormat style.
- *
- * @param style the FormatStyle style
- * @return the int style, or -1 if style is null, indicating unrequired
- */
- private int convertStyle(FormatStyle style) {
- if (style == null) {
- return -1;
- }
- return style.ordinal(); // indices happen to align
- }
-
@Override
public String toString() {
return "Localized(" + (dateStyle != null ? dateStyle : "") + "," +
@@ -4096,7 +4332,7 @@ public final class DateTimeFormatterBuilder {
case 'Y':
field = weekDef.weekBasedYear();
if (count == 2) {
- return new ReducedPrinterParser(field, 2, 2000);
+ return new ReducedPrinterParser(field, 2, 2, 2000, 0);
} else {
return new NumberPrinterParser(field, count, 19,
(count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);
diff --git a/jdk/src/share/classes/java/time/format/DateTimeParseContext.java b/jdk/src/share/classes/java/time/format/DateTimeParseContext.java
index f2e3ff3a300..f72ef7b77c9 100644
--- a/jdk/src/share/classes/java/time/format/DateTimeParseContext.java
+++ b/jdk/src/share/classes/java/time/format/DateTimeParseContext.java
@@ -61,6 +61,7 @@
*/
package java.time.format;
+import java.time.Duration;
import java.time.ZoneId;
import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
@@ -79,7 +80,7 @@ import java.util.Objects;
* Once parsing is complete, the {@link #toParsed()} is used to obtain the data.
* It contains a method to resolve the separate parsed fields into meaningful values.
*
- *
Specification for implementors
+ * @implSpec
* This class is a mutable context intended for use from a single thread.
* Usage of the class is thread-safe within standard parsing as a new instance of this class
* is automatically created for each parse and parsing is single-threaded
@@ -118,9 +119,13 @@ final class DateTimeParseContext {
/**
* Creates a copy of this context.
+ * This retains the case sensitive and strict flags.
*/
DateTimeParseContext copy() {
- return new DateTimeParseContext(formatter);
+ DateTimeParseContext newContext = new DateTimeParseContext(formatter);
+ newContext.caseSensitive = caseSensitive;
+ newContext.strict = strict;
+ return newContext;
}
//-----------------------------------------------------------------------
@@ -128,7 +133,7 @@ final class DateTimeParseContext {
* Gets the locale.
*
* This locale is used to control localization in the parse except
- * where localization is controlled by the symbols.
+ * where localization is controlled by the DecimalStyle.
*
* @return the locale, not null
*/
@@ -137,14 +142,14 @@ final class DateTimeParseContext {
}
/**
- * Gets the formatting symbols.
+ * Gets the DecimalStyle.
*
- * The symbols control the localization of numeric parsing.
+ * The DecimalStyle controls the numeric parsing.
*
- * @return the formatting symbols, not null
+ * @return the DecimalStyle, not null
*/
- DateTimeFormatSymbols getSymbols() {
- return formatter.getSymbols();
+ DecimalStyle getDecimalStyle() {
+ return formatter.getDecimalStyle();
}
/**
@@ -370,6 +375,13 @@ final class DateTimeParseContext {
currentParsed().zone = zone;
}
+ /**
+ * Stores the parsed leap second.
+ */
+ void setParsedLeapSecond() {
+ currentParsed().leapSecond = true;
+ }
+
//-----------------------------------------------------------------------
/**
* Returns a string version of the context for debugging.
diff --git a/jdk/src/share/classes/java/time/format/DateTimeParseException.java b/jdk/src/share/classes/java/time/format/DateTimeParseException.java
index 37b72a2f92a..d02ed15a046 100644
--- a/jdk/src/share/classes/java/time/format/DateTimeParseException.java
+++ b/jdk/src/share/classes/java/time/format/DateTimeParseException.java
@@ -68,7 +68,7 @@ import java.time.DateTimeException;
*
* This exception includes the text being parsed and the error index.
*
- *
Specification for implementors
+ * @implSpec
* This class is intended for use in a single thread.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/format/DateTimePrintContext.java b/jdk/src/share/classes/java/time/format/DateTimePrintContext.java
index 8124fc85c98..3e3f90fb5eb 100644
--- a/jdk/src/share/classes/java/time/format/DateTimePrintContext.java
+++ b/jdk/src/share/classes/java/time/format/DateTimePrintContext.java
@@ -85,7 +85,7 @@ import java.util.Objects;
*
* This class provides a single wrapper to items used in the format.
*
- *
Specification for implementors
+ * @implSpec
* This class is a mutable context intended for use from a single thread.
* Usage of the class is thread-safe within standard printing as the framework creates
* a new instance of the class for each format and printing is single-threaded.
@@ -234,7 +234,7 @@ final class DateTimePrintContext {
* Gets the locale.
*
* This locale is used to control localization in the format output except
- * where localization is controlled by the symbols.
+ * where localization is controlled by the DecimalStyle.
*
* @return the locale, not null
*/
@@ -243,14 +243,14 @@ final class DateTimePrintContext {
}
/**
- * Gets the formatting symbols.
+ * Gets the DecimalStyle.
*
- * The symbols control the localization of numeric output.
+ * The DecimalStyle controls the localization of numeric output.
*
- * @return the formatting symbols, not null
+ * @return the DecimalStyle, not null
*/
- DateTimeFormatSymbols getSymbols() {
- return formatter.getSymbols();
+ DecimalStyle getDecimalStyle() {
+ return formatter.getDecimalStyle();
}
//-----------------------------------------------------------------------
diff --git a/jdk/src/share/classes/java/time/format/DateTimeTextProvider.java b/jdk/src/share/classes/java/time/format/DateTimeTextProvider.java
index 7262c5b3341..4e1bd4a811f 100644
--- a/jdk/src/share/classes/java/time/format/DateTimeTextProvider.java
+++ b/jdk/src/share/classes/java/time/format/DateTimeTextProvider.java
@@ -94,7 +94,7 @@ import sun.util.locale.provider.LocaleResources;
/**
* A provider to obtain the textual form of a date-time field.
*
- *
Specification for implementors
+ * @implSpec
* Implementations must be thread-safe.
* Implementations should cache the textual information.
*
diff --git a/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java b/jdk/src/share/classes/java/time/format/DecimalStyle.java
similarity index 82%
rename from jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java
rename to jdk/src/share/classes/java/time/format/DecimalStyle.java
index 0bfe8441020..8143037feff 100644
--- a/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java
+++ b/jdk/src/share/classes/java/time/format/DecimalStyle.java
@@ -62,34 +62,38 @@
package java.time.format;
import java.text.DecimalFormatSymbols;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Locale;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
- * Localized symbols used in date and time formatting.
+ * Localized decimal style used in date and time formatting.
*
* A significant part of dealing with dates and times is the localization.
* This class acts as a central point for accessing the information.
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
*/
-public final class DateTimeFormatSymbols {
+public final class DecimalStyle {
/**
- * The standard set of non-localized symbols.
+ * The standard set of non-localized decimal style symbols.
*
* This uses standard ASCII characters for zero, positive, negative and a dot for the decimal point.
*/
- public static final DateTimeFormatSymbols STANDARD = new DateTimeFormatSymbols('0', '+', '-', '.');
+ public static final DecimalStyle STANDARD = new DecimalStyle('0', '+', '-', '.');
/**
- * The cache of symbols instances.
+ * The cache of DecimalStyle instances.
*/
- private static final ConcurrentMap CACHE = new ConcurrentHashMap<>(16, 0.75f, 2);
+ private static final ConcurrentMap CACHE = new ConcurrentHashMap<>(16, 0.75f, 2);
/**
* The zero digit.
@@ -114,17 +118,20 @@ public final class DateTimeFormatSymbols {
*
* The locale 'en_US' will always be present.
*
- * @return an array of locales for which localization is supported
+ * @return a Set of Locales for which localization is supported
*/
- public static Locale[] getAvailableLocales() {
- return DecimalFormatSymbols.getAvailableLocales();
+ public static Set getAvailableLocales() {
+ Locale[] l = DecimalFormatSymbols.getAvailableLocales();
+ Set locales = new HashSet<>(l.length);
+ Collections.addAll(locales, l);
+ return locales;
}
/**
- * Obtains symbols for the default
+ * Obtains the DecimalStyle for the default
* {@link java.util.Locale.Category#FORMAT FORMAT} locale.
*
- * This method provides access to locale sensitive symbols.
+ * This method provides access to locale sensitive decimal style symbols.
*
* This is equivalent to calling
* {@link #of(Locale)
@@ -133,21 +140,21 @@ public final class DateTimeFormatSymbols {
* @see java.util.Locale.Category#FORMAT
* @return the info, not null
*/
- public static DateTimeFormatSymbols ofDefaultLocale() {
+ public static DecimalStyle ofDefaultLocale() {
return of(Locale.getDefault(Locale.Category.FORMAT));
}
/**
- * Obtains symbols for the specified locale.
+ * Obtains the DecimalStyle for the specified locale.
*
- * This method provides access to locale sensitive symbols.
+ * This method provides access to locale sensitive decimal style symbols.
*
* @param locale the locale, not null
* @return the info, not null
*/
- public static DateTimeFormatSymbols of(Locale locale) {
+ public static DecimalStyle of(Locale locale) {
Objects.requireNonNull(locale, "locale");
- DateTimeFormatSymbols info = CACHE.get(locale);
+ DecimalStyle info = CACHE.get(locale);
if (info == null) {
info = create(locale);
CACHE.putIfAbsent(locale, info);
@@ -156,7 +163,7 @@ public final class DateTimeFormatSymbols {
return info;
}
- private static DateTimeFormatSymbols create(Locale locale) {
+ private static DecimalStyle create(Locale locale) {
DecimalFormatSymbols oldSymbols = DecimalFormatSymbols.getInstance(locale);
char zeroDigit = oldSymbols.getZeroDigit();
char positiveSign = '+';
@@ -165,7 +172,7 @@ public final class DateTimeFormatSymbols {
if (zeroDigit == '0' && negativeSign == '-' && decimalSeparator == '.') {
return STANDARD;
}
- return new DateTimeFormatSymbols(zeroDigit, positiveSign, negativeSign, decimalSeparator);
+ return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
}
//-----------------------------------------------------------------------
@@ -177,7 +184,7 @@ public final class DateTimeFormatSymbols {
* @param negativeSignChar the character to use for the negative sign
* @param decimalPointChar the character to use for the decimal point
*/
- private DateTimeFormatSymbols(char zeroChar, char positiveSignChar, char negativeSignChar, char decimalPointChar) {
+ private DecimalStyle(char zeroChar, char positiveSignChar, char negativeSignChar, char decimalPointChar) {
this.zeroDigit = zeroChar;
this.positiveSign = positiveSignChar;
this.negativeSign = negativeSignChar;
@@ -207,11 +214,11 @@ public final class DateTimeFormatSymbols {
* @return a copy with a new character that represents zero, not null
*/
- public DateTimeFormatSymbols withZeroDigit(char zeroDigit) {
+ public DecimalStyle withZeroDigit(char zeroDigit) {
if (zeroDigit == this.zeroDigit) {
return this;
}
- return new DateTimeFormatSymbols(zeroDigit, positiveSign, negativeSign, decimalSeparator);
+ return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
}
//-----------------------------------------------------------------------
@@ -236,11 +243,11 @@ public final class DateTimeFormatSymbols {
* @param positiveSign the character for the positive sign
* @return a copy with a new character that represents the positive sign, not null
*/
- public DateTimeFormatSymbols withPositiveSign(char positiveSign) {
+ public DecimalStyle withPositiveSign(char positiveSign) {
if (positiveSign == this.positiveSign) {
return this;
}
- return new DateTimeFormatSymbols(zeroDigit, positiveSign, negativeSign, decimalSeparator);
+ return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
}
//-----------------------------------------------------------------------
@@ -265,11 +272,11 @@ public final class DateTimeFormatSymbols {
* @param negativeSign the character for the negative sign
* @return a copy with a new character that represents the negative sign, not null
*/
- public DateTimeFormatSymbols withNegativeSign(char negativeSign) {
+ public DecimalStyle withNegativeSign(char negativeSign) {
if (negativeSign == this.negativeSign) {
return this;
}
- return new DateTimeFormatSymbols(zeroDigit, positiveSign, negativeSign, decimalSeparator);
+ return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
}
//-----------------------------------------------------------------------
@@ -294,11 +301,11 @@ public final class DateTimeFormatSymbols {
* @param decimalSeparator the character for the decimal point
* @return a copy with a new character that represents the decimal point, not null
*/
- public DateTimeFormatSymbols withDecimalSeparator(char decimalSeparator) {
+ public DecimalStyle withDecimalSeparator(char decimalSeparator) {
if (decimalSeparator == this.decimalSeparator) {
return this;
}
- return new DateTimeFormatSymbols(zeroDigit, positiveSign, negativeSign, decimalSeparator);
+ return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
}
//-----------------------------------------------------------------------
@@ -333,7 +340,7 @@ public final class DateTimeFormatSymbols {
//-----------------------------------------------------------------------
/**
- * Checks if these symbols equal another set of symbols.
+ * Checks if this DecimalStyle is equal another DecimalStyle.
*
* @param obj the object to check, null returns false
* @return true if this is equal to the other date
@@ -343,8 +350,8 @@ public final class DateTimeFormatSymbols {
if (this == obj) {
return true;
}
- if (obj instanceof DateTimeFormatSymbols) {
- DateTimeFormatSymbols other = (DateTimeFormatSymbols) obj;
+ if (obj instanceof DecimalStyle) {
+ DecimalStyle other = (DecimalStyle) obj;
return (zeroDigit == other.zeroDigit && positiveSign == other.positiveSign &&
negativeSign == other.negativeSign && decimalSeparator == other.decimalSeparator);
}
@@ -352,7 +359,7 @@ public final class DateTimeFormatSymbols {
}
/**
- * A hash code for these symbols.
+ * A hash code for this DecimalStyle.
*
* @return a suitable hash code
*/
@@ -363,13 +370,13 @@ public final class DateTimeFormatSymbols {
//-----------------------------------------------------------------------
/**
- * Returns a string describing these symbols.
+ * Returns a string describing this DecimalStyle.
*
* @return a string description, not null
*/
@Override
public String toString() {
- return "Symbols[" + zeroDigit + positiveSign + negativeSign + decimalSeparator + "]";
+ return "DecimalStyle[" + zeroDigit + positiveSign + negativeSign + decimalSeparator + "]";
}
}
diff --git a/jdk/src/share/classes/java/time/format/FormatStyle.java b/jdk/src/share/classes/java/time/format/FormatStyle.java
index 0be538e28dd..a5c82295405 100644
--- a/jdk/src/share/classes/java/time/format/FormatStyle.java
+++ b/jdk/src/share/classes/java/time/format/FormatStyle.java
@@ -67,7 +67,7 @@ package java.time.format;
* These styles are used when obtaining a date-time style from configuration.
* See {@link DateTimeFormatter} and {@link DateTimeFormatterBuilder} for usage.
*
- *
Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/format/Parsed.java b/jdk/src/share/classes/java/time/format/Parsed.java
index a35fab1b9d8..b0a7fe810d9 100644
--- a/jdk/src/share/classes/java/time/format/Parsed.java
+++ b/jdk/src/share/classes/java/time/format/Parsed.java
@@ -80,6 +80,7 @@ import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalTime;
+import java.time.Period;
import java.time.ZoneId;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
@@ -105,7 +106,7 @@ import java.util.Set;
* Once parsing is completed, this class can be used as the resultant {@code TemporalAccessor}.
* In most cases, it is only exposed once the fields have been resolved.
*
- * Specification for implementors
+ * @implSpec
* This class is a mutable context intended for use from a single thread.
* Usage of the class is thread-safe within standard parsing as a new instance of this class
* is automatically created for each parse and parsing is single-threaded
@@ -127,6 +128,10 @@ final class Parsed implements TemporalAccessor {
* The parsed chronology.
*/
Chronology chrono;
+ /**
+ * Whether a leap-second is parsed.
+ */
+ boolean leapSecond;
/**
* The effective chronology.
*/
@@ -143,6 +148,10 @@ final class Parsed implements TemporalAccessor {
* The resolved time.
*/
private LocalTime time;
+ /**
+ * The excess period from time-only parsing.
+ */
+ Period excessDays = Period.ZERO;
/**
* Creates an instance.
@@ -159,6 +168,7 @@ final class Parsed implements TemporalAccessor {
cloned.fieldValues.putAll(this.fieldValues);
cloned.zone = this.zone;
cloned.chrono = this.chrono;
+ cloned.leapSecond = this.leapSecond;
return cloned;
}
@@ -232,6 +242,7 @@ final class Parsed implements TemporalAccessor {
resolveFields();
resolveTimeLenient();
crossCheck();
+ resolvePeriod();
return this;
}
@@ -308,36 +319,72 @@ final class Parsed implements TemporalAccessor {
private void resolveTimeFields() {
// simplify fields
if (fieldValues.containsKey(CLOCK_HOUR_OF_DAY)) {
+ // lenient allows anything, smart allows 0-24, strict allows 1-24
long ch = fieldValues.remove(CLOCK_HOUR_OF_DAY);
+ if (resolverStyle == ResolverStyle.STRICT || (resolverStyle == ResolverStyle.SMART && ch != 0)) {
+ CLOCK_HOUR_OF_DAY.checkValidValue(ch);
+ }
updateCheckConflict(CLOCK_HOUR_OF_DAY, HOUR_OF_DAY, ch == 24 ? 0 : ch);
}
if (fieldValues.containsKey(CLOCK_HOUR_OF_AMPM)) {
+ // lenient allows anything, smart allows 0-12, strict allows 1-12
long ch = fieldValues.remove(CLOCK_HOUR_OF_AMPM);
+ if (resolverStyle == ResolverStyle.STRICT || (resolverStyle == ResolverStyle.SMART && ch != 0)) {
+ CLOCK_HOUR_OF_AMPM.checkValidValue(ch);
+ }
updateCheckConflict(CLOCK_HOUR_OF_AMPM, HOUR_OF_AMPM, ch == 12 ? 0 : ch);
}
if (fieldValues.containsKey(AMPM_OF_DAY) && fieldValues.containsKey(HOUR_OF_AMPM)) {
long ap = fieldValues.remove(AMPM_OF_DAY);
long hap = fieldValues.remove(HOUR_OF_AMPM);
- updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, ap * 12 + hap);
+ if (resolverStyle == ResolverStyle.LENIENT) {
+ updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, Math.addExact(Math.multiplyExact(ap, 12), hap));
+ } else { // STRICT or SMART
+ AMPM_OF_DAY.checkValidValue(ap);
+ HOUR_OF_AMPM.checkValidValue(ap);
+ updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, ap * 12 + hap);
+ }
+ }
+ if (fieldValues.containsKey(NANO_OF_DAY)) {
+ long nod = fieldValues.remove(NANO_OF_DAY);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ NANO_OF_DAY.checkValidValue(nod);
+ }
+ updateCheckConflict(NANO_OF_DAY, HOUR_OF_DAY, nod / 3600_000_000_000L);
+ updateCheckConflict(NANO_OF_DAY, MINUTE_OF_HOUR, (nod / 60_000_000_000L) % 60);
+ updateCheckConflict(NANO_OF_DAY, SECOND_OF_MINUTE, (nod / 1_000_000_000L) % 60);
+ updateCheckConflict(NANO_OF_DAY, NANO_OF_SECOND, nod % 1_000_000_000L);
}
if (fieldValues.containsKey(MICRO_OF_DAY)) {
long cod = fieldValues.remove(MICRO_OF_DAY);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ MICRO_OF_DAY.checkValidValue(cod);
+ }
updateCheckConflict(MICRO_OF_DAY, SECOND_OF_DAY, cod / 1_000_000L);
updateCheckConflict(MICRO_OF_DAY, MICRO_OF_SECOND, cod % 1_000_000L);
}
if (fieldValues.containsKey(MILLI_OF_DAY)) {
long lod = fieldValues.remove(MILLI_OF_DAY);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ MILLI_OF_DAY.checkValidValue(lod);
+ }
updateCheckConflict(MILLI_OF_DAY, SECOND_OF_DAY, lod / 1_000);
updateCheckConflict(MILLI_OF_DAY, MILLI_OF_SECOND, lod % 1_000);
}
if (fieldValues.containsKey(SECOND_OF_DAY)) {
long sod = fieldValues.remove(SECOND_OF_DAY);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ SECOND_OF_DAY.checkValidValue(sod);
+ }
updateCheckConflict(SECOND_OF_DAY, HOUR_OF_DAY, sod / 3600);
updateCheckConflict(SECOND_OF_DAY, MINUTE_OF_HOUR, (sod / 60) % 60);
updateCheckConflict(SECOND_OF_DAY, SECOND_OF_MINUTE, sod % 60);
}
if (fieldValues.containsKey(MINUTE_OF_DAY)) {
long mod = fieldValues.remove(MINUTE_OF_DAY);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ MINUTE_OF_DAY.checkValidValue(mod);
+ }
updateCheckConflict(MINUTE_OF_DAY, HOUR_OF_DAY, mod / 60);
updateCheckConflict(MINUTE_OF_DAY, MINUTE_OF_HOUR, mod % 60);
}
@@ -345,29 +392,34 @@ final class Parsed implements TemporalAccessor {
// combine partial second fields strictly, leaving lenient expansion to later
if (fieldValues.containsKey(NANO_OF_SECOND)) {
long nos = fieldValues.get(NANO_OF_SECOND);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ NANO_OF_SECOND.checkValidValue(nos);
+ }
if (fieldValues.containsKey(MICRO_OF_SECOND)) {
long cos = fieldValues.remove(MICRO_OF_SECOND);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ MICRO_OF_SECOND.checkValidValue(cos);
+ }
nos = cos * 1000 + (nos % 1000);
updateCheckConflict(MICRO_OF_SECOND, NANO_OF_SECOND, nos);
}
if (fieldValues.containsKey(MILLI_OF_SECOND)) {
long los = fieldValues.remove(MILLI_OF_SECOND);
+ if (resolverStyle != ResolverStyle.LENIENT) {
+ MILLI_OF_SECOND.checkValidValue(los);
+ }
updateCheckConflict(MILLI_OF_SECOND, NANO_OF_SECOND, los * 1_000_000L + (nos % 1_000_000L));
}
}
- // convert to time if possible
- if (fieldValues.containsKey(NANO_OF_DAY)) {
- long nod = fieldValues.remove(NANO_OF_DAY);
- updateCheckConflict(LocalTime.ofNanoOfDay(nod));
- }
+ // convert to time if all four fields available (optimization)
if (fieldValues.containsKey(HOUR_OF_DAY) && fieldValues.containsKey(MINUTE_OF_HOUR) &&
fieldValues.containsKey(SECOND_OF_MINUTE) && fieldValues.containsKey(NANO_OF_SECOND)) {
- int hodVal = HOUR_OF_DAY.checkValidIntValue(fieldValues.remove(HOUR_OF_DAY));
- int mohVal = MINUTE_OF_HOUR.checkValidIntValue(fieldValues.remove(MINUTE_OF_HOUR));
- int somVal = SECOND_OF_MINUTE.checkValidIntValue(fieldValues.remove(SECOND_OF_MINUTE));
- int nosVal = NANO_OF_SECOND.checkValidIntValue(fieldValues.remove(NANO_OF_SECOND));
- updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal));
+ long hod = fieldValues.remove(HOUR_OF_DAY);
+ long moh = fieldValues.remove(MINUTE_OF_HOUR);
+ long som = fieldValues.remove(SECOND_OF_MINUTE);
+ long nos = fieldValues.remove(NANO_OF_SECOND);
+ resolveTime(hod, moh, som, nos);
}
}
@@ -377,7 +429,7 @@ final class Parsed implements TemporalAccessor {
// which would break updateCheckConflict(field)
if (time == null) {
- // can only get here if NANO_OF_SECOND not present
+ // NANO_OF_SECOND merged with MILLI/MICRO above
if (fieldValues.containsKey(MILLI_OF_SECOND)) {
long los = fieldValues.remove(MILLI_OF_SECOND);
if (fieldValues.containsKey(MICRO_OF_SECOND)) {
@@ -395,43 +447,87 @@ final class Parsed implements TemporalAccessor {
long cos = fieldValues.remove(MICRO_OF_SECOND);
fieldValues.put(NANO_OF_SECOND, cos * 1_000L);
}
- }
- // merge hour/minute/second/nano leniently
- Long hod = fieldValues.get(HOUR_OF_DAY);
- if (hod != null) {
- int hodVal = HOUR_OF_DAY.checkValidIntValue(hod);
- Long moh = fieldValues.get(MINUTE_OF_HOUR);
- Long som = fieldValues.get(SECOND_OF_MINUTE);
- Long nos = fieldValues.get(NANO_OF_SECOND);
+ // merge hour/minute/second/nano leniently
+ Long hod = fieldValues.get(HOUR_OF_DAY);
+ if (hod != null) {
+ Long moh = fieldValues.get(MINUTE_OF_HOUR);
+ Long som = fieldValues.get(SECOND_OF_MINUTE);
+ Long nos = fieldValues.get(NANO_OF_SECOND);
- // check for invalid combinations that cannot be defaulted
- if (time == null) {
+ // check for invalid combinations that cannot be defaulted
if ((moh == null && (som != null || nos != null)) ||
(moh != null && som == null && nos != null)) {
return;
}
- }
- // default as necessary and build time
- int mohVal = (moh != null ? MINUTE_OF_HOUR.checkValidIntValue(moh) : (time != null ? time.getMinute() : 0));
- int somVal = (som != null ? SECOND_OF_MINUTE.checkValidIntValue(som) : (time != null ? time.getSecond() : 0));
- int nosVal = (nos != null ? NANO_OF_SECOND.checkValidIntValue(nos) : (time != null ? time.getNano() : 0));
- updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal));
- fieldValues.remove(HOUR_OF_DAY);
- fieldValues.remove(MINUTE_OF_HOUR);
- fieldValues.remove(SECOND_OF_MINUTE);
- fieldValues.remove(NANO_OF_SECOND);
+ // default as necessary and build time
+ long mohVal = (moh != null ? moh : 0);
+ long somVal = (som != null ? som : 0);
+ long nosVal = (nos != null ? nos : 0);
+ resolveTime(hod, mohVal, somVal, nosVal);
+ fieldValues.remove(HOUR_OF_DAY);
+ fieldValues.remove(MINUTE_OF_HOUR);
+ fieldValues.remove(SECOND_OF_MINUTE);
+ fieldValues.remove(NANO_OF_SECOND);
+ }
+ }
+
+ // validate remaining
+ if (resolverStyle != ResolverStyle.LENIENT && fieldValues.size() > 0) {
+ for (Entry entry : fieldValues.entrySet()) {
+ TemporalField field = entry.getKey();
+ if (field instanceof ChronoField && field.isTimeBased()) {
+ ((ChronoField) field).checkValidValue(entry.getValue());
+ }
+ }
}
}
- private void updateCheckConflict(LocalTime lt) {
+ private void resolveTime(long hod, long moh, long som, long nos) {
+ if (resolverStyle == ResolverStyle.LENIENT) {
+ long totalNanos = Math.multiplyExact(hod, 3600_000_000_000L);
+ totalNanos = Math.addExact(totalNanos, Math.multiplyExact(moh, 60_000_000_000L));
+ totalNanos = Math.addExact(totalNanos, Math.multiplyExact(som, 1_000_000_000L));
+ totalNanos = Math.addExact(totalNanos, nos);
+ int excessDays = (int) Math.floorDiv(totalNanos, 86400_000_000_000L); // safe int cast
+ long nod = Math.floorMod(totalNanos, 86400_000_000_000L);
+ updateCheckConflict(LocalTime.ofNanoOfDay(nod), Period.ofDays(excessDays));
+ } else { // STRICT or SMART
+ int mohVal = MINUTE_OF_HOUR.checkValidIntValue(moh);
+ int nosVal = NANO_OF_SECOND.checkValidIntValue(nos);
+ // handle 24:00 end of day
+ if (resolverStyle == ResolverStyle.SMART && hod == 24 && mohVal == 0 && som == 0 && nosVal == 0) {
+ updateCheckConflict(LocalTime.MIDNIGHT, Period.ofDays(1));
+ } else {
+ int hodVal = HOUR_OF_DAY.checkValidIntValue(hod);
+ int somVal = SECOND_OF_MINUTE.checkValidIntValue(som);
+ updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal), Period.ZERO);
+ }
+ }
+ }
+
+ private void resolvePeriod() {
+ // add whole days if we have both date and time
+ if (date != null && time != null && excessDays.isZero() == false) {
+ date = date.plus(excessDays);
+ excessDays = Period.ZERO;
+ }
+ }
+
+ private void updateCheckConflict(LocalTime timeToSet, Period periodToSet) {
if (time != null) {
- if (lt != null && time.equals(lt) == false) {
- throw new DateTimeException("Conflict found: Fields resolved to two different times: " + time + " " + lt);
+ if (time.equals(timeToSet) == false) {
+ throw new DateTimeException("Conflict found: Fields resolved to different times: " + time + " " + timeToSet);
+ }
+ if (excessDays.isZero() == false && periodToSet.isZero() == false && excessDays.equals(periodToSet) == false) {
+ throw new DateTimeException("Conflict found: Fields resolved to different excess periods: " + excessDays + " " + periodToSet);
+ } else {
+ excessDays = periodToSet;
}
} else {
- time = lt;
+ time = timeToSet;
+ excessDays = periodToSet;
}
}
diff --git a/jdk/src/share/classes/java/time/format/ResolverStyle.java b/jdk/src/share/classes/java/time/format/ResolverStyle.java
index b53b827ab8d..313bd178d84 100644
--- a/jdk/src/share/classes/java/time/format/ResolverStyle.java
+++ b/jdk/src/share/classes/java/time/format/ResolverStyle.java
@@ -69,7 +69,7 @@ package java.time.format;
* Phase 2 resolves the parsed field-value pairs into date and/or time objects.
* This style is used to control how phase 2, resolving, happens.
*
- * Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
@@ -96,10 +96,9 @@ public enum ResolverStyle {
* behavior. Individual fields will interpret this differently.
*
* For example, resolving year-month and day-of-month in the ISO calendar
- * system using smart mode will ensure that the day-of-month is valid
- * for the year-month, rejecting invalid values, with the exception that
- * February 29th in a year other than a leap year will be converted to
- * February 28th.
+ * system using smart mode will ensure that the day-of-month is from
+ * 1 to 31, converting any value beyond the last valid day-of-month to be
+ * the last valid day-of-month.
*/
SMART,
/**
@@ -110,6 +109,7 @@ public enum ResolverStyle {
*
* For example, lenient mode allows the month in the ISO calendar system
* to be outside the range 1 to 12.
+ * For example, month 15 is treated as being 3 months after month 12.
*/
LENIENT;
diff --git a/jdk/src/share/classes/java/time/format/SignStyle.java b/jdk/src/share/classes/java/time/format/SignStyle.java
index 2f8c57aecb3..56dfd03511a 100644
--- a/jdk/src/share/classes/java/time/format/SignStyle.java
+++ b/jdk/src/share/classes/java/time/format/SignStyle.java
@@ -68,7 +68,7 @@ package java.time.format;
* to be controlled using this enum.
* See {@link DateTimeFormatterBuilder} for usage.
*
- *
Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/format/TextStyle.java b/jdk/src/share/classes/java/time/format/TextStyle.java
index dbc2c27f0d0..ed65d2773a3 100644
--- a/jdk/src/share/classes/java/time/format/TextStyle.java
+++ b/jdk/src/share/classes/java/time/format/TextStyle.java
@@ -80,7 +80,7 @@ import java.util.Calendar;
* For example, the word used for a month when used alone in a date picker is different
* to the word used for month in association with a day and year in a date.
*
- * Specification for implementors
+ * @implSpec
* This is immutable and thread-safe enum.
*/
public enum TextStyle {
diff --git a/jdk/src/share/classes/java/time/format/package-info.java b/jdk/src/share/classes/java/time/format/package-info.java
index 94a0600dc8e..140bb6d750d 100644
--- a/jdk/src/share/classes/java/time/format/package-info.java
+++ b/jdk/src/share/classes/java/time/format/package-info.java
@@ -76,7 +76,7 @@
* Localization occurs by calling
* {@link java.time.format.DateTimeFormatter#withLocale(java.util.Locale) withLocale(Locale)}
* on the formatter. Further customization is possible using
- * {@link java.time.format.DateTimeFormatSymbols DateTimeFormatSymbols}.
+ * {@link java.time.format.DecimalStyle DecimalStyle}.
*
*
* Package specification
diff --git a/jdk/src/share/classes/java/time/temporal/ChronoField.java b/jdk/src/share/classes/java/time/temporal/ChronoField.java
index 0fdeb2273d5..ac4522bb60b 100644
--- a/jdk/src/share/classes/java/time/temporal/ChronoField.java
+++ b/jdk/src/share/classes/java/time/temporal/ChronoField.java
@@ -93,7 +93,7 @@ import sun.util.locale.provider.LocaleResources;
* just with slightly different rules.
* The documentation of each field explains how it operates.
*
- * Specification for implementors
+ * @implSpec
* This is a final, immutable and thread-safe enum.
*
* @since 1.8
@@ -115,6 +115,10 @@ public enum ChronoField implements TemporalField {
* object stores, using integer division to remove excess precision.
* For example, if the {@code TemporalAccessor} stores time to millisecond precision,
* then the nano-of-second must be divided by 1,000,000 before replacing the milli-of-second.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The field is resolved in combination with {@code MILLI_OF_SECOND} and {@code MICRO_OF_SECOND}.
*/
NANO_OF_SECOND("NanoOfSecond", NANOS, SECONDS, ValueRange.of(0, 999_999_999)),
/**
@@ -126,6 +130,11 @@ public enum ChronoField implements TemporalField {
* This field is used to represent the nano-of-day handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_DAY} filling unknown precision with zero.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The value is split to form {@code NANO_OF_SECOND}, {@code SECOND_OF_MINUTE},
+ * {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
NANO_OF_DAY("NanoOfDay", NANOS, DAYS, ValueRange.of(0, 86400L * 1000_000_000L - 1)),
/**
@@ -141,6 +150,11 @@ public enum ChronoField implements TemporalField {
*
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_SECOND} with the value multiplied by 1,000.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The field is resolved in combination with {@code MILLI_OF_SECOND} to produce
+ * {@code NANO_OF_SECOND}.
*/
MICRO_OF_SECOND("MicroOfSecond", MICROS, SECONDS, ValueRange.of(0, 999_999)),
/**
@@ -155,6 +169,11 @@ public enum ChronoField implements TemporalField {
*
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_DAY} with the value multiplied by 1,000.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The value is split to form {@code MICRO_OF_SECOND}, {@code SECOND_OF_MINUTE},
+ * {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
MICRO_OF_DAY("MicroOfDay", MICROS, DAYS, ValueRange.of(0, 86400L * 1000_000L - 1)),
/**
@@ -170,6 +189,11 @@ public enum ChronoField implements TemporalField {
*
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_SECOND} with the value multiplied by 1,000,000.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The field is resolved in combination with {@code MICRO_OF_SECOND} to produce
+ * {@code NANO_OF_SECOND}.
*/
MILLI_OF_SECOND("MilliOfSecond", MILLIS, SECONDS, ValueRange.of(0, 999)),
/**
@@ -184,6 +208,11 @@ public enum ChronoField implements TemporalField {
*
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_DAY} with the value multiplied by 1,000,000.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The value is split to form {@code MILLI_OF_SECOND}, {@code SECOND_OF_MINUTE},
+ * {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
MILLI_OF_DAY("MilliOfDay", MILLIS, DAYS, ValueRange.of(0, 86400L * 1000L - 1)),
/**
@@ -191,6 +220,9 @@ public enum ChronoField implements TemporalField {
*
* This counts the second within the minute, from 0 to 59.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
*/
SECOND_OF_MINUTE("SecondOfMinute", SECONDS, MINUTES, ValueRange.of(0, 59), "second"),
/**
@@ -198,6 +230,11 @@ public enum ChronoField implements TemporalField {
*
* This counts the second within the day, from 0 to (24 * 60 * 60) - 1.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The value is split to form {@code SECOND_OF_MINUTE}, {@code MINUTE_OF_HOUR}
+ * and {@code HOUR_OF_DAY} fields.
*/
SECOND_OF_DAY("SecondOfDay", SECONDS, DAYS, ValueRange.of(0, 86400L - 1)),
/**
@@ -205,6 +242,9 @@ public enum ChronoField implements TemporalField {
*
* This counts the minute within the hour, from 0 to 59.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
*/
MINUTE_OF_HOUR("MinuteOfHour", MINUTES, HOURS, ValueRange.of(0, 59), "minute"),
/**
@@ -212,6 +252,10 @@ public enum ChronoField implements TemporalField {
*
* This counts the minute within the day, from 0 to (24 * 60) - 1.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The value is split to form {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
MINUTE_OF_DAY("MinuteOfDay", MINUTES, DAYS, ValueRange.of(0, (24 * 60) - 1)),
/**
@@ -220,6 +264,12 @@ public enum ChronoField implements TemporalField {
* This counts the hour within the AM/PM, from 0 to 11.
* This is the hour that would be observed on a standard 12-hour digital clock.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated from 0 to 11 in strict and smart mode.
+ * In lenient mode the value is not validated. It is combined with
+ * {@code AMPM_OF_DAY} to form {@code HOUR_OF_DAY} by multiplying
+ * the {AMPM_OF_DAY} value by 12.
*/
HOUR_OF_AMPM("HourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(0, 11)),
/**
@@ -228,6 +278,12 @@ public enum ChronoField implements TemporalField {
* This counts the hour within the AM/PM, from 1 to 12.
* This is the hour that would be observed on a standard 12-hour analog wall clock.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated from 1 to 12 in strict mode and from
+ * 0 to 12 in smart mode. In lenient mode the value is not validated.
+ * The field is converted to an {@code HOUR_OF_AMPM} with the same value,
+ * unless the value is 12, in which case it is converted to 0.
*/
CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)),
/**
@@ -236,6 +292,13 @@ public enum ChronoField implements TemporalField {
* This counts the hour within the day, from 0 to 23.
* This is the hour that would be observed on a standard 24-hour digital clock.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated in strict and smart mode but not in lenient mode.
+ * The field is combined with {@code MINUTE_OF_HOUR}, {@code SECOND_OF_MINUTE} and
+ * {@code NANO_OF_SECOND} to produce a {@code LocalTime}.
+ * In lenient mode, any excess days are added to the parsed date, or
+ * made available via {@link java.time.format.DateTimeFormatter#parsedExcessDays()}.
*/
HOUR_OF_DAY("HourOfDay", HOURS, DAYS, ValueRange.of(0, 23), "hour"),
/**
@@ -244,6 +307,12 @@ public enum ChronoField implements TemporalField {
* This counts the hour within the AM/PM, from 1 to 24.
* This is the hour that would be observed on a 24-hour analog wall clock.
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated from 1 to 24 in strict mode and from
+ * 0 to 24 in smart mode. In lenient mode the value is not validated.
+ * The field is converted to an {@code HOUR_OF_DAY} with the same value,
+ * unless the value is 24, in which case it is converted to 0.
*/
CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)),
/**
@@ -251,6 +320,12 @@ public enum ChronoField implements TemporalField {
*
* This counts the AM/PM within the day, from 0 (AM) to 1 (PM).
* This field has the same meaning for all calendar systems.
+ *
+ * When parsing this field it behaves equivalent to the following:
+ * The value is validated from 0 to 1 in strict and smart mode.
+ * In lenient mode the value is not validated. It is combined with
+ * {@code HOUR_OF_AMPM} to form {@code HOUR_OF_DAY} by multiplying
+ * the {AMPM_OF_DAY} value by 12.
*/
AMPM_OF_DAY("AmPmOfDay", HALF_DAYS, DAYS, ValueRange.of(0, 1), "dayperiod"),
/**
diff --git a/jdk/src/share/classes/java/time/temporal/ChronoUnit.java b/jdk/src/share/classes/java/time/temporal/ChronoUnit.java
index 03c5310312d..661960c28fb 100644
--- a/jdk/src/share/classes/java/time/temporal/ChronoUnit.java
+++ b/jdk/src/share/classes/java/time/temporal/ChronoUnit.java
@@ -72,7 +72,7 @@ import java.time.chrono.ChronoZonedDateTime;
* just with slightly different rules.
* The documentation of each unit explains how it operates.
*
- *
Specification for implementors
+ * @implSpec
* This is a final, immutable and thread-safe enum.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/temporal/IsoFields.java b/jdk/src/share/classes/java/time/temporal/IsoFields.java
index 851685a3132..e335c434d23 100644
--- a/jdk/src/share/classes/java/time/temporal/IsoFields.java
+++ b/jdk/src/share/classes/java/time/temporal/IsoFields.java
@@ -146,7 +146,7 @@ import sun.util.locale.provider.LocaleResources;
* 2009-01-05 Monday Week 2 of week-based-year 2009
*
*
- * Specification for implementors
+ * @implSpec
*
* This class is immutable and thread-safe.
*
diff --git a/jdk/src/share/classes/java/time/temporal/JulianFields.java b/jdk/src/share/classes/java/time/temporal/JulianFields.java
index 72956cec79a..95400addcaa 100644
--- a/jdk/src/share/classes/java/time/temporal/JulianFields.java
+++ b/jdk/src/share/classes/java/time/temporal/JulianFields.java
@@ -81,7 +81,7 @@ import java.util.Map;
* The fields are supported, and can be queried and set if {@code EPOCH_DAY} is available.
* The fields work with all chronologies.
*
- *
Specification for implementors
+ * @implSpec
* This is an immutable and thread-safe class.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/temporal/Temporal.java b/jdk/src/share/classes/java/time/temporal/Temporal.java
index 7cbc49fa176..1928186b285 100644
--- a/jdk/src/share/classes/java/time/temporal/Temporal.java
+++ b/jdk/src/share/classes/java/time/temporal/Temporal.java
@@ -119,7 +119,7 @@ import java.time.ZoneId;
* days to months.
*
*
- *
Specification for implementors
+ * @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
* All implementations must be {@link Comparable}.
@@ -146,7 +146,7 @@ public interface Temporal extends TemporalAccessor {
* date = date.with(next(WEDNESDAY)); // static import from Adjusters and DayOfWeek
*
*
- * Specification for implementors
+ * @implSpec
* Implementations must not alter either this object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
@@ -177,7 +177,7 @@ public interface Temporal extends TemporalAccessor {
* In cases like this, the field is responsible for resolving the result. Typically it will choose
* the previous valid date, which would be the last valid day of February in this example.
*
- * Specification for implementors
+ * @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then the adjustment must be performed.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
@@ -217,7 +217,7 @@ public interface Temporal extends TemporalAccessor {
* Note that calling {@code plus} followed by {@code minus} is not guaranteed to
* return the same date-time.
*
- * Specification for implementors
+ * @implSpec
* Implementations must not alter either this object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
@@ -247,12 +247,8 @@ public interface Temporal extends TemporalAccessor {
* a date representing the 31st January, then adding one month would be unclear.
* In cases like this, the field is responsible for resolving the result. Typically it will choose
* the previous valid date, which would be the last valid day of February in this example.
- *
- * If the implementation represents a date-time that has boundaries, such as {@code LocalTime},
- * then the permitted units must include the boundary unit, but no multiples of the boundary unit.
- * For example, {@code LocalTime} must accept {@code DAYS} but not {@code WEEKS} or {@code MONTHS}.
*
- *
Specification for implementors
+ * @implSpec
* Implementations must check and handle all units defined in {@link ChronoUnit}.
* If the unit is supported, then the addition must be performed.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
@@ -292,7 +288,7 @@ public interface Temporal extends TemporalAccessor {
* Note that calling {@code plus} followed by {@code minus} is not guaranteed to
* return the same date-time.
*
- * Specification for implementors
+ * @implSpec
* Implementations must not alter either this object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
@@ -322,12 +318,8 @@ public interface Temporal extends TemporalAccessor {
* a date representing the 31st March, then subtracting one month would be unclear.
* In cases like this, the field is responsible for resolving the result. Typically it will choose
* the previous valid date, which would be the last valid day of February in this example.
- *
- * If the implementation represents a date-time that has boundaries, such as {@code LocalTime},
- * then the permitted units must include the boundary unit, but no multiples of the boundary unit.
- * For example, {@code LocalTime} must accept {@code DAYS} but not {@code WEEKS} or {@code MONTHS}.
*
- *
Specification for implementors
+ * @implSpec
* Implementations must behave in a manor equivalent to the default method behavior.
*
* Implementations must not alter either this object or the specified temporal object.
@@ -353,10 +345,10 @@ public interface Temporal extends TemporalAccessor {
//-----------------------------------------------------------------------
/**
- * Calculates the period between this temporal and another temporal in
- * terms of the specified unit.
+ * Calculates the amount of time until another temporal in terms of the specified unit.
*
- * This calculates the period between two temporals in terms of a single unit.
+ * This calculates the amount of time between two temporal objects
+ * of the same type in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified temporal.
* The result will be negative if the end is before the start.
* For example, the period in hours between two temporal objects can be
@@ -385,7 +377,7 @@ public interface Temporal extends TemporalAccessor {
* long daysBetween = DAYS.between(start, end);
*
*
- *
Specification for implementors
+ * @implSpec
* Implementations must begin by checking to ensure that the input temporal
* object is of the same observable type as the implementation.
* They must then perform the calculation for all instances of {@link ChronoUnit}.
@@ -410,11 +402,11 @@ public interface Temporal extends TemporalAccessor {
* Neither this object, nor the specified temporal, may be altered.
*
* @param endTemporal the end temporal, of the same type as this object, not null
- * @param unit the unit to measure the period in, not null
- * @return the period between this temporal object and the specified one in terms of
- * the unit; positive if the specified object is later than this one, negative if
- * it is earlier than this one
- * @throws DateTimeException if the period cannot be calculated
+ * @param unit the unit to measure the amount in, not null
+ * @return the amount of time between this temporal object and the specified one
+ * in terms of the unit; positive if the specified object is later than this one,
+ * negative if it is earlier than this one
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
diff --git a/jdk/src/share/classes/java/time/temporal/TemporalAccessor.java b/jdk/src/share/classes/java/time/temporal/TemporalAccessor.java
index 3f4a571e477..a212be85981 100644
--- a/jdk/src/share/classes/java/time/temporal/TemporalAccessor.java
+++ b/jdk/src/share/classes/java/time/temporal/TemporalAccessor.java
@@ -94,7 +94,7 @@ import java.util.Objects;
* of this interface may be in calendar systems other than ISO.
* See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
*
- * Specification for implementors
+ * @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
@@ -109,7 +109,7 @@ public interface TemporalAccessor {
* If false, then calling the {@link #range(TemporalField) range} and {@link #get(TemporalField) get}
* methods will throw an exception.
*
- * Specification for implementors
+ * @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then true is returned, otherwise false
*
@@ -137,7 +137,7 @@ public interface TemporalAccessor {
* and it is important not to read too much into them. For example, there
* could be values within the range that are invalid for the field.
*
- *
Specification for implementors
+ * @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then the range of the field must be returned.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
@@ -183,7 +183,7 @@ public interface TemporalAccessor {
* If the date-time cannot return the value, because the field is unsupported or for
* some other reason, an exception will be thrown.
*
- * Specification for implementors
+ * @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported and has an {@code int} range, then the value of
* the field must be returned.
@@ -231,7 +231,7 @@ public interface TemporalAccessor {
* If the date-time cannot return the value, because the field is unsupported or for
* some other reason, an exception will be thrown.
*
- * Specification for implementors
+ * @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then the value of the field must be returned.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
@@ -265,7 +265,7 @@ public interface TemporalAccessor {
* {@code LocalDate::from} and {@code ZoneId::from}.
* Additional implementations are provided as static methods on {@link TemporalQuery}.
*
- * Specification for implementors
+ * @implSpec
* The default implementation must behave equivalent to this code:
*
* if (query == TemporalQuery.zoneId() ||
diff --git a/jdk/src/share/classes/java/time/temporal/TemporalAdjuster.java b/jdk/src/share/classes/java/time/temporal/TemporalAdjuster.java
index 0cd44a363d2..13f8cea80d6 100644
--- a/jdk/src/share/classes/java/time/temporal/TemporalAdjuster.java
+++ b/jdk/src/share/classes/java/time/temporal/TemporalAdjuster.java
@@ -97,7 +97,7 @@ import java.util.function.UnaryOperator;
* finding the next or previous day-of-week, such as "next Thursday"
*
*
- * Specification for implementors
+ * @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
@@ -127,7 +127,7 @@ public interface TemporalAdjuster {
* It is recommended to use the second approach, {@code with(TemporalAdjuster)},
* as it is a lot clearer to read in code.
*
- *
Specification for implementors
+ * @implSpec
* The implementation must take the input object and adjust it.
* The implementation defines the logic of the adjustment and is responsible for
* documenting that logic. It may use any method on {@code Temporal} to
@@ -162,10 +162,10 @@ public interface TemporalAdjuster {
* This is provided for convenience to make user-written adjusters simpler.
*
* In general, user-written adjusters should be static constants:
- *
+ * {@code
* static TemporalAdjuster TWO_DAYS_LATER = TemporalAdjuster.ofDateAdjuster(
* date -> date.plusDays(2));
- *
+ * }
*
* @param dateBasedAdjuster the date-based adjuster, not null
* @return the temporal adjuster wrapping on the date adjuster, not null
diff --git a/jdk/src/share/classes/java/time/temporal/TemporalAmount.java b/jdk/src/share/classes/java/time/temporal/TemporalAmount.java
index a264ebaa604..802dc4d73d5 100644
--- a/jdk/src/share/classes/java/time/temporal/TemporalAmount.java
+++ b/jdk/src/share/classes/java/time/temporal/TemporalAmount.java
@@ -90,7 +90,7 @@ import java.util.List;
* used in application code. Instead, applications should create and pass
* around instances of concrete types, such as {@code Period} and {@code Duration}.
*
- * Specification for implementors
+ * @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
@@ -104,7 +104,7 @@ public interface TemporalAmount {
* value of the {@code TemporalAmount}. A value must be returned
* for each unit listed in {@code getUnits}.
*
- * Specification for implementors
+ * @implSpec
* Implementations may declare support for units not listed by {@link #getUnits()}.
* Typically, the implementation would define additional units
* as conversions for the convenience of developers.
@@ -124,7 +124,7 @@ public interface TemporalAmount {
* The units are ordered from longest duration to the shortest duration
* of the unit.
*
- * Specification for implementors
+ * @implSpec
* The list of units completely and uniquely represents the
* state of the object without omissions, overlaps or duplication.
* The units are in order from longest duration to shortest.
@@ -150,7 +150,7 @@ public interface TemporalAmount {
* It is recommended to use the second approach, {@code plus(TemporalAmount)},
* as it is a lot clearer to read in code.
*
- * Specification for implementors
+ * @implSpec
* The implementation must take the input object and add to it.
* The implementation defines the logic of the addition and is responsible for
* documenting that logic. It may use any method on {@code Temporal} to
@@ -192,7 +192,7 @@ public interface TemporalAmount {
* It is recommended to use the second approach, {@code minus(TemporalAmount)},
* as it is a lot clearer to read in code.
*
- * Specification for implementors
+ * @implSpec
* The implementation must take the input object and subtract from it.
* The implementation defines the logic of the subtraction and is responsible for
* documenting that logic. It may use any method on {@code Temporal} to
diff --git a/jdk/src/share/classes/java/time/temporal/TemporalField.java b/jdk/src/share/classes/java/time/temporal/TemporalField.java
index 81992b4fb2f..cce2dfbd4de 100644
--- a/jdk/src/share/classes/java/time/temporal/TemporalField.java
+++ b/jdk/src/share/classes/java/time/temporal/TemporalField.java
@@ -82,7 +82,7 @@ import java.util.Objects;
* If it is, then the date-time must handle it.
* Otherwise, the method call is re-dispatched to the matching method in this interface.
*
- * Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Implementations should be {@code Serializable} where possible.
diff --git a/jdk/src/share/classes/java/time/temporal/TemporalQuery.java b/jdk/src/share/classes/java/time/temporal/TemporalQuery.java
index 599377847aa..188b13df61e 100644
--- a/jdk/src/share/classes/java/time/temporal/TemporalQuery.java
+++ b/jdk/src/share/classes/java/time/temporal/TemporalQuery.java
@@ -96,7 +96,7 @@ import java.time.chrono.Chronology;
* {@code LocalDate::from} and {@code ZoneId::from}.
* Additional common implementations are provided on this interface as static methods.
*
- * Specification for implementors
+ * @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
@@ -124,7 +124,7 @@ public interface TemporalQuery {
* It is recommended to use the second approach, {@code query(TemporalQuery)},
* as it is a lot clearer to read in code.
*
- * Specification for implementors
+ * @implSpec
* The implementation must take the input object and query it.
* The implementation defines the logic of the query and is responsible for
* documenting that logic.
diff --git a/jdk/src/share/classes/java/time/temporal/TemporalUnit.java b/jdk/src/share/classes/java/time/temporal/TemporalUnit.java
index 86e3ba86137..01ab406f85a 100644
--- a/jdk/src/share/classes/java/time/temporal/TemporalUnit.java
+++ b/jdk/src/share/classes/java/time/temporal/TemporalUnit.java
@@ -83,7 +83,7 @@ import java.time.Period;
* If it is, then the date-time must handle it.
* Otherwise, the method call is re-dispatched to the matching method in this interface.
*
- * Specification for implementors
+ * @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* It is recommended to use an enum where possible.
@@ -197,19 +197,17 @@ public interface TemporalUnit {
//-----------------------------------------------------------------------
/**
- * Calculates the period in terms of this unit between two temporal objects
- * of the same type.
+ * Calculates the amount of time between two temporal objects.
*
- * This calculates the period between two temporals in terms of this unit.
- * The start and end points are supplied as temporal objects and must be
- * of the same type.
+ * This calculates the amount in terms of this unit. The start and end
+ * points are supplied as temporal objects and must be of the same type.
* The result will be negative if the end is before the start.
- * For example, the period in hours between two temporal objects can be
+ * For example, the amount in hours between two temporal objects can be
* calculated using {@code HOURS.between(startTime, endTime)}.
*
* The calculation returns a whole number, representing the number of
* complete units between the two temporals.
- * For example, the period in hours between the times 11:30 and 13:29
+ * For example, the amount in hours between the times 11:30 and 13:29
* will only be one hour as it is one minute short of two hours.
*
* There are two equivalent ways of using this method.
@@ -237,9 +235,9 @@ public interface TemporalUnit {
*
* @param temporal1 the base temporal object, not null
* @param temporal2 the other temporal object, not null
- * @return the period between temporal1 and temporal2 in terms of this unit;
+ * @return the amount of time between temporal1 and temporal2 in terms of this unit;
* positive if temporal2 is later than temporal1, negative if earlier
- * @throws DateTimeException if the period cannot be calculated
+ * @throws DateTimeException if the amount cannot be calculated
* @throws UnsupportedTemporalTypeException if the unit is not supported by the temporal
* @throws ArithmeticException if numeric overflow occurs
*/
diff --git a/jdk/src/share/classes/java/time/temporal/UnsupportedTemporalTypeException.java b/jdk/src/share/classes/java/time/temporal/UnsupportedTemporalTypeException.java
index 4b47b0afcf1..e4b2b1281a3 100644
--- a/jdk/src/share/classes/java/time/temporal/UnsupportedTemporalTypeException.java
+++ b/jdk/src/share/classes/java/time/temporal/UnsupportedTemporalTypeException.java
@@ -67,7 +67,7 @@ import java.time.DateTimeException;
* UnsupportedTemporalTypeException indicates that a ChronoField or ChronoUnit is
* not supported for a Temporal class.
*
- *
Specification for implementors
+ * @implSpec
* This class is intended for use in a single thread.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/temporal/ValueRange.java b/jdk/src/share/classes/java/time/temporal/ValueRange.java
index d6e3a525c70..4ac8e74402a 100644
--- a/jdk/src/share/classes/java/time/temporal/ValueRange.java
+++ b/jdk/src/share/classes/java/time/temporal/ValueRange.java
@@ -79,7 +79,7 @@ import java.time.DateTimeException;
*
* Instances of this class are not tied to a specific field.
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/temporal/WeekFields.java b/jdk/src/share/classes/java/time/temporal/WeekFields.java
index 29a1e1bf8fb..07ffa91d2a3 100644
--- a/jdk/src/share/classes/java/time/temporal/WeekFields.java
+++ b/jdk/src/share/classes/java/time/temporal/WeekFields.java
@@ -170,7 +170,8 @@ import sun.util.locale.provider.LocaleResources;
* 2009-01-05 Monday
* Week 2 of 2009 Week 1 of 2009
*
- * Specification for implementors
+ *
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
@@ -200,8 +201,6 @@ public final class WeekFields implements Serializable {
* Note that the first week may start in the previous calendar year.
* Note also that the first few days of a calendar year may be in the
* week-based-year corresponding to the previous calendar year.
- *
- * This field is an immutable and thread-safe singleton.
*/
public static final WeekFields ISO = new WeekFields(DayOfWeek.MONDAY, 4);
@@ -211,8 +210,6 @@ public final class WeekFields implements Serializable {
*
* Defined as starting on Sunday and with a minimum of 1 day in the month.
* This week definition is in use in the US and other European countries.
- *
- * This field is an immutable and thread-safe singleton.
*/
public static final WeekFields SUNDAY_START = WeekFields.of(DayOfWeek.SUNDAY, 1);
@@ -230,7 +227,7 @@ public final class WeekFields implements Serializable {
* In that case, the week is set to the last week of the year
* with the same day-of-week.
*
- * This field is an immutable and thread-safe singleton.
+ * This unit is an immutable and thread-safe singleton.
*/
public static final TemporalUnit WEEK_BASED_YEARS = IsoFields.WEEK_BASED_YEARS;
@@ -247,22 +244,18 @@ public final class WeekFields implements Serializable {
* The minimal number of days in the first week.
*/
private final int minimalDays;
-
/**
* The field used to access the computed DayOfWeek.
*/
private transient final TemporalField dayOfWeek = ComputedDayOfField.ofDayOfWeekField(this);
-
/**
* The field used to access the computed WeekOfMonth.
*/
private transient final TemporalField weekOfMonth = ComputedDayOfField.ofWeekOfMonthField(this);
-
/**
* The field used to access the computed WeekOfYear.
*/
private transient final TemporalField weekOfYear = ComputedDayOfField.ofWeekOfYearField(this);
-
/**
* The field that represents the week-of-week-based-year.
*
@@ -271,7 +264,6 @@ public final class WeekFields implements Serializable {
* This unit is an immutable and thread-safe singleton.
*/
private transient final TemporalField weekOfWeekBasedYear = ComputedDayOfField.ofWeekOfWeekBasedYearField(this);
-
/**
* The field that represents the week-based-year.
*
@@ -281,6 +273,7 @@ public final class WeekFields implements Serializable {
*/
private transient final TemporalField weekBasedYear = ComputedDayOfField.ofWeekBasedYearField(this);
+ //-----------------------------------------------------------------------
/**
* Obtains an instance of {@code WeekFields} appropriate for a locale.
*
@@ -359,8 +352,7 @@ public final class WeekFields implements Serializable {
try {
return WeekFields.of(firstDayOfWeek, minimalDays);
} catch (IllegalArgumentException iae) {
- throw new InvalidObjectException("Invalid serialized WeekFields: "
- + iae.getMessage());
+ throw new InvalidObjectException("Invalid serialized WeekFields: " + iae.getMessage());
}
}
@@ -394,21 +386,24 @@ public final class WeekFields implements Serializable {
//-----------------------------------------------------------------------
/**
- * Returns a field to access the day of week,
- * computed based on this WeekFields.
+ * Returns a field to access the day of week based on this {@code WeekFields}.
*
- * The days of week are numbered from 1 to 7.
- * Day number 1 is the {@link #getFirstDayOfWeek() first day-of-week}.
+ * This is similar to {@link ChronoField#DAY_OF_WEEK} but uses values for
+ * the day-of-week based on this {@code WeekFields}.
+ * The days are numbered from 1 to 7 where the
+ * {@link #getFirstDayOfWeek() first day-of-week} is assigned the value 1.
+ *
+ * For example, if the first day-of-week is Sunday, then that will have the
+ * value 1, with other days ranging from Monday as 2 to Saturday as 7.
*
- * @return the field for day-of-week using this week definition, not null
+ * @return a field providing access to the day-of-week with localized numbering, not null
*/
public TemporalField dayOfWeek() {
return dayOfWeek;
}
/**
- * Returns a field to access the week of month,
- * computed based on this WeekFields.
+ * Returns a field to access the week of month based on this {@code WeekFields}.
*
* This represents the concept of the count of weeks within the month where weeks
* start on a fixed day-of-week, such as Monday.
@@ -426,15 +421,15 @@ public final class WeekFields implements Serializable {
* - if the 5th day of the month is a Monday, week two starts on the 5th and the 1st to 4th is in week one
*
* This field can be used with any calendar system.
- * @return a TemporalField to access the WeekOfMonth, not null
+ *
+ * @return a field providing access to the week-of-month, not null
*/
public TemporalField weekOfMonth() {
return weekOfMonth;
}
/**
- * Returns a field to access the week of year,
- * computed based on this WeekFields.
+ * Returns a field to access the week of year based on this {@code WeekFields}.
*
* This represents the concept of the count of weeks within the year where weeks
* start on a fixed day-of-week, such as Monday.
@@ -452,15 +447,15 @@ public final class WeekFields implements Serializable {
* - if the 5th day of the year is a Monday, week two starts on the 5th and the 1st to 4th is in week one
*
* This field can be used with any calendar system.
- * @return a TemporalField to access the WeekOfYear, not null
+ *
+ * @return a field providing access to the week-of-year, not null
*/
public TemporalField weekOfYear() {
return weekOfYear;
}
/**
- * Returns a field to access the week of a week-based-year,
- * computed based on this WeekFields.
+ * Returns a field to access the week of a week-based-year based on this {@code WeekFields}.
*
* This represents the concept of the count of weeks within the year where weeks
* start on a fixed day-of-week, such as Monday and each week belongs to exactly one year.
@@ -482,15 +477,15 @@ public final class WeekFields implements Serializable {
* the 1st to 4th is in week one
*
* This field can be used with any calendar system.
- * @return a TemporalField to access the week of week-based-year, not null
+ *
+ * @return a field providing access to the week-of-week-based-year, not null
*/
public TemporalField weekOfWeekBasedYear() {
return weekOfWeekBasedYear;
}
/**
- * Returns a field to access the year of a week-based-year,
- * computed based on this WeekFields.
+ * Returns a field to access the year of a week-based-year based on this {@code WeekFields}.
*
* This represents the concept of the year where weeks start on a fixed day-of-week,
* such as Monday and each week belongs to exactly one year.
@@ -504,14 +499,16 @@ public final class WeekFields implements Serializable {
* is in the last week of the previous year.
*
* This field can be used with any calendar system.
- * @return a TemporalField to access the year of week-based-year, not null
+ *
+ * @return a field providing access to the week-based-year, not null
*/
public TemporalField weekBasedYear() {
return weekBasedYear;
}
+ //-----------------------------------------------------------------------
/**
- * Checks if this WeekFields is equal to the specified object.
+ * Checks if this {@code WeekFields} is equal to the specified object.
*
* The comparison is based on the entire state of the rules, which is
* the first day-of-week and minimal days.
@@ -531,7 +528,7 @@ public final class WeekFields implements Serializable {
}
/**
- * A hash code for these rules.
+ * A hash code for this {@code WeekFields}.
*
* @return a suitable hash code
*/
@@ -542,7 +539,7 @@ public final class WeekFields implements Serializable {
//-----------------------------------------------------------------------
/**
- * A string representation of this definition.
+ * A string representation of this {@code WeekFields} instance.
*
* @return the string representation, not null
*/
@@ -957,7 +954,6 @@ public final class WeekFields implements Serializable {
/**
* Map the field range to a week range of a week year.
* @param temporal the temporal
- * @param field the field to get the range of
* @return the ValueRange with the range adjusted to weeks.
*/
private ValueRange rangeWeekOfWeekBasedYear(TemporalAccessor temporal) {
diff --git a/jdk/src/share/classes/java/time/zone/Ser.java b/jdk/src/share/classes/java/time/zone/Ser.java
index 7d5c0c6719b..e34126436af 100644
--- a/jdk/src/share/classes/java/time/zone/Ser.java
+++ b/jdk/src/share/classes/java/time/zone/Ser.java
@@ -74,7 +74,7 @@ import java.time.ZoneOffset;
/**
* The shared serialization delegate for this package.
*
- *
Implementation notes
+ * @implNote
* This class is mutable and should be created once per serialization.
*
* @serial include
diff --git a/jdk/src/share/classes/java/time/zone/ZoneOffsetTransition.java b/jdk/src/share/classes/java/time/zone/ZoneOffsetTransition.java
index 1b5810b0594..f2eab7c888e 100644
--- a/jdk/src/share/classes/java/time/zone/ZoneOffsetTransition.java
+++ b/jdk/src/share/classes/java/time/zone/ZoneOffsetTransition.java
@@ -89,7 +89,7 @@ import java.util.Objects;
* An example would be when the offset changes from {@code +04:00} to {@code +03:00}.
* This might be described as 'the clocks will move back one hour tonight at 2am'.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java b/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java
index bb1b79fb332..ad52f82de55 100644
--- a/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java
+++ b/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java
@@ -90,7 +90,7 @@ import java.util.Objects;
*
* These different rule types can be expressed and queried.
*
- *
Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/zone/ZoneRules.java b/jdk/src/share/classes/java/time/zone/ZoneRules.java
index fa7498c858f..070ad6e8398 100644
--- a/jdk/src/share/classes/java/time/zone/ZoneRules.java
+++ b/jdk/src/share/classes/java/time/zone/ZoneRules.java
@@ -100,7 +100,7 @@ import java.util.concurrent.ConcurrentMap;
* Applications should treat the data provided as representing the best information
* available to the implementation of this rule.
*
- * Specification for implementors
+ * @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/zone/ZoneRulesException.java b/jdk/src/share/classes/java/time/zone/ZoneRulesException.java
index e965af0dc34..2c845caf5fc 100644
--- a/jdk/src/share/classes/java/time/zone/ZoneRulesException.java
+++ b/jdk/src/share/classes/java/time/zone/ZoneRulesException.java
@@ -64,7 +64,7 @@ import java.time.DateTimeException;
* This exception is used to indicate a problems with the configured
* time-zone rules.
*
- * Specification for implementors
+ * @implSpec
* This class is intended for use in a single thread.
*
* @since 1.8
diff --git a/jdk/src/share/classes/java/time/zone/ZoneRulesProvider.java b/jdk/src/share/classes/java/time/zone/ZoneRulesProvider.java
index 5c88e3ea0cb..9523664d169 100644
--- a/jdk/src/share/classes/java/time/zone/ZoneRulesProvider.java
+++ b/jdk/src/share/classes/java/time/zone/ZoneRulesProvider.java
@@ -111,7 +111,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* Each provider will provide the latest rules for each zone ID, but they
* may also provide the history of how the rules changed.
*
- * Specification for implementors
+ * @implSpec
* This interface is a service provider that can be called by multiple threads.
* Implementations must be immutable and thread-safe.
*
diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java
index 62580594837..efb1459c9e8 100644
--- a/jdk/src/share/classes/java/util/Base64.java
+++ b/jdk/src/share/classes/java/util/Base64.java
@@ -625,7 +625,8 @@ public class Base64 {
* character(s) padded), they are decoded as if followed by padding
* character(s). If there is padding character present in the
* final unit, the correct number of padding character(s) must be
- * present, otherwise {@code IllegalArgumentException} is thrown
+ * present, otherwise {@code IllegalArgumentException} (
+ * {@code IOException} when reading from a Base64 stream) is thrown
* during decoding.
*
*
Instances of {@link Decoder} class are safe for use by
@@ -1306,7 +1307,12 @@ public class Base64 {
return off - oldOff;
}
if (v == '=') { // padding byte(s)
- if (nextin != 6 && nextin != 0) {
+ // = shiftto==18 unnecessary padding
+ // x= shiftto==12 invalid unit
+ // xx= shiftto==6 && missing last '='
+ // xx=y or last is not '='
+ if (nextin == 18 || nextin == 12 ||
+ nextin == 6 && is.read() != '=') {
throw new IOException("Illegal base64 ending sequence:" + nextin);
}
b[off++] = (byte)(bits >> (16));
diff --git a/jdk/src/share/classes/java/util/JapaneseImperialCalendar.java b/jdk/src/share/classes/java/util/JapaneseImperialCalendar.java
index ed95f96e05d..e37374af15f 100644
--- a/jdk/src/share/classes/java/util/JapaneseImperialCalendar.java
+++ b/jdk/src/share/classes/java/util/JapaneseImperialCalendar.java
@@ -249,11 +249,14 @@ class JapaneseImperialCalendar extends Calendar {
CalendarDate transitionDate = eras[i].getSinceDate();
date.setDate(transitionDate.getYear(), BaseCalendar.JANUARY, 1);
long fdd = gcal.getFixedDate(date);
- dayOfYear = Math.min((int)(fdd - fd), dayOfYear);
+ if (fd != fdd) {
+ dayOfYear = Math.min((int)(fd - fdd) + 1, dayOfYear);
+ }
date.setDate(transitionDate.getYear(), BaseCalendar.DECEMBER, 31);
- fdd = gcal.getFixedDate(date) + 1;
- dayOfYear = Math.min((int)(fd - fdd), dayOfYear);
-
+ fdd = gcal.getFixedDate(date);
+ if (fd != fdd) {
+ dayOfYear = Math.min((int)(fdd - fd) + 1, dayOfYear);
+ }
LocalGregorianCalendar.Date lgd = getCalendarDate(fd - 1);
int y = lgd.getYear();
// Unless the first year starts from January 1, the actual
diff --git a/jdk/src/share/classes/java/util/Objects.java b/jdk/src/share/classes/java/util/Objects.java
index 695f0c62eb3..e526079e37c 100644
--- a/jdk/src/share/classes/java/util/Objects.java
+++ b/jdk/src/share/classes/java/util/Objects.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, 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
@@ -25,6 +25,8 @@
package java.util;
+import java.util.function.Supplier;
+
/**
* This class consists of {@code static} utility methods for operating
* on objects. These utilities include {@code null}-safe or {@code
@@ -262,4 +264,30 @@ public final class Objects {
public static boolean nonNull(Object obj) {
return obj != null;
}
+
+ /**
+ * Checks that the specified object reference is not {@code null} and
+ * throws a customized {@link NullPointerException} if it is.
+ *
+ *
Unlike the method {@link #requireNonNull(Object, String)},
+ * this method allows creation of the message to be deferred until
+ * after the null check is made. While this may confer a
+ * performance advantage in the non-null case, when deciding to
+ * call this method care should be taken that the costs of
+ * creating the message supplier are less than the cost of just
+ * creating the string message directly.
+ *
+ * @param obj the object reference to check for nullity
+ * @param messageSupplier supplier of the detail message to be
+ * used in the event that a {@code NullPointerException} is thrown
+ * @param the type of the reference
+ * @return {@code obj} if not {@code null}
+ * @throws NullPointerException if {@code obj} is {@code null}
+ * @since 1.8
+ */
+ public static T requireNonNull(T obj, Supplier messageSupplier) {
+ if (obj == null)
+ throw new NullPointerException(messageSupplier.get());
+ return obj;
+ }
}
diff --git a/jdk/src/share/classes/sun/net/www/MessageHeader.java b/jdk/src/share/classes/sun/net/www/MessageHeader.java
index 3a46def13b3..d6982b659e2 100644
--- a/jdk/src/share/classes/sun/net/www/MessageHeader.java
+++ b/jdk/src/share/classes/sun/net/www/MessageHeader.java
@@ -31,12 +31,7 @@ package sun.net.www;
import java.io.*;
import java.util.Collections;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.util.*;
/** An RFC 844 or MIME message header. Includes methods
for parsing headers from incoming streams, fetching
@@ -59,6 +54,17 @@ class MessageHeader {
parseHeader(is);
}
+ /**
+ * Returns list of header names in a comma separated list
+ */
+ public synchronized String getHeaderNamesInList() {
+ StringJoiner joiner = new StringJoiner(",");
+ for (int i=0; i() {
+ public Void run() throws IOException {
+ plainConnect0();
+ return null;
+ }
+ }
+// }, null, p -- replace line above, when limited doPriv ready
+ );
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ } else {
+ // run without additional permission
+ plainConnect0();
+ }
+ }
+
+ /**
+ * if the caller has a HttpURLPermission for connecting to the
+ * given URL, then return a SocketPermission which permits
+ * access to that destination. Return null otherwise. The permission
+ * is cached in a field (which can only be changed by redirects)
+ */
+ SocketPermission URLtoSocketPermission(URL url) throws IOException {
+
+ if (socketPermission != null) {
+ return socketPermission;
+ }
+
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm == null) {
+ return null;
+ }
+
+ // the permission, which we might grant
+
+ SocketPermission newPerm = new SocketPermission(
+ getHostAndPort(url), "connect"
+ );
+
+ String actions = getRequestMethod()+":" +
+ getUserSetHeaders().getHeaderNamesInList();
+
+ HttpURLPermission p = new HttpURLPermission(url.toString(), actions);
+ try {
+ sm.checkPermission(p);
+ socketPermission = newPerm;
+ return socketPermission;
+ } catch (SecurityException e) {
+ // fall thru
+ }
+ return null;
+ }
+
+ protected void plainConnect0() throws IOException {
// try to see if request can be served from local cache
if (cacheHandler != null && getUseCaches()) {
try {
@@ -1068,7 +1178,28 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
@Override
public synchronized OutputStream getOutputStream() throws IOException {
+ connecting = true;
+ SocketPermission p = URLtoSocketPermission(this.url);
+ if (p != null) {
+ try {
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ public OutputStream run() throws IOException {
+ return getOutputStream0();
+ }
+ }
+// }, null, p -- replace line above, when limited doPriv ready
+ );
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ } else {
+ return getOutputStream0();
+ }
+ }
+
+ private synchronized OutputStream getOutputStream0() throws IOException {
try {
if (!doOutput) {
throw new ProtocolException("cannot write to a URLConnection"
@@ -1231,8 +1362,30 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
@Override
- @SuppressWarnings("empty-statement")
public synchronized InputStream getInputStream() throws IOException {
+ connecting = true;
+ SocketPermission p = URLtoSocketPermission(this.url);
+
+ if (p != null) {
+ try {
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ public InputStream run() throws IOException {
+ return getInputStream0();
+ }
+ }
+// }, null, p -- replace line above, when limited doPriv ready
+ );
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ } else {
+ return getInputStream0();
+ }
+ }
+
+ @SuppressWarnings("empty-statement")
+ private synchronized InputStream getInputStream0() throws IOException {
if (!doInput) {
throw new ProtocolException("Cannot read from URLConnection"
@@ -2319,18 +2472,19 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return false;
}
- int stat = getResponseCode();
+ final int stat = getResponseCode();
if (stat < 300 || stat > 307 || stat == 306
|| stat == HTTP_NOT_MODIFIED) {
return false;
}
- String loc = getHeaderField("Location");
+ final String loc = getHeaderField("Location");
if (loc == null) {
/* this should be present - if not, we have no choice
* but to go forward w/ the response we got
*/
return false;
}
+
URL locUrl;
try {
locUrl = new URL(loc);
@@ -2342,6 +2496,38 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
// treat loc as a relative URI to conform to popular browsers
locUrl = new URL(url, loc);
}
+
+ final URL locUrl0 = locUrl;
+ socketPermission = null; // force recalculation
+ SocketPermission p = URLtoSocketPermission(locUrl);
+
+ if (p != null) {
+ try {
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ public Boolean run() throws IOException {
+ return followRedirect0(loc, stat, locUrl0);
+ }
+ }
+// }, null, p -- replace line above, when limited doPriv ready
+ );
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ } else {
+ // run without additional permission
+ return followRedirect0(loc, stat, locUrl);
+ }
+ }
+
+ /* Tells us whether to follow a redirect. If so, it
+ * closes the connection (break any keep-alive) and
+ * resets the url, re-connects, and resets the request
+ * property.
+ */
+ private boolean followRedirect0(String loc, int stat, URL locUrl)
+ throws IOException
+ {
disconnectInternal();
if (streaming()) {
throw new HttpRetryException (RETRY_MSG3, stat, loc);
@@ -2753,17 +2939,24 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
* @param value the value to be set
*/
@Override
- public void setRequestProperty(String key, String value) {
- if (connected)
+ public synchronized void setRequestProperty(String key, String value) {
+ if (connected || connecting)
throw new IllegalStateException("Already connected");
if (key == null)
throw new NullPointerException ("key is null");
if (isExternalMessageHeaderAllowed(key, value)) {
requests.set(key, value);
+ if (!key.equalsIgnoreCase("Content-Type")) {
+ userHeaders.set(key, value);
+ }
}
}
+ MessageHeader getUserSetHeaders() {
+ return userHeaders;
+ }
+
/**
* Adds a general request property specified by a
* key-value pair. This method will not overwrite
@@ -2776,14 +2969,17 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
* @since 1.4
*/
@Override
- public void addRequestProperty(String key, String value) {
- if (connected)
+ public synchronized void addRequestProperty(String key, String value) {
+ if (connected || connecting)
throw new IllegalStateException("Already connected");
if (key == null)
throw new NullPointerException ("key is null");
if (isExternalMessageHeaderAllowed(key, value)) {
requests.add(key, value);
+ if (!key.equalsIgnoreCase("Content-Type")) {
+ userHeaders.add(key, value);
+ }
}
}
diff --git a/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java b/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java
index 12631577807..0389a12b825 100644
--- a/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_JP_2.java
@@ -47,17 +47,17 @@ public class ISO2022_JP_2 extends ISO2022_JP
}
public CharsetDecoder newDecoder() {
- return new Decoder(this, Decoder.DEC0208, DEC0212);
+ return new Decoder(this, Decoder.DEC0208, CoderHolder.DEC0212);
}
public CharsetEncoder newEncoder() {
- return new Encoder(this, Encoder.ENC0208, ENC0212, true);
+ return new Encoder(this, Encoder.ENC0208, CoderHolder.ENC0212, true);
}
- private final static DoubleByte.Decoder DEC0212 =
- (DoubleByte.Decoder)new JIS_X_0212().newDecoder();
-
- private final static DoubleByte.Encoder ENC0212 =
- (DoubleByte.Encoder)new JIS_X_0212().newEncoder();
-
+ private static class CoderHolder {
+ final static DoubleByte.Decoder DEC0212 =
+ (DoubleByte.Decoder)new JIS_X_0212().newDecoder();
+ final static DoubleByte.Encoder ENC0212 =
+ (DoubleByte.Encoder)new JIS_X_0212().newEncoder();
+ }
}
diff --git a/jdk/src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider b/jdk/src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider
deleted file mode 100644
index cf0949e4ca8..00000000000
--- a/jdk/src/share/classes/sun/nio/cs/ext/META-INF/services/java.nio.charset.spi.CharsetProvider
+++ /dev/null
@@ -1,2 +0,0 @@
-# NIO charset SPI extended charset provider
-sun.nio.cs.ext.ExtendedCharsets
diff --git a/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java b/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java
index 2be71a210c7..761809aa304 100644
--- a/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java
+++ b/jdk/src/share/classes/sun/nio/cs/ext/MSISO2022JP.java
@@ -46,16 +46,17 @@ public class MSISO2022JP extends ISO2022_JP
}
public CharsetDecoder newDecoder() {
- return new Decoder(this, DEC0208, null);
+ return new Decoder(this, CoderHolder.DEC0208, null);
}
public CharsetEncoder newEncoder() {
- return new Encoder(this, ENC0208, null, true);
+ return new Encoder(this, CoderHolder.ENC0208, null, true);
}
- private final static DoubleByte.Decoder DEC0208 =
- (DoubleByte.Decoder)new JIS_X_0208_MS932().newDecoder();
-
- private final static DoubleByte.Encoder ENC0208 =
- (DoubleByte.Encoder)new JIS_X_0208_MS932().newEncoder();
+ private static class CoderHolder {
+ final static DoubleByte.Decoder DEC0208 =
+ (DoubleByte.Decoder)new JIS_X_0208_MS932().newDecoder();
+ final static DoubleByte.Encoder ENC0208 =
+ (DoubleByte.Encoder)new JIS_X_0208_MS932().newEncoder();
+ }
}
diff --git a/jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java b/jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java
index aa0a73b76a7..9a9b6637471 100644
--- a/jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java
+++ b/jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java
@@ -246,16 +246,16 @@ public class LocalGregorianCalendar extends BaseCalendar {
return false;
}
ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1);
- // If it's not the last Era, validate the date.
- if (era != eras[eras.length - 1]) {
- Date tmp = newCalendarDate(date.getZone());
- tmp.setEra(era).setDate(date.getYear(), date.getMonth(), date.getDayOfMonth());
- normalize(tmp);
- if (tmp.getEra() != era) {
- return false;
- }
+ Date tmp = newCalendarDate(date.getZone());
+ tmp.setEra(era).setDate(date.getYear(), date.getMonth(), date.getDayOfMonth());
+ normalize(tmp);
+ if (tmp.getEra() != era) {
+ return false;
}
} else {
+ if (date.getYear() >= eras[0].getSinceDate().getYear()) {
+ return false;
+ }
ldate.setNormalizedYear(ldate.getYear());
}
return super.validate(ldate);
diff --git a/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java
index b003c2eead0..60cd91911a2 100644
--- a/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java
+++ b/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java
@@ -585,12 +585,17 @@ public final class ZoneInfoFile {
dstSavings = (startRule.offsetAfter - startRule.offsetBefore) * 1000;
// Note: known mismatching -> Asia/Amman
+ // Asia/Gaza
+ // Asia/Hebron
// ZoneInfo : startDayOfWeek=5 <= Thursday
// startTime=86400000 <= 24 hours
// This: startDayOfWeek=6
// startTime=0
// Below is the workaround, it probably slows down everyone a little
- if (params[2] == 6 && params[3] == 0 && zoneId.equals("Asia/Amman")) {
+ if (params[2] == 6 && params[3] == 0 &&
+ (zoneId.equals("Asia/Amman") ||
+ zoneId.equals("Asia/Gaza") ||
+ zoneId.equals("Asia/Hebron"))) {
params[2] = 5;
params[3] = 86400000;
}
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
index 59af1d215bf..974fd26d051 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
@@ -365,7 +365,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -646,6 +646,10 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST",
+ "Khandyga Time", "YAKT"}},
+
{"Asia/Kolkata", IST},
{"Asia/Krasnoyarsk", new String[] {"Krasnoyarsk Time", "KRAT",
"Krasnoyarsk Summer Time", "KRAST",
@@ -703,6 +707,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST",
+ "Ust-Nera Time", "VLAT"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Vladivostok Time", "VLAT",
"Vladivostok Summer Time", "VLAST",
@@ -888,7 +895,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Middle Europe Time", "MET",
"Middle Europe Summer Time", "MEST",
"Middle Europe Time", "MET"}},
diff --git a/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
index ab1e3673500..8dc71d7758f 100644
--- a/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
+++ b/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"Asia/Kolkata", IST},
{"Asia/Krasnoyarsk", new String[] {"Krasnojarsker Zeit", "KRAT",
"Krasnojarsker Sommerzeit", "KRAST"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Wladiwostok Zeit", "VLAT",
"Wladiwostok Sommerzeit", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Zentraleurop\u00e4ische Zeit", "MET",
"Zentraleurop\u00e4ische Sommerzeit", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
index 7e4a41a4237..66e3e02acb2 100644
--- a/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
+++ b/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"Asia/Kolkata", IST},
{"Asia/Krasnoyarsk", new String[] {"Hora de Krasnoyarsk", "KRAT",
"Hora de verano de Krasnoyarsk", "KRAST"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Hora de Vladivostok", "VLAT",
"Hora de verano de Vladivostok", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Hora de Europa Central", "MET",
"Hora de verano de Europa Central", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
index fc579bda857..2d960819cd7 100644
--- a/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
+++ b/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"Asia/Kolkata", IST},
{"Asia/Krasnoyarsk", new String[] {"Heure de Krasno\u00efarsk", "KRAT",
"Heure d'\u00e9t\u00e9 de Krasno\u00efarsk", "KRAST"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Heure de Vladivostok", "VLAT",
"Heure d'\u00e9t\u00e9 de Vladivostok", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Heure de l'Europe centrale", "MET",
"Heure d'\u00e9t\u00e9 de l'Europe centrale", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
index 12cf3cfd7e9..18b434413b4 100644
--- a/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
+++ b/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -536,6 +536,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
{"Asia/Kolkata", IST},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"Asia/Krasnoyarsk", new String[] {"Ora di Krasnojarsk", "KRAT",
"Ora estiva di Krasnojarsk", "KRAST"}},
{"Asia/Kuala_Lumpur", MYT},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Ora di Vladivostok", "VLAT",
"Ora estiva di Vladivostok", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Ora dell'Europa centrale", "MET",
"Ora estiva dell'Europa centrale", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
index 0c1e64af729..5001fd28f04 100644
--- a/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
+++ b/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"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"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"\u30a6\u30e9\u30b8\u30aa\u30b9\u30c8\u30af\u6642\u9593", "VLAT",
"\u30a6\u30e9\u30b8\u30aa\u30b9\u30c8\u30af\u590f\u6642\u9593", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"\u4e2d\u90e8\u30e8\u30fc\u30ed\u30c3\u30d1\u6642\u9593", "MET",
"\u4e2d\u90e8\u30e8\u30fc\u30ed\u30c3\u30d1\u590f\u6642\u9593", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
index f449bf3ab87..416a2c51214 100644
--- a/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
+++ b/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"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"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST" }},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"\ube14\ub77c\ub514\ubcf4\uc2a4\ud1a1 \uc2dc\uac04", "VLAT",
"\ube14\ub77c\ub514\ubcf4\uc2a4\ud1a1 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"\uc911\ubd80 \uc720\ub7fd \uc2dc\uac04", "MET",
"\uc911\ubd80 \uc720\ub7fd \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java b/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
index 32d57832fea..124b8eb0c2d 100644
--- a/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
+++ b/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"Asia/Kolkata", IST},
{"Asia/Krasnoyarsk", new String[] {"Fuso hor\u00e1rio de Krasnoyarsk", "KRAT",
"Fuso hor\u00e1rio de ver\u00e3o de Krasnoyarsk", "KRAST"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Fuso hor\u00e1rio de Vladivostok", "VLAT",
"Fuso hor\u00e1rio de ver\u00e3o de Vladivostok", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Fuso hor\u00e1rio da Europa M\u00e9dia", "MET",
"Fuso hor\u00e1rio de ver\u00e3o da Europa M\u00e9dia", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
index 65b1979888d..0e54cea9116 100644
--- a/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
+++ b/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"Asia/Kolkata", IST},
{"Asia/Krasnoyarsk", new String[] {"Krasnojarsk, normaltid", "KRAT",
"Krasnojarsk, sommartid", "KRAST"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"Vladivostok, normaltid", "VLAT",
"Vladivostok, sommartid", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"Mellaneuropeisk tid", "MET",
"Mellaneuropeisk sommartid", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
index bd2333bdd30..74777e3619d 100644
--- a/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
+++ b/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"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"}},
@@ -583,6 +585,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"\u6d77\u53c2\u5d34\u65f6\u95f4", "VLAT",
"\u6d77\u53c2\u5d34\u590f\u4ee4\u65f6", "VLAST"}},
@@ -750,7 +754,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"\u4e2d\u6b27\u65f6\u95f4", "MET",
"\u4e2d\u6b27\u590f\u4ee4\u65f6", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
index 62b1a60e296..66de2c388af 100644
--- a/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
+++ b/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
@@ -289,7 +289,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"Africa/Porto-Novo", WAT},
{"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
- {"Africa/Tripoli", EET},
+ {"Africa/Tripoli", CET},
{"Africa/Tunis", CET},
{"Africa/Windhoek", WAT},
{"America/Adak", HAST},
@@ -535,6 +535,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"Asia/Kashgar", CTT},
{"Asia/Kathmandu", NPT},
{"Asia/Katmandu", NPT},
+ {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT",
+ "Khandyga Summer Time", "YAKST"}},
{"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"}},
@@ -584,6 +586,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"Asia/Ulaanbaatar", ULAT},
{"Asia/Ulan_Bator", ULAT},
{"Asia/Urumqi", CTT},
+ {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT",
+ "Ust-Nera Summer Time", "VLAST"}},
{"Asia/Vientiane", ICT},
{"Asia/Vladivostok", new String[] {"\u6d77\u53c3\u5d34\u6642\u9593", "VLAT",
"\u6d77\u53c3\u5d34\u590f\u4ee4\u6642\u9593", "VLAST"}},
@@ -751,7 +755,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"Jamaica", EST},
{"Japan", JST},
{"Kwajalein", MHT},
- {"Libya", EET},
+ {"Libya", CET},
{"MET", new String[] {"\u4e2d\u6b50\u6642\u9593", "MET",
"\u4e2d\u6b50\u590f\u4ee4\u6642\u9593", "MEST"}},
{"Mexico/BajaNorte", PST},
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/com/sun/sample/scriptpad/Main.java b/jdk/src/share/sample/scripting/scriptpad/src/com/sun/sample/scriptpad/Main.java
index e720687667e..aaeb58d0916 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/com/sun/sample/scriptpad/Main.java
+++ b/jdk/src/share/sample/scripting/scriptpad/src/com/sun/sample/scriptpad/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -75,7 +75,7 @@ public class Main {
*/
InputStream is = Main.class.getResourceAsStream("/resources/" + name);
// current script file name for better error messages
- engine.put(ScriptEngine.NAME, name);
+ engine.put(ScriptEngine.FILENAME, name);
// evaluate the script in the InputStream
engine.eval(new InputStreamReader(is));
}
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/resources/Main.js b/jdk/src/share/sample/scripting/scriptpad/src/resources/Main.js
index 9d1e5fe1d95..a1c332db310 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/resources/Main.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/resources/Main.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +37,6 @@
* this sample code.
*/
-
/*
* This script can be loaded in jrunscript to start scriptpad.
*
@@ -48,4 +47,3 @@ load("conc.js");
load("gui.js");
load("scriptpad.js");
load("mm.js");
-
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/resources/conc.js b/jdk/src/share/sample/scripting/scriptpad/src/resources/conc.js
index 1618b1d76d3..7e56fad4703 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/resources/conc.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/resources/conc.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,15 +37,43 @@
* this sample code.
*/
-
/*
* Concurrency utilities for JavaScript. These are based on
- * java.lang and java.util.concurrent API. The following functions
+ * java.lang and java.util.concurrent API. The following functions
* provide a simpler API for scripts. Instead of directly using java.lang
* and java.util.concurrent classes, scripts can use functions and
- * objects exported from here.
+ * objects exported from here.
*/
+// shortcut for j.u.c lock classes
+var Lock = java.util.concurrent.locks.ReentrantLock;
+var RWLock = java.util.concurrent.locks.ReentrantReadWriteLock;
+
+// check if there is a build in sync function, define one if missing
+if (typeof sync === "undefined") {
+ var sync = function(func, obj) {
+ if (arguments.length < 1 || arguments.length > 2 ) {
+ throw "sync(function [,object]) parameter count mismatch";
+ }
+
+ var syncobj = (arguments.length == 2 ? obj : this);
+
+ if (!syncobj._syncLock) {
+ syncobj._syncLock = new Lock();
+ }
+
+ return function() {
+ syncobj._syncLock.lock();
+ try {
+ func.apply(null, arguments);
+ } finally {
+ syncobj._syncLock.unlock();
+ }
+ };
+ };
+ sync.docString = "synchronize a function, optionally on an object";
+}
+
/**
* Wrapper for java.lang.Object.wait
*
@@ -58,7 +86,6 @@ function wait(object) {
}
wait.docString = "convenient wrapper for java.lang.Object.wait method";
-
/**
* Wrapper for java.lang.Object.notify
*
@@ -71,7 +98,6 @@ function notify(object) {
}
notify.docString = "convenient wrapper for java.lang.Object.notify method";
-
/**
* Wrapper for java.lang.Object.notifyAll
*
@@ -84,7 +110,6 @@ function notifyAll(object) {
}
notifyAll.docString = "convenient wrapper for java.lang.Object.notifyAll method";
-
/**
* Creates a java.lang.Runnable from a given script
* function.
@@ -97,7 +122,7 @@ Function.prototype.runnable = function() {
func.apply(null, args);
}
}
-}
+};
/**
* Executes the function on a new Java Thread.
@@ -106,7 +131,7 @@ Function.prototype.thread = function() {
var t = new java.lang.Thread(this.runnable.apply(this, arguments));
t.start();
return t;
-}
+};
/**
* Executes the function on a new Java daemon Thread.
@@ -116,7 +141,7 @@ Function.prototype.daemon = function() {
t.setDaemon(true);
t.start();
return t;
-}
+};
/**
* Creates a java.util.concurrent.Callable from a given script
@@ -128,7 +153,7 @@ Function.prototype.callable = function() {
return new java.util.concurrent.Callable() {
call: function() { return func.apply(null, args); }
}
-}
+};
/**
* Registers the script function so that it will be called exit.
@@ -137,10 +162,10 @@ Function.prototype.atexit = function () {
var args = arguments;
java.lang.Runtime.getRuntime().addShutdownHook(
new java.lang.Thread(this.runnable.apply(this, args)));
-}
+};
/**
- * Executes the function asynchronously.
+ * Executes the function asynchronously.
*
* @return a java.util.concurrent.FutureTask
*/
@@ -152,13 +177,9 @@ Function.prototype.future = (function() {
(function() { theExecutor.shutdown(); }).atexit();
return function() {
return theExecutor.submit(this.callable.apply(this, arguments));
- }
+ };
})();
-// shortcut for j.u.c lock classes
-var Lock = java.util.concurrent.locks.ReentrantLock;
-var RWLock = java.util.concurrent.locks.ReentrantReadWriteLock;
-
/**
* Executes a function after acquiring given lock. On return,
* (normal or exceptional), lock is released.
@@ -179,7 +200,7 @@ Function.prototype.sync = function (lock) {
} finally {
lock.unlock();
}
-}
+};
/**
* Causes current thread to sleep for specified
@@ -193,30 +214,29 @@ function sleep(interval) {
sleep.docString = "wrapper for java.lang.Thread.sleep method";
/**
- * Schedules a task to be executed once in
- * every N milliseconds specified.
+ * Schedules a task to be executed once in N milliseconds specified.
*
* @param callback function or expression to evaluate
* @param interval in milliseconds to sleep
* @return timeout ID (which is nothing but Thread instance)
*/
function setTimeout(callback, interval) {
- if (! (callback instanceof Function)) {
+ if (! (callback instanceof Function) && typeof callback !== "function") {
callback = new Function(callback);
}
// start a new thread that sleeps given time
// and calls callback in an infinite loop
return (function() {
- while (true) {
+ try {
sleep(interval);
- callback();
- }
+ } catch (x) { }
+ callback();
}).daemon();
}
-setTimeout.docString = "calls given callback once after specified interval"
+setTimeout.docString = "calls given callback once after specified interval";
-/**
+/**
* Cancels a timeout set earlier.
* @param tid timeout ID returned from setTimeout
*/
@@ -224,23 +244,62 @@ function clearTimeout(tid) {
// we just interrupt the timer thread
tid.interrupt();
}
+clearTimeout.docString = "interrupt a setTimeout timer";
/**
- * Simple access to thread local storage.
+ * Schedules a task to be executed once in
+ * every N milliseconds specified.
+ *
+ * @param callback function or expression to evaluate
+ * @param interval in milliseconds to sleep
+ * @return timeout ID (which is nothing but Thread instance)
+ */
+function setInterval(callback, interval) {
+ if (! (callback instanceof Function) && typeof callback !== "function") {
+ callback = new Function(callback);
+ }
+
+ // start a new thread that sleeps given time
+ // and calls callback in an infinite loop
+ return (function() {
+ while (true) {
+ try {
+ sleep(interval);
+ } catch (x) {
+ break;
+ }
+ callback();
+ }
+ }).daemon();
+}
+setInterval.docString = "calls given callback every specified interval";
+
+/**
+ * Cancels a timeout set earlier.
+ * @param tid timeout ID returned from setTimeout
+ */
+function clearInterval(tid) {
+ // we just interrupt the timer thread
+ tid.interrupt();
+}
+clearInterval.docString = "interrupt a setInterval timer";
+
+/**
+ * Simple access to thread local storage.
*
* Script sample:
*
* __thread.x = 44;
- * function f() {
- * __thread.x = 'hello';
- * print(__thread.x);
+ * function f() {
+ * __thread.x = 'hello';
+ * print(__thread.x);
* }
* f.thread(); // prints 'hello'
* print(__thread.x); // prints 44 in main thread
*/
var __thread = (function () {
var map = new Object();
- return new JSAdapter() {
+ return new JSAdapter({
__has__: function(name) {
return map[name] != undefined;
},
@@ -263,8 +322,8 @@ var __thread = (function () {
__delete__: function(name) {
if (map[name] != undefined) {
map[name].set(null);
- }
+ }
}
- }
+ });
})();
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/resources/gui.js b/jdk/src/share/sample/scripting/scriptpad/src/resources/gui.js
index 950f64c0787..7882d2aa5c7 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/resources/gui.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/resources/gui.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,16 +37,15 @@
* this sample code.
*/
-
/*
- * Few user interface utilities.
+ * Few user interface utilities.
*/
if (this.window === undefined) {
this.window = null;
}
-/**
+/**
* Swing invokeLater - invokes given function in AWT event thread
*/
Function.prototype.invokeLater = function() {
@@ -54,13 +53,13 @@ Function.prototype.invokeLater = function() {
var func = this;
var args = arguments;
SwingUtilities.invokeLater(new java.lang.Runnable() {
- run: function() {
+ run: function() {
func.apply(func, args);
}
});
-}
+};
-/**
+/**
* Swing invokeAndWait - invokes given function in AWT event thread
* and waits for it's completion
*/
@@ -69,11 +68,11 @@ Function.prototype.invokeAndWait = function() {
var func = this;
var args = arguments;
SwingUtilities.invokeAndWait(new java.lang.Runnable() {
- run: function() {
+ run: function() {
func.apply(func, args);
}
});
-}
+};
/**
* Am I running in AWT event dispatcher thread?
@@ -85,22 +84,24 @@ function isEventThread() {
isEventThread.docString = "returns whether the current thread is GUI thread";
/**
- * Opens a file dialog box
+ * Opens a file dialog box
*
* @param curDir current directory [optional]
* @param save flag tells whether this is a save dialog or not
* @return selected file or else null
*/
-function fileDialog(curDir, save) {
+function fileDialog(curDir, save) {
var result;
function _fileDialog() {
if (curDir == undefined) {
curDir = new java.io.File(".");
}
+
var JFileChooser = javax.swing.JFileChooser;
- var dialog = new JFileChooser(curDir);
- var res = save? dialog.showSaveDialog(window):
- dialog.showOpenDialog(window);
+ var dialog = new JFileChooser(curDir);
+ var res = save ? dialog.showSaveDialog(window):
+ dialog.showOpenDialog(window);
+
if (res == JFileChooser.APPROVE_OPTION) {
result = dialog.getSelectedFile();
} else {
@@ -113,37 +114,41 @@ function fileDialog(curDir, save) {
} else {
_fileDialog.invokeAndWait();
}
+
return result;
}
fileDialog.docString = "show a file dialog box";
/**
- * Opens a color chooser dialog box
+ * Opens a color chooser dialog box
*
* @param title of the dialog box [optional]
* @param color default color [optional]
* @return choosen color or default color
*/
-
function colorDialog(title, color) {
var result;
+
function _colorDialog() {
if (title == undefined) {
title = "Choose Color";
}
+
if (color == undefined) {
color = java.awt.Color.BLACK;
}
+
var chooser = new javax.swing.JColorChooser();
var res = chooser.showDialog(window, title, color);
- result = res? res : color;
- }
+ result = res ? res : color;
+ }
if (isEventThread()) {
_colorDialog();
} else {
_colorDialog.invokeAndWait();
}
+
return result;
}
colorDialog.docString = "shows a color chooser dialog box";
@@ -156,15 +161,15 @@ colorDialog.docString = "shows a color chooser dialog box";
* @param msgType type of message box [constants in JOptionPane]
*/
function msgBox(msg, title, msgType) {
-
- function _msgBox() {
+ function _msgBox() {
var JOptionPane = javax.swing.JOptionPane;
if (msg === undefined) msg = "undefined";
if (msg === null) msg = "null";
if (title == undefined) title = msg;
- if (msgType == undefined) type = JOptionPane.INFORMATION_MESSAGE;
+ if (msgType == undefined) msgType = JOptionPane.INFORMATION_MESSAGE;
JOptionPane.showMessageDialog(window, msg, title, msgType);
}
+
if (isEventThread()) {
_msgBox();
} else {
@@ -172,13 +177,13 @@ function msgBox(msg, title, msgType) {
}
}
msgBox.docString = "shows MessageBox to the user";
-
+
/**
* Shows an information alert box
*
* @param msg message to be shown
* @param title title of message box [optional]
- */
+ */
function alert(msg, title) {
var JOptionPane = javax.swing.JOptionPane;
msgBox(msg, title, JOptionPane.INFORMATION_MESSAGE);
@@ -197,7 +202,6 @@ function error(msg, title) {
}
error.docString = "shows an error message box to the user";
-
/**
* Shows a warning alert box
*
@@ -210,7 +214,6 @@ function warn(msg, title) {
}
warn.docString = "shows a warning message box to the user";
-
/**
* Shows a prompt dialog box
*
@@ -225,11 +228,13 @@ function prompt(question, answer) {
if (answer == undefined) answer = "";
result = JOptionPane.showInputDialog(window, question, answer);
}
+
if (isEventThread()) {
_prompt();
} else {
_prompt.invokeAndWait();
}
+
return result;
}
prompt.docString = "shows a prompt box to the user and returns the answer";
@@ -244,30 +249,33 @@ prompt.docString = "shows a prompt box to the user and returns the answer";
function confirm(msg, title) {
var result;
var JOptionPane = javax.swing.JOptionPane;
+
function _confirm() {
if (title == undefined) title = msg;
var optionType = JOptionPane.YES_NO_OPTION;
result = JOptionPane.showConfirmDialog(window, msg, title, optionType);
}
+
if (isEventThread()) {
_confirm();
} else {
_confirm.invokeAndWait();
- }
+ }
+
return result == JOptionPane.YES_OPTION;
}
confirm.docString = "shows a confirmation message box to the user";
/**
- * Exit the process after confirmation from user
- *
+ * Exit the process after confirmation from user
+ *
* @param exitCode return code to OS [optional]
*/
function exit(exitCode) {
if (exitCode == undefined) exitCode = 0;
if (confirm("Do you really want to exit?")) {
java.lang.System.exit(exitCode);
- }
+ }
}
exit.docString = "exits jconsole";
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/resources/mm.js b/jdk/src/share/sample/scripting/scriptpad/src/resources/mm.js
index 1e6d2305c76..2b75f243bfc 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/resources/mm.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/resources/mm.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,10 +37,9 @@
* this sample code.
*/
-
/*
* This is a collection of utilities for Monitoring
- * and management API.
+ * and management API.
*
* File dependency:
* conc.js -> for concurrency utilities
@@ -71,14 +70,14 @@ function jmxConnect(hostport) {
}
jmxConnect.docString = "connects to the given host, port (specified as name:port)";
-function mbeanConnection() {
- if (mmConnection == null) {
+function mbeanConnection() {
+ if (mmConnection == null) {
throw "Not connected to MBeanServer yet!";
}
return mmConnection;
}
-mbeanConnection.docString = "returns the current MBeanServer connection"
+mbeanConnection.docString = "returns the current MBeanServer connection";
/**
* Returns a platform MXBean proxy for given MXBean name and interface class
@@ -102,7 +101,6 @@ function objectName(objName) {
}
objectName.docString = "creates JMX ObjectName for a given String";
-
/**
* Creates a new (M&M) Attribute object
*
@@ -146,7 +144,6 @@ function queryNames(objName, query) {
}
queryNames.docString = "returns QueryNames using given ObjectName and optional query";
-
/**
* Queries with given ObjectName and QueryExp.
* QueryExp may be null.
@@ -220,7 +217,6 @@ function getMBeanAttribute(objName, attrName) {
}
getMBeanAttribute.docString = "returns a single Attribute of given ObjectName";
-
// sets MBean attributes
function setMBeanAttributes(objName, attrList) {
objName = objectName(objName);
@@ -237,7 +233,6 @@ function setMBeanAttribute(objName, attrName, attrValue) {
}
setMBeanAttribute.docString = "sets a single Attribute of given ObjectName";
-
// invokes an operation on given MBean
function invokeMBean(objName, operation, params, signature) {
objName = objectName(objName);
@@ -260,16 +255,17 @@ invokeMBean.docString = "invokes MBean operation on given ObjectName";
* will be of type FutureTask. When you need value, call 'get' on it.
*/
function mbean(objName, async) {
+ var index;
objName = objectName(objName);
- var info = mbeanInfo(objName);
+ var info = mbeanInfo(objName);
var attrs = info.attributes;
var attrMap = new Object;
- for (var index in attrs) {
+ for (index in attrs) {
attrMap[attrs[index].name] = attrs[index];
}
var opers = info.operations;
var operMap = new Object;
- for (var index in opers) {
+ for (index in opers) {
operMap[opers[index].name] = opers[index];
}
@@ -288,9 +284,9 @@ function mbean(objName, async) {
__get__: function (name) {
if (isAttribute(name)) {
if (async) {
- return getMBeanAttribute.future(objName, name);
+ return getMBeanAttribute.future(objName, name);
} else {
- return getMBeanAttribute(objName, name);
+ return getMBeanAttribute(objName, name);
}
} else if (isOperation(name)) {
var oper = operMap[name];
@@ -302,12 +298,12 @@ function mbean(objName, async) {
sigNames[index] = sigs[index].getType();
}
if (async) {
- return invokeMBean.future(objName, name,
+ return invokeMBean.future(objName, name,
params, sigNames);
} else {
return invokeMBean(objName, name, params, sigNames);
}
- }
+ };
} else {
return undefined;
}
@@ -327,9 +323,9 @@ function mbean(objName, async) {
}
mbean.docString = "returns a conveninent script wrapper for a MBean of given ObjectName";
-if (this.application != undefined) {
- this.application.addTool("JMX Connect",
- // connect to a JMX MBean Server
+if (this.application != undefined) {
+ this.application.addTool("JMX Connect",
+ // connect to a JMX MBean Server
function () {
var url = prompt("Connect to JMX server (host:port)");
if (url != null) {
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/resources/scriptpad.js b/jdk/src/share/sample/scripting/scriptpad/src/resources/scriptpad.js
index 43507043d82..807d05e1ba2 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/resources/scriptpad.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/resources/scriptpad.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,9 +37,8 @@
* this sample code.
*/
-
/*
- * This script creates a simple Notepad-like interface, which
+ * This script creates a simple Notepad-like interface, which
* serves as a simple script editor, runner.
*
* File dependency:
@@ -47,6 +46,11 @@
* gui.js -> for basic GUI functions
*/
+/*
+ * globalThis is used for actionHelpGlobals() and showFrame().
+ */
+var globalThis = this;
+
/*
* JavaImporter helps in avoiding pollution of JavaScript
* global namespace. We can import multiple Java packages
@@ -54,573 +58,572 @@
* statement.
*/
var guiPkgs = new JavaImporter(java.awt, java.awt.event,
- javax.swing, javax.swing.undo,
- javax.swing.event, javax.swing.text);
+ javax.swing, javax.swing.undo,
+ javax.swing.event, javax.swing.text);
-with (guiPkgs) {
-
- /*
- * within this "with" statement all Java classes in
- * packages defined in "guiPkgs" can be used as simple
- * names instead of the fully qualified names.
- */
-
-
- // main entry point of the scriptpad application
- function main() {
- function createEditor() {
- var c = new JTextArea();
- c.setDragEnabled(true);
- c.setFont(new Font("monospaced", Font.PLAIN, 12));
- return c;
- }
-
- /*const*/ var titleSuffix = "- Scriptpad";
- /*const*/ var defaultTitle = "Untitled" + titleSuffix;
-
- // Scriptpad's main frame
- var frame;
- // Scriptpad's main editor
- var editor;
-
- // To track the current file name
- var curFileName = null;
-
- // To track whether the current document
- // has been modified or not
- var docChanged = false;
-
- // check and alert user for unsaved
- // but modified document
- function checkDocChanged() {
- if (docChanged) {
- // ignore zero-content untitled document
- if (curFileName == null &&
- editor.document.length == 0) {
- return;
- }
-
- if (confirm(
- "Do you want to save the changes?",
- "The document has changed")) {
- actionSave();
- }
- }
- }
-
- // set a document listener to track
- // whether that is modified or not
- function setDocListener() {
- var doc = editor.getDocument();
- docChanged = false;
- doc.addDocumentListener(new DocumentListener() {
- equals: function(o) { return this === o; },
- toString: function() { return "doc listener"; },
- changeUpdate: function() { docChanged = true; },
- insertUpdate: function() { docChanged = true; },
- removeUpdate: function() { docChanged = true; },
- });
- }
-
- // menu action functions
-
- // "File" menu
-
- // create a "new" document
- function actionNew(){
- checkDocChanged();
- curFileName = null;
- editor.setDocument(new PlainDocument());
- setDocListener();
- frame.setTitle(defaultTitle);
- editor.revalidate();
- }
-
- // open an existing file
- function actionOpen() {
- checkDocChanged();
- var f = fileDialog();
- if (f == null) {
- return;
- }
- if (f.isFile() && f.canRead()) {
- frame.setTitle(f.getName() + titleSuffix);
- editor.setDocument(new PlainDocument());
- var progress = new JProgressBar();
- progress.setMinimum(0);
- progress.setMaximum(f.length());
- var doc = editor.getDocument();
- var inp = new java.io.FileReader(f);
- var buff = java.lang.reflect.Array.newInstance(
- java.lang.Character.TYPE, 4096);
- var nch;
- while ((nch = inp.read(buff, 0, buff.length)) != -1) {
- doc.insertString(doc.getLength(),
- new java.lang.String(buff, 0, nch), null);
- progress.setValue(progress.getValue() + nch);
- }
- inp.close();
- curFileName = f.getAbsolutePath();
- setDocListener();
- } else {
- error("Can not open file: " + f,
- "Error opening file: " + f);
- }
- }
-
- // open script from a URL
- function actionOpenURL() {
- checkDocChanged();
- var url = prompt("Address:");
- if (url == null) {
- return;
- }
-
- try {
- var u = new java.net.URL(url);
- editor.setDocument(new PlainDocument());
- frame.setTitle(url + titleSuffix);
- var progress = new JProgressBar();
- progress.setMinimum(0);
- progress.setIndeterminate(true);
- var doc = editor.getDocument();
- var inp = new java.io.InputStreamReader(u.openStream());
- var buff = java.lang.reflect.Array.newInstance(
- java.lang.Character.TYPE, 4096);
- var nch;
- while ((nch = inp.read(buff, 0, buff.length)) != -1) {
- doc.insertString(doc.getLength(),
- new java.lang.String(buff, 0, nch), null);
- progress.setValue(progress.getValue() + nch);
- }
- curFileName = null;
- setDocListener();
- } catch (e) {
- error("Error opening URL: " + e,
- "Can not open URL: " + url);
- }
- }
-
- // factored out "save" function used by
- // save, save as menu actions
- function save(file) {
- var doc = editor.getDocument();
- frame.setTitle(file.getName() + titleSuffix);
- curFileName = file;
- var progress = new JProgressBar();
- progress.setMinimum(0);
- progress.setMaximum(file.length());
- var out = new java.io.FileWriter(file);
- var text = new Segment();
- text.setPartialReturn(true);
- var charsLeft = doc.getLength();
- var offset = 0;
- while (charsLeft > 0) {
- doc.getText(offset, java.lang.Math.min(4096, charsLeft), text);
- out.write(text.array, text.offset, text.count);
- charsLeft -= text.count;
- offset += text.count;
- progress.setValue(offset);
- java.lang.Thread.sleep(10);
- }
- out.flush();
- out.close();
- docChanged = false;
- }
-
- // file-save as menu
- function actionSaveAs() {
- var ret = fileDialog(null, true);
- if (ret == null) {
- return;
- }
- save(ret);
- }
-
- // file-save menu
- function actionSave() {
- if (curFileName) {
- save(new java.io.File(curFileName));
- } else {
- actionSaveAs();
- }
- }
-
- // exit from scriptpad
- function actionExit() {
- checkDocChanged();
- java.lang.System.exit(0);
- }
-
- // "Edit" menu
-
- // cut the currently selected text
- function actionCut() {
- editor.cut();
- }
-
- // copy the currently selected text to clipboard
- function actionCopy() {
- editor.copy();
- }
-
- // paste clipboard content to document
- function actionPaste() {
- editor.paste();
- }
-
- // select all the text in editor
- function actionSelectAll() {
- editor.selectAll();
- }
-
- // "Tools" menu
-
- // run the current document as JavaScript
- function actionRun() {
- var doc = editor.getDocument();
- var script = doc.getText(0, doc.getLength());
- var oldFile = engine.get(javax.script.ScriptEngine.FILENAME);
- try {
- if (this.engine == undefined) {
- var m = new javax.script.ScriptEngineManager();
- engine = m.getEngineByName("js");
- }
- engine.put(javax.script.ScriptEngine.FILENAME, frame.title);
- engine.eval(script, context);
- } catch (e) {
- error(e, "Script Error");
- // e.rhinoException.printStackTrace();
- } finally {
- engine.put(javax.script.ScriptEngine.FILENAME, oldFile);
- }
- }
-
- // "Examples" menu
-
- // show given script as new document
- function showScript(title, str) {
- actionNew();
- frame.setTitle("Example - " + title + titleSuffix);
- var doc = editor.document;
- doc.insertString(0, str, null);
- }
-
- // "hello world"
- function actionHello() {
- showScript(arguments.callee.title,
- "alert('Hello, world');");
- }
- actionHello.title = "Hello, World";
-
- // eval the "hello world"!
- function actionEval() {
- showScript(actionEval.title,
- "eval(\"alert('Hello, world')\");");
- }
- actionEval.title = "Eval";
-
- // show how to access Java static methods
- function actionJavaStatic() {
- showScript(arguments.callee.title,
- "// Just use Java syntax\n" +
- "var props = java.lang.System.getProperties();\n" +
- "alert(props.get('os.name'));");
- }
- actionJavaStatic.title = "Java Static Calls";
-
- // show how to access Java classes, methods
- function actionJavaAccess() {
- showScript(arguments.callee.title,
- "// just use new JavaClass();\n" +
- "var fr = new javax.swing.JFrame();\n" +
- "// call all public methods as in Java\n" +
- "fr.setTitle('hello');\n" +
- "fr.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);\n" +
- "fr.setSize(200, 200);\n" +
- "fr.setVisible(true);");
- }
- actionJavaAccess.title = "Java Object Access";
-
- // show how to use Java bean conventions
- function actionJavaBean() {
- showScript(arguments.callee.title,
- "var fr = new javax.swing.JFrame();\n" +
- "fr.setSize(200, 200);\n" +
- "// access public get/set methods as fields\n" +
- "fr.defaultCloseOperation = javax.swing.WindowConstants.DISPOSE_ON_CLOSE;\n" +
- "fr.title = 'hello';\n" +
- "fr.visible = true;");
- }
- actionJavaBean.title = "Java Beans";
-
- // show how to implement Java interface
- function actionJavaInterface() {
- showScript(arguments.callee.title,
- "// use Java anonymizer class-like syntax!\n" +
- "var r = new java.lang.Runnable() {\n" +
- " run: function() {\n" +
- " alert('hello');\n" +
- " }\n" +
- " };\n" +
- "// use the above Runnable to create a Thread\n" +
- "java.lang.Thread(r).start();\n" +
- "// For simple one method interfaces, just pass script function\n" +
- "java.lang.Thread(function() { alert('world'); }).start();");
- }
- actionJavaInterface.title = "Java Interfaces";
-
- // show how to import Java classes, packages
- function actionJavaImport() {
- showScript(arguments.callee.title,
- "// use Java-like import *...\n" +
- "// importPackage(java.io);\n" +
- "// or import a specific class\n" +
- "// importClass(java.io.File);\n" +
- "// or better - import just within a scope!\n" +
- "var ioPkgs = JavaImporter(java.io);\n" +
- "with (ioPkgs) { alert(new File('.').absolutePath); }");
- }
- actionJavaImport.title = "Java Import";
-
- // "Help" menu
-
- /*
- * Shows a one liner help message for each
- * global function. Note that this function
- * depends on docString meta-data for each
- * function.
- */
- function actionHelpGlobals() {
- var names = new java.util.ArrayList();
- for (var i in this) {
- var func = this[i];
- if (typeof(func) == "function" &&
- ("docString" in func)) {
- names.add(i);
- }
- }
- java.util.Collections.sort(names);
- var helpDoc = new java.lang.StringBuffer();
- helpDoc.append("");
- var itr = names.iterator();
- while (itr.hasNext()) {
- var name = itr.next();
- helpDoc.append("");
- helpDoc.append(name);
- helpDoc.append(" ");
- helpDoc.append(this[name].docString);
- helpDoc.append(" ");
- }
- helpDoc.append("
");
-
- var helpEditor = new JEditorPane();
- helpEditor.setContentType("text/html");
- helpEditor.setEditable(false);
- helpEditor.setText(helpDoc.toString());
-
- var scroller = new JScrollPane();
- var port = scroller.getViewport();
- port.add(helpEditor);
-
- var helpFrame = new JFrame("Help - Global Functions");
- helpFrame.getContentPane().add("Center", scroller);
- helpFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
- helpFrame.pack();
- helpFrame.setSize(500, 600);
- helpFrame.setVisible(true);
- }
-
- // show a simple about message for scriptpad
- function actionAbout() {
- alert("Scriptpad\nVersion 1.0", "Scriptpad");
- }
-
- /*
- * This data is used to construct menu bar.
- * This way adding a menu is easier. Just add
- * top level menu or add an item to an existing
- * menu. "action" should be a function that is
- * called back on clicking the correponding menu.
- */
- var menuData = [
- {
- menu: "File",
- items: [
- { name: "New", action: actionNew , accel: KeyEvent.VK_N },
- { name: "Open...", action: actionOpen, accel: KeyEvent.VK_O },
- { name: "Open URL...", action: actionOpenURL, accel: KeyEvent.VK_U },
- { name: "Save", action: actionSave, accel: KeyEvent.VK_S },
- { name: "Save As...", action: actionSaveAs },
- { name: "-" },
- { name: "Exit", action: actionExit }
- ]
- },
-
- {
- menu: "Edit",
- items: [
- { name: "Cut", action: actionCut, accel: KeyEvent.VK_X },
- { name: "Copy", action: actionCopy, accel: KeyEvent.VK_C },
- { name: "Paste", action: actionPaste, accel: KeyEvent.VK_V },
- { name: "-" },
- { name: "Select All", action: actionSelectAll, accel: KeyEvent.VK_A }
- ]
- },
-
- {
- menu: "Tools",
- items: [
- { name: "Run", action: actionRun, accel: KeyEvent.VK_R },
- ]
- },
-
- {
- menu: "Examples",
- items: [
- { name: actionHello.title, action: actionHello },
- { name: actionEval.title, action: actionEval },
- { name: actionJavaStatic.title, action: actionJavaStatic },
- { name: actionJavaAccess.title, action: actionJavaAccess },
- { name: actionJavaBean.title, action: actionJavaBean },
- { name: actionJavaInterface.title, action: actionJavaInterface },
- { name: actionJavaImport.title, action: actionJavaImport },
- ]
- },
-
- {
- menu: "Help",
- items: [
- { name: "Global Functions", action: actionHelpGlobals },
- { name: "-" },
- { name: "About Scriptpad", action: actionAbout },
- ]
- }
- ];
-
-
- function setMenuAccelerator(mi, accel) {
- var keyStroke = KeyStroke.getKeyStroke(accel,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
- mi.setAccelerator(keyStroke);
- }
-
- // create a menubar using the above menu data
- function createMenubar() {
- var mb = new JMenuBar();
- for (var m in menuData) {
- var items = menuData[m].items;
- var menu = new JMenu(menuData[m].menu);
- for (var i in items) {
- if (items[i].name.equals("-")) {
- menu.addSeparator();
- } else {
- var mi = new JMenuItem(items[i].name);
- var action = items[i].action;
- mi.addActionListener(action);
- var accel = items[i].accel;
- if (accel) {
- setMenuAccelerator(mi, accel);
- }
- menu.add(mi);
- }
- }
- mb.add(menu);
- }
- return mb;
- }
-
- // function to add a new menu item under "Tools" menu
- function addTool(menuItem, action, accel) {
- if (typeof(action) != "function") {
- return;
- }
-
- var toolsIndex = -1;
- // find the index of the "Tools" menu
- for (var i in menuData) {
- if (menuData[i].menu.equals("Tools")) {
- toolsIndex = i;
- break;
- }
- }
- if (toolsIndex == -1) {
- return;
- }
- var toolsMenu = frame.getJMenuBar().getMenu(toolsIndex);
- var mi = new JMenuItem(menuItem);
- mi.addActionListener(action);
- if (accel) {
- setMenuAccelerator(mi, accel);
- }
- toolsMenu.add(mi);
- }
-
-
- // create Scriptpad frame
- function createFrame() {
- frame = new JFrame();
- frame.setTitle(defaultTitle);
- frame.setBackground(Color.lightGray);
- frame.getContentPane().setLayout(new BorderLayout());
-
- // create notepad panel
- var notepad = new JPanel();
- notepad.setBorder(BorderFactory.createEtchedBorder());
- notepad.setLayout(new BorderLayout());
-
- // create editor
- editor = createEditor();
- var scroller = new JScrollPane();
- var port = scroller.getViewport();
- port.add(editor);
-
- // add editor to notepad panel
- var panel = new JPanel();
- panel.setLayout(new BorderLayout());
- panel.add("Center", scroller);
- notepad.add("Center", panel);
-
- // add notepad panel to frame
- frame.getContentPane().add("Center", notepad);
-
- // set menu bar to frame and show the frame
- frame.setJMenuBar(createMenubar());
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.pack();
- frame.setSize(500, 600);
- }
-
- // show Scriptpad frame
- function showFrame() {
- // set global variable by the name "window"
- this.window = frame;
-
- // open new document
- actionNew();
-
- frame.setVisible(true);
- }
-
- // create and show Scriptpad frame
- createFrame();
- showFrame();
-
- /*
- * Application object has two fields "frame", "editor"
- * which are current JFrame and editor and a method
- * called "addTool" to add new menu item to "Tools" menu.
- */
- return {
- frame: frame,
- editor: editor,
- addTool: addTool
- };
+// main entry point of the scriptpad application
+var main = function() {
+ function createEditor() {
+ var c = new guiPkgs.JTextArea();
+ c.setDragEnabled(true);
+ c.setFont(new guiPkgs.Font("monospaced", guiPkgs.Font.PLAIN, 12));
+ return c;
}
-}
+
+ /*const*/ var titleSuffix = "- Scriptpad";
+ /*const*/ var defaultTitle = "Untitled" + titleSuffix;
+
+ // Scriptpad's main frame
+ var frame;
+ // Scriptpad's main editor
+ var editor;
+
+ // To track the current file name
+ var curFileName = null;
+
+ // To track whether the current document
+ // has been modified or not
+ var docChanged = false;
+
+ // check and alert user for unsaved
+ // but modified document
+ function checkDocChanged() {
+ if (docChanged) {
+ // ignore zero-content untitled document
+ if (curFileName == null &&
+ editor.document.length == 0) {
+ return;
+ }
+
+ if (confirm("Do you want to save the changes?",
+ "The document has changed")) {
+ actionSave();
+ }
+ }
+ }
+
+ // set a document listener to track
+ // whether that is modified or not
+ function setDocListener() {
+ var doc = editor.getDocument();
+ docChanged = false;
+ doc.addDocumentListener( new guiPkgs.DocumentListener() {
+ equals: function(o) {
+ return this === o; },
+ toString: function() {
+ return "doc listener"; },
+ changeUpdate: function() {
+ docChanged = true; },
+ insertUpdate: function() {
+ docChanged = true; },
+ removeUpdate: function() {
+ docChanged = true; }
+ });
+ }
+
+ // menu action functions
+
+ // "File" menu
+
+ // create a "new" document
+ function actionNew() {
+ checkDocChanged();
+ curFileName = null;
+ editor.setDocument(new guiPkgs.PlainDocument());
+ setDocListener();
+ frame.setTitle(defaultTitle);
+ editor.revalidate();
+ }
+
+ // open an existing file
+ function actionOpen() {
+ checkDocChanged();
+ var f = fileDialog();
+ if (f == null) {
+ return;
+ }
+
+ if (f.isFile() && f.canRead()) {
+ frame.setTitle(f.getName() + titleSuffix);
+ editor.setDocument(new guiPkgs.PlainDocument());
+ var progress = new guiPkgs.JProgressBar();
+ progress.setMinimum(0);
+ progress.setMaximum(f.length());
+ var doc = editor.getDocument();
+ var inp = new java.io.FileReader(f);
+ var buff = java.lang.reflect.Array.newInstance(
+ java.lang.Character.TYPE, 4096);
+ var nch;
+ while ((nch = inp.read(buff, 0, buff.length)) != -1) {
+ doc.insertString(doc.getLength(),
+ new java.lang.String(buff, 0, nch), null);
+ progress.setValue(progress.getValue() + nch);
+ }
+ inp.close();
+ curFileName = f.getAbsolutePath();
+ setDocListener();
+ } else {
+ error("Can not open file: " + f,
+ "Error opening file: " + f);
+ }
+ }
+
+ // open script from a URL
+ function actionOpenURL() {
+ checkDocChanged();
+ var url = prompt("Address:");
+ if (url == null) {
+ return;
+ }
+
+ try {
+ var u = new java.net.URL(url);
+ editor.setDocument(new guiPkgs.PlainDocument());
+ frame.setTitle(url + titleSuffix);
+ var progress = new guiPkgs.JProgressBar();
+ progress.setMinimum(0);
+ progress.setIndeterminate(true);
+ var doc = editor.getDocument();
+ var inp = new java.io.InputStreamReader(u.openStream());
+ var buff = java.lang.reflect.Array.newInstance(
+ java.lang.Character.TYPE, 4096);
+ var nch;
+ while ((nch = inp.read(buff, 0, buff.length)) != -1) {
+ doc.insertString(doc.getLength(),
+ new java.lang.String(buff, 0, nch), null);
+ progress.setValue(progress.getValue() + nch);
+ }
+ curFileName = null;
+ setDocListener();
+ } catch (e) {
+ error("Error opening URL: " + e,
+ "Can not open URL: " + url);
+ }
+ }
+
+ // factored out "save" function used by
+ // save, save as menu actions
+ function save(file) {
+ var doc = editor.getDocument();
+ frame.setTitle(file.getName() + titleSuffix);
+ curFileName = file;
+ var progress = new guiPkgs.JProgressBar();
+ progress.setMinimum(0);
+ progress.setMaximum(file.length());
+ var out = new java.io.FileWriter(file);
+ var text = new guiPkgs.Segment();
+ text.setPartialReturn(true);
+ var charsLeft = doc.getLength();
+ var offset = 0;
+ var min;
+
+ while (charsLeft > 0) {
+ doc.getText(offset, Math.min(4096, charsLeft), text);
+ out.write(text.array, text.offset, text.count);
+ charsLeft -= text.count;
+ offset += text.count;
+ progress.setValue(offset);
+ java.lang.Thread.sleep(10);
+ }
+
+ out.flush();
+ out.close();
+ docChanged = false;
+ }
+
+ // file-save as menu
+ function actionSaveAs() {
+ var ret = fileDialog(null, true);
+ if (ret == null) {
+ return;
+ }
+ save(ret);
+ }
+
+ // file-save menu
+ function actionSave() {
+ if (curFileName) {
+ save(new java.io.File(curFileName));
+ } else {
+ actionSaveAs();
+ }
+ }
+
+ // exit from scriptpad
+ function actionExit() {
+ checkDocChanged();
+ java.lang.System.exit(0);
+ }
+
+ // "Edit" menu
+
+ // cut the currently selected text
+ function actionCut() {
+ editor.cut();
+ }
+
+ // copy the currently selected text to clipboard
+ function actionCopy() {
+ editor.copy();
+ }
+
+ // paste clipboard content to document
+ function actionPaste() {
+ editor.paste();
+ }
+
+ // select all the text in editor
+ function actionSelectAll() {
+ editor.selectAll();
+ }
+
+ // "Tools" menu
+
+ // run the current document as JavaScript
+ function actionRun() {
+ var doc = editor.getDocument();
+ var script = doc.getText(0, doc.getLength());
+ var oldFile = engine.get(javax.script.ScriptEngine.FILENAME);
+ try {
+ if (engine == undefined) {
+ var m = new javax.script.ScriptEngineManager();
+ engine = m.getEngineByName("nashorn");
+ }
+ engine.put(javax.script.ScriptEngine.FILENAME, frame.title);
+ engine.eval(script, context);
+ } catch (e) {
+ error(e, "Script Error");
+ e.printStackTrace();
+ } finally {
+ engine.put(javax.script.ScriptEngine.FILENAME, oldFile);
+ }
+ }
+
+ // "Examples" menu
+
+ // show given script as new document
+ function showScript(title, str) {
+ actionNew();
+ frame.setTitle("Example - " + title + titleSuffix);
+ var doc = editor.document;
+ doc.insertString(0, str, null);
+ }
+
+ // "hello world"
+ function actionHello() {
+ showScript(actionEval.title,
+ "alert('Hello, world');");
+ }
+ actionHello.title = "Hello, World";
+
+ // eval the "hello world"!
+ function actionEval() {
+ showScript(actionEval.title,
+ "eval(\"alert('Hello, world')\");");
+ }
+ actionEval.title = "Eval";
+
+ // show how to access Java static methods
+ function actionJavaStatic() {
+ showScript(arguments.callee.title,
+ "// Just use Java syntax\n" +
+ "var props = java.lang.System.getProperties();\n" +
+ "alert(props.get('os.name'));");
+ }
+ actionJavaStatic.title = "Java Static Calls";
+
+ // show how to access Java classes, methods
+ function actionJavaAccess() {
+ showScript(arguments.callee.title,
+ "// just use new JavaClass();\n" +
+ "var fr = new javax.swing.JFrame();\n" +
+ "// call all public methods as in Java\n" +
+ "fr.setTitle('hello');\n" +
+ "fr.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);\n" +
+ "fr.setSize(200, 200);\n" +
+ "fr.setVisible(true);");
+ }
+ actionJavaAccess.title = "Java Object Access";
+
+ // show how to use Java bean conventions
+ function actionJavaBean() {
+ showScript(arguments.callee.title,
+ "var fr = new javax.swing.JFrame();\n" +
+ "fr.setSize(200, 200);\n" +
+ "// access public get/set methods as fields\n" +
+ "fr.defaultCloseOperation = javax.swing.WindowConstants.DISPOSE_ON_CLOSE;\n" +
+ "fr.title = 'hello';\n" +
+ "fr.visible = true;");
+ }
+ actionJavaBean.title = "Java Beans";
+
+ // show how to implement Java interface
+ function actionJavaInterface() {
+ showScript(arguments.callee.title,
+ "// use Java anonymizer class-like syntax!\n" +
+ "var r = new java.lang.Runnable() {\n" +
+ " run: function() {\n" +
+ " alert('hello');\n" +
+ " }\n" +
+ " };\n" +
+ "// use the above Runnable to create a Thread\n" +
+ "new java.lang.Thread(r).start();\n" +
+ "// For simple one method interfaces, just pass script function\n" +
+ "new java.lang.Thread(function() { alert('world'); }).start();");
+ }
+ actionJavaInterface.title = "Java Interfaces";
+
+ // show how to import Java classes, packages
+ function actionJavaImport() {
+ showScript(arguments.callee.title,
+ "// use Java-like import *...\n" +
+ "// importPackage(java.io);\n" +
+ "// or import a specific class\n" +
+ "// importClass(java.io.File);\n" +
+ "// or better - import just within a scope!\n" +
+ "var ioPkgs = JavaImporter(java.io);\n" +
+ "with (ioPkgs) { alert(new File('.').absolutePath); }");
+ }
+ actionJavaImport.title = "Java Import";
+
+ // "Help" menu
+
+ /*
+ * Shows a one liner help message for each
+ * global function. Note that this function
+ * depends on docString meta-data for each
+ * function.
+ */
+ function actionHelpGlobals() {
+ var names = new java.util.ArrayList();
+ for (var i in globalThis) {
+ var func = globalThis[i];
+ if (typeof(func) == "function" &&
+ ("docString" in func)) {
+ names.add(i);
+ }
+ }
+ java.util.Collections.sort(names);
+ var helpDoc = new java.lang.StringBuffer();
+ helpDoc.append("");
+ var itr = names.iterator();
+ while (itr.hasNext()) {
+ var name = itr.next();
+ helpDoc.append("");
+ helpDoc.append(name);
+ helpDoc.append(" ");
+ helpDoc.append(globalThis[name].docString);
+ helpDoc.append(" ");
+ }
+ helpDoc.append("
");
+
+ var helpEditor = new guiPkgs.JEditorPane();
+ helpEditor.setContentType("text/html");
+ helpEditor.setEditable(false);
+ helpEditor.setText(helpDoc.toString());
+
+ var scroller = new guiPkgs.JScrollPane();
+ var port = scroller.getViewport();
+ port.add(helpEditor);
+
+ var helpFrame = new guiPkgs.JFrame("Help - Global Functions");
+ helpFrame.getContentPane().add("Center", scroller);
+ helpFrame.setDefaultCloseOperation(guiPkgs.WindowConstants.DISPOSE_ON_CLOSE);
+ helpFrame.pack();
+ helpFrame.setSize(500, 600);
+ helpFrame.setVisible(true);
+ }
+
+ // show a simple about message for scriptpad
+ function actionAbout() {
+ alert("Scriptpad\nVersion 1.1", "Scriptpad");
+ }
+
+ /*
+ * This data is used to construct menu bar.
+ * This way adding a menu is easier. Just add
+ * top level menu or add an item to an existing
+ * menu. "action" should be a function that is
+ * called back on clicking the correponding menu.
+ */
+ var menuData = [
+ {
+ menu: "File",
+ items: [
+ { name: "New", action: actionNew , accel: guiPkgs.KeyEvent.VK_N },
+ { name: "Open...", action: actionOpen, accel: guiPkgs.KeyEvent.VK_O },
+ { name: "Open URL...", action: actionOpenURL, accel: guiPkgs.KeyEvent.VK_U },
+ { name: "Save", action: actionSave, accel: guiPkgs.KeyEvent.VK_S },
+ { name: "Save As...", action: actionSaveAs },
+ { name: "-" },
+ { name: "Exit", action: actionExit, accel: guiPkgs.KeyEvent.VK_Q }
+ ]
+ },
+
+ {
+ menu: "Edit",
+ items: [
+ { name: "Cut", action: actionCut, accel: guiPkgs.KeyEvent.VK_X },
+ { name: "Copy", action: actionCopy, accel: guiPkgs.KeyEvent.VK_C },
+ { name: "Paste", action: actionPaste, accel: guiPkgs.KeyEvent.VK_V },
+ { name: "-" },
+ { name: "Select All", action: actionSelectAll, accel: guiPkgs.KeyEvent.VK_A }
+ ]
+ },
+
+ {
+ menu: "Tools",
+ items: [
+ { name: "Run", action: actionRun, accel: guiPkgs.KeyEvent.VK_R }
+ ]
+ },
+
+ {
+ menu: "Examples",
+ items: [
+ { name: actionHello.title, action: actionHello },
+ { name: actionEval.title, action: actionEval },
+ { name: actionJavaStatic.title, action: actionJavaStatic },
+ { name: actionJavaAccess.title, action: actionJavaAccess },
+ { name: actionJavaBean.title, action: actionJavaBean },
+ { name: actionJavaInterface.title, action: actionJavaInterface },
+ { name: actionJavaImport.title, action: actionJavaImport }
+ ]
+ },
+
+ {
+ menu: "Help",
+ items: [
+ { name: "Global Functions", action: actionHelpGlobals },
+ { name: "-" },
+ { name: "About Scriptpad", action: actionAbout }
+ ]
+ }
+ ];
+
+ function setMenuAccelerator(mi, accel) {
+ var keyStroke = guiPkgs.KeyStroke.getKeyStroke(accel,
+ guiPkgs.Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
+ mi.setAccelerator(keyStroke);
+ }
+
+ // create a menubar using the above menu data
+ function createMenubar() {
+ var mb = new guiPkgs.JMenuBar();
+ for (var m in menuData) {
+ var items = menuData[m].items;
+ var menu = new guiPkgs.JMenu(menuData[m].menu);
+
+ for (var i in items) {
+ if (items[i].name.equals("-")) {
+ menu.addSeparator();
+ } else {
+ var mi = new guiPkgs.JMenuItem(items[i].name);
+ var action = items[i].action;
+ mi.addActionListener(action);
+ var accel = items[i].accel;
+ if (accel) {
+ setMenuAccelerator(mi, accel);
+ }
+ menu.add(mi);
+ }
+ }
+
+ mb.add(menu);
+ }
+
+ return mb;
+ }
+
+ // function to add a new menu item under "Tools" menu
+ function addTool(menuItem, action, accel) {
+ if (typeof(action) != "function") {
+ return;
+ }
+
+ var toolsIndex = -1;
+ // find the index of the "Tools" menu
+ for (var i in menuData) {
+ if (menuData[i].menu.equals("Tools")) {
+ toolsIndex = i;
+ break;
+ }
+ }
+ if (toolsIndex == -1) {
+ return;
+ }
+ var toolsMenu = frame.getJMenuBar().getMenu(toolsIndex);
+ var mi = new guiPkgs.JMenuItem(menuItem);
+ mi.addActionListener(action);
+ if (accel) {
+ setMenuAccelerator(mi, accel);
+ }
+ toolsMenu.add(mi);
+ }
+
+ // create Scriptpad frame
+ function createFrame() {
+ frame = new guiPkgs.JFrame();
+ frame.setTitle(defaultTitle);
+ frame.setBackground(guiPkgs.Color.lightGray);
+ frame.getContentPane().setLayout(new guiPkgs.BorderLayout());
+
+ // create notepad panel
+ var notepad = new guiPkgs.JPanel();
+ notepad.setBorder(guiPkgs.BorderFactory.createEtchedBorder());
+ notepad.setLayout(new guiPkgs.BorderLayout());
+
+ // create editor
+ editor = createEditor();
+ var scroller = new guiPkgs.JScrollPane();
+ var port = scroller.getViewport();
+ port.add(editor);
+
+ // add editor to notepad panel
+ var panel = new guiPkgs.JPanel();
+ panel.setLayout(new guiPkgs.BorderLayout());
+ panel.add("Center", scroller);
+ notepad.add("Center", panel);
+
+ // add notepad panel to frame
+ frame.getContentPane().add("Center", notepad);
+
+ // set menu bar to frame and show the frame
+ frame.setJMenuBar(createMenubar());
+ frame.setDefaultCloseOperation(guiPkgs.JFrame.EXIT_ON_CLOSE);
+ frame.pack();
+ frame.setSize(500, 600);
+ }
+
+ // show Scriptpad frame
+ function showFrame() {
+ // set global variable by the name "window"
+ globalThis.window = frame;
+
+ // open new document
+ actionNew();
+
+ frame.setVisible(true);
+ }
+
+ // create and show Scriptpad frame
+ createFrame();
+ showFrame();
+
+ /*
+ * Application object has two fields "frame", "editor"
+ * which are current JFrame and editor and a method
+ * called "addTool" to add new menu item to "Tools" menu.
+ */
+ return {
+ frame: frame,
+ editor: editor,
+ addTool: addTool
+ };
+};
/*
- * Call the main and store Application object
+ * Call the main and store Application object
* in a global variable named "application".
*/
var application = main();
@@ -657,4 +660,3 @@ function loadUserInit() {
}
loadUserInit();
-
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/browse.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/browse.js
index 975e45435e3..fbe50e1a414 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/browse.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/browse.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,33 +37,30 @@
* this sample code.
*/
-
/*
* This function uses new Swing Desktop API in JDK 6.
* To use this with scriptpad, open this in scriptpad
* and use "Tools->Run Script" menu.
*/
function browse() {
- with (guiPkgs) {
- var desktop = null;
- // Before more Desktop API is used, first check
- // whether the API is supported by this particular
- // virtual machine (VM) on this particular host.
- if (Desktop.isDesktopSupported()) {
- desktop = Desktop.getDesktop();
- } else {
- alert("no desktop support");
- return;
- }
+ var desktop = null;
+ // Before more Desktop API is used, first check
+ // whether the API is supported by this particular
+ // virtual machine (VM) on this particular host.
+ if (java.awt.Desktop.isDesktopSupported()) {
+ desktop = java.awt.Desktop.getDesktop();
+ } else {
+ alert("no desktop support");
+ return;
+ }
- if (desktop.isSupported(Desktop.Action.BROWSE)) {
- var url = prompt("Address:");
- if (url != null) {
- desktop.browse(new java.net.URI(url));
- }
- } else {
- alert("no browser support");
+ if (desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
+ var url = prompt("Address:");
+ if (url != null) {
+ desktop.browse(new java.net.URI(url));
}
+ } else {
+ alert("no browser support");
}
}
@@ -71,4 +68,3 @@ if (this.application != undefined) {
// add "Browse" menu item under "Tools" menu
this.application.addTool("Browse", browse);
}
-
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/insertfile.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/insertfile.js
index b463e9a79c7..07a7ac28d19 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/insertfile.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/insertfile.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +37,6 @@
* this sample code.
*/
-
/*
* This script adds "Insert File" mode menu item to "Tools" menu.
* When selected, this menu shows a file dialog box and inserts
@@ -48,18 +47,22 @@ if (this.application) {
application.addTool("Insert File...",
function() {
var file = fileDialog();
- if (file) {
+
+ if (file) {
var reader = new java.io.FileReader(file);
var arr = java.lang.reflect.Array.newInstance(
java.lang.Character.TYPE, 8*1024); // 8K at a time
var buf = new java.lang.StringBuffer();
var numChars;
+
while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
buf.append(arr, 0, numChars);
}
+
var pos = application.editor.caretPosition;
var doc = application.editor.document;
+
doc.insertString(pos, buf.toString(), null);
}
- })
+ });
}
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/linewrap.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/linewrap.js
index e1ac50dc126..989473a6cf1 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/linewrap.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/linewrap.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,19 +37,15 @@
* this sample code.
*/
-
/*
* This script adds "Line Wrap" mode menu item to "Tools" menu.
* When selected, this menu toggles the current word wrap mode
* of the editor.
*/
-with (guiPkgs) {
- function toggleLineWrap() {
- var wrap = application.editor.lineWrap;
- application.editor.lineWrap = !wrap;
- }
-
- application.addTool("Line Wrap", toggleLineWrap);
+function toggleLineWrap() {
+ var wrap = application.editor.lineWrap;
+ application.editor.lineWrap = !wrap;
}
+application.addTool("Line Wrap", toggleLineWrap);
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/mail.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/mail.js
index 7104e29ad1d..cabe5c47541 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/mail.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/mail.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,30 +37,27 @@
* this sample code.
*/
-
/*
* This function uses new Swing Desktop API in JDK 6.
* To use this with scriptpad, open this in scriptpad
* and use "Tools->Run Script" menu.
*/
function mail() {
- with (guiPkgs) {
- var desktop = null;
- // Before more Desktop API is used, first check
- // whether the API is supported by this particular
- // virtual machine (VM) on this particular host.
- if (Desktop.isDesktopSupported()) {
- desktop = Desktop.getDesktop();
- } else {
- alert("no desktop support");
- return;
- }
+ var desktop = null;
+ // Before more Desktop API is used, first check
+ // whether the API is supported by this particular
+ // virtual machine (VM) on this particular host.
+ if (java.awt.Desktop.isDesktopSupported()) {
+ desktop = java.awt.Desktop.getDesktop();
+ } else {
+ alert("no desktop support");
+ return;
+ }
- if (desktop.isSupported(Desktop.Action.MAIL)) {
- var mailTo = prompt("Mail To:");
- if (mailTo != null) {
- desktop.mail(new java.net.URI("mailto", mailTo, null));
- }
+ if (desktop.isSupported(java.awt.Desktop.Action.MAIL)) {
+ var mailTo = prompt("Mail To:");
+ if (mailTo != null) {
+ desktop.mail(new java.net.URI("mailto", mailTo, null));
}
}
}
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/memmonitor.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/memmonitor.js
index 7fac72f6954..0744e303b78 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/memmonitor.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/memmonitor.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,36 +37,37 @@
* this sample code.
*/
-
// this checker function runs asynchronously
function memoryChecker(memoryBean, threshold, interval) {
while (true) {
var memUsage = memoryBean.HeapMemoryUsage;
var usage = memUsage.get("used") / (1024 * 1024);
- println(usage);
+
+ println("usage: " + usage);
+
if (usage > threshold) {
alert("Hey! heap usage threshold exceeded!");
// after first alert just return.
return;
}
- java.lang.Thread.currentThread().sleep(interval);
+
+ java.lang.Thread.sleep(interval);
}
}
-
// add "Tools->Memory Monitor" menu item
if (this.application != undefined) {
- this.application.addTool("Memory Monitor",
+ this.application.addTool("Memory Monitor",
function () {
// show threshold box with default of 50 MB
var threshold = prompt("Threshold (mb)", 50);
+
// show interval box with default of 1000 millisec.
var interval = prompt("Sample Interval (ms):", 1000);
var memoryBean = mbean("java.lang:type=Memory");
- // ".future" makes the function to be called
+ // ".future" makes the function to be called
// asynchronously in a separate thread.
memoryChecker.future(memoryBean, threshold, interval);
});
}
-
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.js
index 53b8b3575b7..b8252fbfbcc 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +37,6 @@
* this sample code.
*/
-
/*
* This script serves as a simple "monitored application".
* Start this script using memory.bat or memory.sh in the
@@ -45,12 +44,11 @@
*/
java.lang.System.out.print("Enter a number and press enter:");
-java.lang.System["in"].read();
+var input = java.lang.System["in"].read();
// allocate an integer array of "big enough" size!
var a = java.lang.reflect.Array.newInstance(
- java.lang.Integer.TYPE, 1024*1024);
-
-// loop forever!
-while (true);
+ java.lang.Integer.TYPE, input * 1024 * 1024);
+// sleep some time...
+java.lang.Thread.sleep(10*60*1000);
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.sh b/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.sh
index d42370ffe6e..5477623c8ee 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.sh
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/memory.sh
@@ -30,7 +30,3 @@
#
jrunscript -J-Dcom.sun.management.jmxremote.port=1090 -J-Dcom.sun.management.jmxremote.ssl=false -J-Dcom.sun.management.jmxremote.authenticate=false memory.js
-
-
-
-
diff --git a/jdk/src/share/sample/scripting/scriptpad/src/scripts/textcolor.js b/jdk/src/share/sample/scripting/scriptpad/src/scripts/textcolor.js
index 49f5dfbf1f5..b9d86cc37f0 100644
--- a/jdk/src/share/sample/scripting/scriptpad/src/scripts/textcolor.js
+++ b/jdk/src/share/sample/scripting/scriptpad/src/scripts/textcolor.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,14 +37,13 @@
* this sample code.
*/
-
/*
* This script adds "Selected Text Color" menu item to "Tools" menu.
* When selected, this menu changes the "selected text" color.
*/
if (this.application) {
application.addTool("Selected Text Color...",
- function() {
+ function() {
var color = application.editor.selectedTextColor;
color = colorDialog("Selected Text Color", color);
application.editor.selectedTextColor = color;
diff --git a/jdk/src/windows/classes/java/lang/ProcessImpl.java b/jdk/src/windows/classes/java/lang/ProcessImpl.java
index 90878af2d10..de7a9057c54 100644
--- a/jdk/src/windows/classes/java/lang/ProcessImpl.java
+++ b/jdk/src/windows/classes/java/lang/ProcessImpl.java
@@ -37,7 +37,10 @@ import java.io.BufferedOutputStream;
import java.lang.ProcessBuilder.Redirect;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/* This class is for the exclusive use of ProcessBuilder.start() to
* create new processes.
@@ -145,6 +148,66 @@ final class ProcessImpl extends Process {
}
+ private static class LazyPattern {
+ // Escape-support version:
+ // "(\")((?:\\\\\\1|.)+?)\\1|([^\\s\"]+)";
+ private static final Pattern PATTERN =
+ Pattern.compile("[^\\s\"]+|\"[^\"]*\"");
+ };
+
+ /* Parses the command string parameter into the executable name and
+ * program arguments.
+ *
+ * The command string is broken into tokens. The token separator is a space
+ * or quota character. The space inside quotation is not a token separator.
+ * There are no escape sequences.
+ */
+ private static String[] getTokensFromCommand(String command) {
+ ArrayList matchList = new ArrayList<>(8);
+ Matcher regexMatcher = LazyPattern.PATTERN.matcher(command);
+ while (regexMatcher.find())
+ matchList.add(regexMatcher.group());
+ return matchList.toArray(new String[matchList.size()]);
+ }
+
+ private static String createCommandLine(boolean isCmdFile,
+ final String executablePath,
+ final String cmd[])
+ {
+ StringBuilder cmdbuf = new StringBuilder(80);
+
+ cmdbuf.append(executablePath);
+
+ for (int i = 1; i < cmd.length; ++i) {
+ cmdbuf.append(' ');
+ String s = cmd[i];
+ if (needsEscaping(isCmdFile, s)) {
+ cmdbuf.append('"');
+ cmdbuf.append(s);
+
+ // The code protects the [java.exe] and console command line
+ // parser, that interprets the [\"] combination as an escape
+ // sequence for the ["] char.
+ // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+ //
+ // If the argument is an FS path, doubling of the tail [\]
+ // char is not a problem for non-console applications.
+ //
+ // The [\"] sequence is not an escape sequence for the [cmd.exe]
+ // command line parser. The case of the [""] tail escape
+ // sequence could not be realized due to the argument validation
+ // procedure.
+ if (!isCmdFile && s.endsWith("\\")) {
+ cmdbuf.append('\\');
+ }
+ cmdbuf.append('"');
+ } else {
+ cmdbuf.append(s);
+ }
+ }
+ return cmdbuf.toString();
+ }
+
// We guarantee the only command file execution for implicit [cmd.exe] run.
// http://technet.microsoft.com/en-us/library/bb490954.aspx
private static final char CMD_BAT_ESCAPE[] = {' ', '\t', '<', '>', '&', '|', '^'};
@@ -227,64 +290,89 @@ final class ProcessImpl extends Process {
}
+ private boolean isShellFile(String executablePath) {
+ String upPath = executablePath.toUpperCase();
+ return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
+ }
+
+ private String quoteString(String arg) {
+ StringBuilder argbuf = new StringBuilder(arg.length() + 2);
+ return argbuf.append('"').append(arg).append('"').toString();
+ }
+
+
private long handle = 0;
private OutputStream stdin_stream;
private InputStream stdout_stream;
private InputStream stderr_stream;
- private ProcessImpl(final String cmd[],
+ private ProcessImpl(String cmd[],
final String envblock,
final String path,
final long[] stdHandles,
final boolean redirectErrorStream)
throws IOException
{
- // The [executablePath] is not quoted for any case.
- String executablePath = getExecutablePath(cmd[0]);
-
- // We need to extend the argument verification procedure
- // to guarantee the only command file execution for implicit [cmd.exe]
- // run.
- String upPath = executablePath.toUpperCase();
- boolean isCmdFile = (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
-
- StringBuilder cmdbuf = new StringBuilder(80);
-
- // Quotation protects from interpretation of the [path] argument as
- // start of longer path with spaces. Quotation has no influence to
- // [.exe] extension heuristic.
- cmdbuf.append('"');
- cmdbuf.append(executablePath);
- cmdbuf.append('"');
-
- for (int i = 1; i < cmd.length; i++) {
- cmdbuf.append(' ');
- String s = cmd[i];
- if (needsEscaping(isCmdFile, s)) {
- cmdbuf.append('"');
- cmdbuf.append(s);
-
- // The code protects the [java.exe] and console command line
- // parser, that interprets the [\"] combination as an escape
- // sequence for the ["] char.
- // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
- //
- // If the argument is an FS path, doubling of the tail [\]
- // char is not a problem for non-console applications.
- //
- // The [\"] sequence is not an escape sequence for the [cmd.exe]
- // command line parser. The case of the [""] tail escape
- // sequence could not be realized due to the argument validation
- // procedure.
- if (!isCmdFile && s.endsWith("\\")) {
- cmdbuf.append('\\');
- }
- cmdbuf.append('"');
- } else {
- cmdbuf.append(s);
- }
+ String cmdstr;
+ SecurityManager security = System.getSecurityManager();
+ boolean allowAmbigousCommands = false;
+ if (security == null) {
+ String value = System.getProperty("jdk.lang.Process.allowAmbigousCommands");
+ if (value != null)
+ allowAmbigousCommands = !"false".equalsIgnoreCase(value);
+ }
+ if (allowAmbigousCommands) {
+ // Legacy mode.
+
+ // Normalize path if possible.
+ String executablePath = new File(cmd[0]).getPath();
+
+ // No worry about internal and unpaired ["] .
+ if (needsEscaping(false, executablePath) )
+ executablePath = quoteString(executablePath);
+
+ cmdstr = createCommandLine(
+ false, //legacy mode doesn't worry about extended verification
+ executablePath,
+ cmd);
+ } else {
+ String executablePath;
+ try {
+ executablePath = getExecutablePath(cmd[0]);
+ } catch (IllegalArgumentException e) {
+ // Workaround for the calls like
+ // Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar")
+
+ // No chance to avoid CMD/BAT injection, except to do the work
+ // right from the beginning. Otherwise we have too many corner
+ // cases from
+ // Runtime.getRuntime().exec(String[] cmd [, ...])
+ // calls with internal ["] and escape sequences.
+
+ // Restore original command line.
+ StringBuilder join = new StringBuilder();
+ // terminal space in command line is ok
+ for (String s : cmd)
+ join.append(s).append(' ');
+
+ // Parse the command line again.
+ cmd = getTokensFromCommand(join.toString());
+ executablePath = getExecutablePath(cmd[0]);
+
+ // Check new executable name once more
+ if (security != null)
+ security.checkExec(executablePath);
+ }
+
+ // Quotation protects from interpretation of the [path] argument as
+ // start of longer path with spaces. Quotation has no influence to
+ // [.exe] extension heuristic.
+ cmdstr = createCommandLine(
+ // We need the extended verification procedure for CMD files.
+ isShellFile(executablePath),
+ quoteString(executablePath),
+ cmd);
}
- String cmdstr = cmdbuf.toString();
handle = create(cmdstr, envblock, path,
stdHandles, redirectErrorStream);
diff --git a/jdk/test/java/lang/Runtime/exec/ExecCommand.java b/jdk/test/java/lang/Runtime/exec/ExecCommand.java
new file mode 100644
index 00000000000..40f61734e56
--- /dev/null
+++ b/jdk/test/java/lang/Runtime/exec/ExecCommand.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013, 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 8012453
+ * @run main/othervm ExecCommand
+ * @summary workaround for legacy applications with Runtime.getRuntime().exec(String command)
+ */
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.security.AccessControlException;
+
+public class ExecCommand {
+ static class SecurityMan extends SecurityManager {
+ public static String unquote(String str)
+ {
+ int length = (str == null)
+ ? 0
+ : str.length();
+
+ if (length > 1
+ && str.charAt(0) == '\"'
+ && str.charAt(length - 1) == '\"')
+ {
+ return str.substring(1, length - 1);
+ }
+ return str;
+ }
+
+ @Override public void checkExec(String cmd) {
+ String ncmd = (new File(unquote(cmd))).getPath();
+ if ( ncmd.equals(".\\Program")
+ || ncmd.equals("\".\\Program")
+ || ncmd.equals(".\\Program Files\\do.cmd")
+ || ncmd.equals(".\\Program.cmd"))
+ {
+ return;
+ }
+ super.checkExec(cmd);
+ }
+ }
+
+ // Parameters for the Runtime.exec calls
+ private static final String TEST_RTE_ARG[] = {
+ ".\\Program Files\\do.cmd",
+ "\".\\Program Files\\doNot.cmd\" arg",
+ "\".\\Program Files\\do.cmd\" arg",
+ // compatibility
+ "\".\\Program.cmd\" arg",
+ ".\\Program.cmd arg",
+ };
+
+ private static final String doCmdCopy[] = {
+ ".\\Program.cmd",
+ ".\\Program Files\\doNot.cmd",
+ ".\\Program Files\\do.cmd",
+ };
+
+ // Golden image for results
+ private static final String TEST_RTE_GI[][] = {
+ //Pure system | Legacy mode | Legacy mode & SM
+ // [.\Program File\do.cmd]
+ new String[]{"IOException", // [.\Program] not found
+ "Success",
+ "IOException"}, //SM - no legacy mode [.\Program] - OK
+
+ // [".\Program File\doNot.cmd" arg]
+ new String[]{"Success",
+ "Success",
+ "AccessControlException"}, //SM - [".\Program] - OK,
+ // [.\\Program Files\\doNot.cmd] - Fail
+
+ // [".\Program File\do.cmd" arg]
+ // AccessControlException
+ new String[]{"Success",
+ "Success",
+ "Success"}, //SM - [".\Program] - OK,
+ // [.\\Program Files\\do.cmd] - OK
+
+ // compatibility
+ new String[]{"Success", "Success", "Success"}, //[".\Program.cmd"]
+ new String[]{"Success", "Success", "Success"} //[.\Program.cmd]
+ };
+
+ public static void main(String[] _args) throws Exception {
+ if (!System.getProperty("os.name").startsWith("Windows")) {
+ return;
+ }
+
+ // tear up
+ try {
+ new File(".\\Program Files").mkdirs();
+ for (int i = 0; i < doCmdCopy.length; ++i) {
+ try (BufferedWriter outCmd = new BufferedWriter(
+ new FileWriter(doCmdCopy[i]))) {
+ outCmd.write("@echo %1");
+ }
+ }
+ } catch (IOException e) {
+ throw new Error(e.getMessage());
+ }
+
+ // action
+ for (int k = 0; k < 3; ++k) {
+ switch (k) {
+ case 1:
+ System.setProperty("jdk.lang.Process.allowAmbigousCommands", "");
+ break;
+ case 2:
+ System.setSecurityManager( new SecurityMan() );
+ break;
+ }
+ for (int i = 0; i < TEST_RTE_ARG.length; ++i) {
+ String outRes;
+ try {
+ Process exec = Runtime.getRuntime().exec(TEST_RTE_ARG[i]);
+ exec.waitFor();
+ outRes = "Success";
+ } catch (IOException ioe) {
+ outRes = "IOException: " + ioe.getMessage();
+ } catch (IllegalArgumentException iae) {
+ outRes = "IllegalArgumentException: " + iae.getMessage();
+ } catch (AccessControlException se) {
+ outRes = "AccessControlException: " + se.getMessage();
+ }
+
+ if (!outRes.startsWith(TEST_RTE_GI[i][k])) {
+ throw new Error("Unexpected output! Step" + k + "" + i
+ + " \nArgument: " + TEST_RTE_ARG[i]
+ + "\nExpected: " + TEST_RTE_GI[i][k]
+ + "\n Output: " + outRes);
+ } else {
+ System.out.println("RTE OK:" + TEST_RTE_ARG[i]);
+ }
+ }
+ }
+ }
+}
diff --git a/jdk/test/java/lang/StringBuffer/ToStringCache.java b/jdk/test/java/lang/StringBuffer/ToStringCache.java
new file mode 100644
index 00000000000..6259e27d0e3
--- /dev/null
+++ b/jdk/test/java/lang/StringBuffer/ToStringCache.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2013, 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 8013395
+ * @summary Test StringBuffer.toString caching
+ */
+
+public class ToStringCache {
+
+ // we can't test that we actually use a cached value (the benchmarks
+ // verify that) but we have to test that the cache is cleared when
+ // expected
+
+ public static void main(String[] args) throws Exception {
+ String original = "The original String";
+
+ StringBuffer sb = new StringBuffer(original);
+
+ String a = sb.toString();
+ checkEqual(a, original);
+
+ String b = sb.toString();
+ checkEqual(a, b);
+
+ // mutating methods
+
+ sb.setLength(12);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.setCharAt(0, 'X');
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(new Character('X'));
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append("More text");
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(sb);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(new StringBuilder("Build"));
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(new StringBuilder("Build2"), 0, 1);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(new char[] { 'a', 'b' });
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(true);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append('c');
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(23);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.appendCodePoint(Character.codePointAt(new char[] { 'X'}, 0));
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(1L);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(1.0f);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append(1.0d);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.delete(0, 5);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.deleteCharAt(0);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.replace(0,2, "123");
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, new char[] { 'a', 'b', 'c'}, 0, 3);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, new Object());
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, "abc");
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, new char[] { 'a', 'b', 'c' });
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, new StringBuilder("Build"));
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, new StringBuilder("Build"), 0, 1);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, false);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, 'X');
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, 1);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, 1L);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, 1.0f);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.insert(0, 1.0d);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.reverse();
+ b = sb.toString();
+ checkUnequal(a, b);
+
+ // non-mutating methods
+
+ // Reset to known value
+ sb = new StringBuffer(original);
+ a = sb.toString();
+ b = sb.toString();
+ checkEqual(a, b);
+
+ int l = sb.length();
+ b = sb.toString();
+ checkEqual(a, b);
+
+ int cap = sb.capacity();
+ b = sb.toString();
+ checkEqual(a, b);
+
+ sb.ensureCapacity(100);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ sb.trimToSize();
+ b = sb.toString();
+ checkEqual(a, b);
+
+ char c = sb.charAt(1);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ int cp = sb.codePointAt(1);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ cp = sb.codePointBefore(2);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ int count = sb.codePointCount(0,1);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ count = sb.offsetByCodePoints(0, 1);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ sb.getChars(0, 1, new char[2], 0);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ String sub = sb.substring(0);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ CharSequence cs = sb.subSequence(0,1);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ sub = sb.substring(0, 3);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ int index = sb.indexOf("rig");
+ b = sb.toString();
+ checkEqual(a, b);
+
+ index = sb.indexOf("rig", 2);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ index = sb.lastIndexOf("rig");
+ b = sb.toString();
+ checkEqual(a, b);
+
+ index = sb.lastIndexOf("rig", 3);
+ b = sb.toString();
+ checkEqual(a, b);
+
+ }
+
+ private static void checkEqual(String s1, String s2) {
+ if (!s1.equals(s2))
+ throw new RuntimeException("Unmatched strings: s1 = "
+ + s1 + " s2 = " + s2);
+ }
+ private static void checkUnequal(String s1, String s2) {
+ if (s1.equals(s2))
+ throw new RuntimeException("Unexpected matched strings: " + s1);
+ }
+}
diff --git a/jdk/test/java/net/HttpURLPermission/HttpURLPermissionTest.java b/jdk/test/java/net/HttpURLPermission/HttpURLPermissionTest.java
new file mode 100644
index 00000000000..c2debe7a0bd
--- /dev/null
+++ b/jdk/test/java/net/HttpURLPermission/HttpURLPermissionTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2013, 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 java.net.HttpURLPermission;
+import java.io.*;
+
+/**
+ * @test
+ * @bug 8010464
+ */
+
+public class HttpURLPermissionTest {
+
+ // super class for all test types
+ abstract static class Test {
+ boolean expected;
+ abstract boolean execute();
+ };
+
+ // Tests URL part of implies() method. This is the main test.
+ static class URLImpliesTest extends Test {
+ String arg1, arg2;
+
+ URLImpliesTest(String arg1, String arg2, boolean expected) {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ this.expected = expected;
+ }
+
+ boolean execute() {
+ HttpURLPermission p1 = new HttpURLPermission (arg1, "GET:*");
+ HttpURLPermission p2 = new HttpURLPermission (arg2, "GET:*");
+ boolean result = p1.implies(p2);
+ return result == expected;
+ }
+ };
+
+ static URLImpliesTest imtest(String arg1, String arg2, boolean expected) {
+ return new URLImpliesTest(arg1, arg2, expected);
+ }
+
+ static class ActionImpliesTest extends Test {
+ String arg1, arg2;
+
+ ActionImpliesTest(String arg1, String arg2, boolean expected) {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ this.expected = expected;
+ }
+
+ boolean execute() {
+ String url1 = "http://www.foo.com/-";
+ String url2 = "http://www.foo.com/a/b";
+ HttpURLPermission p1 = new HttpURLPermission(url1, arg1);
+ HttpURLPermission p2 = new HttpURLPermission(url2, arg2);
+ boolean result = p1.implies(p2);
+ return result == expected;
+ }
+ }
+
+ static ActionImpliesTest actest(String arg1, String arg2, boolean expected) {
+ return new ActionImpliesTest(arg1, arg2, expected);
+ }
+
+ static Test[] pathImplies = {
+ // single
+ imtest("http://www.foo.com/", "http://www.foo.com/", true),
+ imtest("http://www.bar.com/", "http://www.foo.com/", false),
+ imtest("http://www.foo.com/a/b", "http://www.foo.com/", false),
+ imtest("http://www.foo.com/a/b", "http://www.foo.com/a/b/c", false),
+ // wildcard
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/a/b/c", true),
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/a/b/*", true),
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/a/b/c#frag", true),
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/a/b/c#frag?foo=foo", true),
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/b/b/c", false),
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/a/b/c.html", true),
+ imtest("http://www.foo.com/a/b/*", "http://www.foo.com/a/b/c.html", true),
+ imtest("http://www.foo.com/a/b/*", "https://www.foo.com/a/b/c", false),
+ // recursive
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/-", true),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c", true),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c#frag", true),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c#frag?foo=foo", true),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/b/b/c", false),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c.html", true),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c.html", true),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c/d/e.html", true),
+ imtest("https://www.foo.com/a/b/-", "http://www.foo.com/a/b/c/d/e.html", false),
+ imtest("http://www.foo.com/a/b/-", "http://www.foo.com/a/b/c/d/e#frag", true),
+ imtest("http://www.foo.com/a/b/-", "https://www.foo.com/a/b/c", false),
+ // special cases
+ imtest("http:*", "https://www.foo.com/a/b/c", false),
+ imtest("http:*", "http://www.foo.com/a/b/c", true),
+ imtest("http:*", "http://foo/bar", true),
+ imtest("http://foo/bar", "https://foo/bar", false)
+ };
+
+ static Test[] actionImplies = {
+ actest("GET", "GET", true),
+ actest("GET", "POST", false),
+ actest("GET:", "PUT", false),
+ actest("GET:", "GET", true),
+ actest("GET,POST", "GET", true),
+ actest("GET,POST:", "GET", true),
+ actest("GET:X-Foo", "GET:x-foo", true),
+ actest("GET:X-Foo,X-bar", "GET:x-foo", true),
+ actest("GET:X-Foo", "GET:x-boo", false),
+ actest("GET:X-Foo,X-Bar", "GET:x-bar,x-foo", true),
+ actest("GET:X-Bar,X-Foo,X-Bar,Y-Foo", "GET:x-bar,x-foo", true),
+ actest("GET:*", "GET:x-bar,x-foo", true),
+ actest("*:*", "GET:x-bar,x-foo", true)
+ };
+
+ static boolean failed = false;
+
+ public static void main(String args[]) throws Exception {
+ for (int i=0; i set = EnumSet.range(WEEKS, FOREVER);
+ EnumSet set = EnumSet.range(DAYS, FOREVER);
INVALID_UNITS = (TemporalUnit[]) set.toArray(new TemporalUnit[set.size()]);
}
@@ -1122,14 +1122,6 @@ public class TCKLocalTime extends AbstractDateTimeTest {
}
}
- @Test
- public void test_plus_longTemporalUnit_multiples() {
- assertEquals(TEST_12_30_40_987654321.plus(0, DAYS), TEST_12_30_40_987654321);
- assertEquals(TEST_12_30_40_987654321.plus(1, DAYS), TEST_12_30_40_987654321);
- assertEquals(TEST_12_30_40_987654321.plus(2, DAYS), TEST_12_30_40_987654321);
- assertEquals(TEST_12_30_40_987654321.plus(-3, DAYS), TEST_12_30_40_987654321);
- }
-
@Test(expectedExceptions=NullPointerException.class)
public void test_plus_longTemporalUnit_null() {
TEST_12_30_40_987654321.plus(1, (TemporalUnit) null);
@@ -1556,14 +1548,6 @@ public class TCKLocalTime extends AbstractDateTimeTest {
}
}
- @Test
- public void test_minus_longTemporalUnit_long_multiples() {
- assertEquals(TEST_12_30_40_987654321.minus(0, DAYS), TEST_12_30_40_987654321);
- assertEquals(TEST_12_30_40_987654321.minus(1, DAYS), TEST_12_30_40_987654321);
- assertEquals(TEST_12_30_40_987654321.minus(2, DAYS), TEST_12_30_40_987654321);
- assertEquals(TEST_12_30_40_987654321.minus(-3, DAYS), TEST_12_30_40_987654321);
- }
-
@Test(expectedExceptions=NullPointerException.class)
public void test_minus_longTemporalUnit_null() {
TEST_12_30_40_987654321.minus(1, (TemporalUnit) null);
diff --git a/jdk/test/java/time/tck/java/time/TCKOffsetTime.java b/jdk/test/java/time/tck/java/time/TCKOffsetTime.java
index ff8ec88502e..7b97380e4de 100644
--- a/jdk/test/java/time/tck/java/time/TCKOffsetTime.java
+++ b/jdk/test/java/time/tck/java/time/TCKOffsetTime.java
@@ -75,7 +75,13 @@ import static java.time.temporal.ChronoField.NANO_OF_SECOND;
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
import static java.time.temporal.ChronoField.SECOND_OF_DAY;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
+import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.DAYS;
+import static java.time.temporal.ChronoUnit.HOURS;
+import static java.time.temporal.ChronoUnit.MINUTES;
+import static java.time.temporal.ChronoUnit.MICROS;
+import static java.time.temporal.ChronoUnit.MILLIS;
+import static java.time.temporal.ChronoUnit.HALF_DAYS;
import static java.time.temporal.ChronoUnit.NANOS;
import static java.time.temporal.ChronoUnit.SECONDS;
import static org.testng.Assert.assertEquals;
@@ -110,6 +116,7 @@ import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalField;
import java.time.temporal.TemporalQuery;
+import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -1030,6 +1037,56 @@ public class TCKOffsetTime extends AbstractDateTimeTest {
assertEquals(test, base);
}
+ //-----------------------------------------------------------------------
+ // periodUntil(Temporal, TemporalUnit)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="periodUntilUnit")
+ Object[][] data_periodUntilUnit() {
+ return new Object[][] {
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(13, 1, 1), ZoneOffset.ofHours(1)), HALF_DAYS, 1},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), HOURS, 1},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), MINUTES, 60},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), SECONDS, 3600},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), MILLIS, 3600*1000},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), MICROS, 3600*1000*1000L},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1)), NANOS, 3600*1000*1000L*1000},
+
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(14, 1, 1), ZoneOffset.ofHours(2)), HALF_DAYS, 1},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), HOURS, 1},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), MINUTES, 60},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), SECONDS, 3600},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), MILLIS, 3600*1000},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), MICROS, 3600*1000*1000L},
+ {OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1)), OffsetTime.of(LocalTime.of(3, 1, 1), ZoneOffset.ofHours(2)), NANOS, 3600*1000*1000L*1000},
+ };
+ }
+
+ @Test(dataProvider="periodUntilUnit")
+ public void test_periodUntil_TemporalUnit(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
+ long amount = offsetTime1.periodUntil(offsetTime2, unit);
+ assertEquals(amount, expected);
+ }
+
+ @Test(dataProvider="periodUntilUnit")
+ public void test_periodUntil_TemporalUnit_negated(OffsetTime offsetTime1, OffsetTime offsetTime2, TemporalUnit unit, long expected) {
+ long amount = offsetTime2.periodUntil(offsetTime1, unit);
+ assertEquals(amount, -expected);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_periodUntil_InvalidType() {
+ OffsetTime offsetTime = OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1));
+ OffsetDateTime offsetDateTime = offsetTime.atDate(LocalDate.of(1980, 2, 10));
+ offsetTime.periodUntil(offsetDateTime, SECONDS);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_periodUntil_InvalidTemporalUnit() {
+ OffsetTime offsetTime1 = OffsetTime.of(LocalTime.of(1, 1, 1), ZoneOffset.ofHours(1));
+ OffsetTime offsetTime2 = OffsetTime.of(LocalTime.of(2, 1, 1), ZoneOffset.ofHours(1));
+ offsetTime1.periodUntil(offsetTime2, MONTHS);
+ }
+
//-----------------------------------------------------------------------
// format(DateTimeFormatter)
//-----------------------------------------------------------------------
diff --git a/jdk/test/java/time/tck/java/time/TCKYear.java b/jdk/test/java/time/tck/java/time/TCKYear.java
index 570946f3239..ac25f0b4fb3 100644
--- a/jdk/test/java/time/tck/java/time/TCKYear.java
+++ b/jdk/test/java/time/tck/java/time/TCKYear.java
@@ -71,6 +71,7 @@ import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.WEEKS;
import static java.time.temporal.ChronoUnit.YEARS;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.io.ByteArrayOutputStream;
@@ -89,6 +90,7 @@ import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.time.chrono.IsoEra;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
@@ -525,6 +527,47 @@ public class TCKYear extends AbstractDateTimeTest {
Year.of(Year.MIN_VALUE).plusYears(-1000);
}
+ //-----------------------------------------------------------------------
+ // plus(long, TemporalUnit)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="plus_long_TemporalUnit")
+ Object[][] data_plus_long_TemporalUnit() {
+ return new Object[][] {
+ {Year.of(1), 1, ChronoUnit.YEARS, Year.of(2), null},
+ {Year.of(1), -12, ChronoUnit.YEARS, Year.of(-11), null},
+ {Year.of(1), 0, ChronoUnit.YEARS, Year.of(1), null},
+ {Year.of(999999999), 0, ChronoUnit.YEARS, Year.of(999999999), null},
+ {Year.of(-999999999), 0, ChronoUnit.YEARS, Year.of(-999999999), null},
+ {Year.of(0), -999999999, ChronoUnit.YEARS, Year.of(-999999999), null},
+ {Year.of(0), 999999999, ChronoUnit.YEARS, Year.of(999999999), null},
+
+ {Year.of(-1), 1, ChronoUnit.ERAS, Year.of(2), null},
+ {Year.of(5), 1, ChronoUnit.CENTURIES, Year.of(105), null},
+ {Year.of(5), 1, ChronoUnit.DECADES, Year.of(15), null},
+
+ {Year.of(999999999), 1, ChronoUnit.YEARS, null, DateTimeException.class},
+ {Year.of(-999999999), -1, ChronoUnit.YEARS, null, DateTimeException.class},
+
+ {Year.of(1), 0, ChronoUnit.DAYS, null, DateTimeException.class},
+ {Year.of(1), 0, ChronoUnit.WEEKS, null, DateTimeException.class},
+ {Year.of(1), 0, ChronoUnit.MONTHS, null, DateTimeException.class},
+ };
+ }
+
+ @Test(groups={"tck"}, dataProvider="plus_long_TemporalUnit")
+ public void test_plus_long_TemporalUnit(Year base, long amount, TemporalUnit unit, Year expectedYear, Class expectedEx) {
+ if (expectedEx == null) {
+ assertEquals(base.plus(amount, unit), expectedYear);
+ } else {
+ try {
+ Year result = base.plus(amount, unit);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
//-----------------------------------------------------------------------
// minus(Period)
//-----------------------------------------------------------------------
@@ -616,6 +659,47 @@ public class TCKYear extends AbstractDateTimeTest {
Year.of(Year.MIN_VALUE).minusYears(1000);
}
+ //-----------------------------------------------------------------------
+ // minus(long, TemporalUnit)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="minus_long_TemporalUnit")
+ Object[][] data_minus_long_TemporalUnit() {
+ return new Object[][] {
+ {Year.of(1), 1, ChronoUnit.YEARS, Year.of(0), null},
+ {Year.of(1), -12, ChronoUnit.YEARS, Year.of(13), null},
+ {Year.of(1), 0, ChronoUnit.YEARS, Year.of(1), null},
+ {Year.of(999999999), 0, ChronoUnit.YEARS, Year.of(999999999), null},
+ {Year.of(-999999999), 0, ChronoUnit.YEARS, Year.of(-999999999), null},
+ {Year.of(0), -999999999, ChronoUnit.YEARS, Year.of(999999999), null},
+ {Year.of(0), 999999999, ChronoUnit.YEARS, Year.of(-999999999), null},
+
+ {Year.of(999999999), 1, ChronoUnit.ERAS, Year.of(-999999999 + 1), null},
+ {Year.of(105), 1, ChronoUnit.CENTURIES, Year.of(5), null},
+ {Year.of(15), 1, ChronoUnit.DECADES, Year.of(5), null},
+
+ {Year.of(-999999999), 1, ChronoUnit.YEARS, null, DateTimeException.class},
+ {Year.of(1), -999999999, ChronoUnit.YEARS, null, DateTimeException.class},
+
+ {Year.of(1), 0, ChronoUnit.DAYS, null, DateTimeException.class},
+ {Year.of(1), 0, ChronoUnit.WEEKS, null, DateTimeException.class},
+ {Year.of(1), 0, ChronoUnit.MONTHS, null, DateTimeException.class},
+ };
+ }
+
+ @Test(groups={"tck"}, dataProvider="minus_long_TemporalUnit")
+ public void test_minus_long_TemporalUnit(Year base, long amount, TemporalUnit unit, Year expectedYear, Class expectedEx) {
+ if (expectedEx == null) {
+ assertEquals(base.minus(amount, unit), expectedYear);
+ } else {
+ try {
+ Year result = base.minus(amount, unit);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
//-----------------------------------------------------------------------
// adjustInto()
//-----------------------------------------------------------------------
@@ -640,6 +724,49 @@ public class TCKYear extends AbstractDateTimeTest {
test.adjustInto((LocalDate) null);
}
+ //-----------------------------------------------------------------------
+ // with(TemporalAdjuster)
+ //-----------------------------------------------------------------------
+ @Test
+ public void test_with_TemporalAdjuster() {
+ Year base = Year.of(-10);
+ for (int i = -4; i <= 2104; i++) {
+ Temporal result = base.with(Year.of(i));
+ assertEquals(result, Year.of(i));
+ }
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_with_BadTemporalAdjuster() {
+ Year test = Year.of(1);
+ test.with(LocalTime.of(18, 1, 2));
+ }
+
+ //-----------------------------------------------------------------------
+ // with(TemporalField, long)
+ //-----------------------------------------------------------------------
+ @Test(groups={"tck"})
+ public void test_with() {
+ Year base = Year.of(5);
+ Year result = base.with(ChronoField.ERA, 0);
+ assertEquals(result, base.with(IsoEra.of(0)));
+
+ int prolepticYear = IsoChronology.INSTANCE.prolepticYear(IsoEra.of(0), 5);
+ assertEquals(result.get(ChronoField.ERA), 0);
+ assertEquals(result.get(ChronoField.YEAR), prolepticYear);
+ assertEquals(result.get(ChronoField.YEAR_OF_ERA), 5);
+
+ result = base.with(ChronoField.YEAR, 10);
+ assertEquals(result.get(ChronoField.ERA), base.get(ChronoField.ERA));
+ assertEquals(result.get(ChronoField.YEAR), 10);
+ assertEquals(result.get(ChronoField.YEAR_OF_ERA), 10);
+
+ result = base.with(ChronoField.YEAR_OF_ERA, 20);
+ assertEquals(result.get(ChronoField.ERA), base.get(ChronoField.ERA));
+ assertEquals(result.get(ChronoField.YEAR), 20);
+ assertEquals(result.get(ChronoField.YEAR_OF_ERA), 20);
+ }
+
//-----------------------------------------------------------------------
// length()
//-----------------------------------------------------------------------
diff --git a/jdk/test/java/time/tck/java/time/TCKYearMonth.java b/jdk/test/java/time/tck/java/time/TCKYearMonth.java
index 8cbf6c472ca..14ccc774b27 100644
--- a/jdk/test/java/time/tck/java/time/TCKYearMonth.java
+++ b/jdk/test/java/time/tck/java/time/TCKYearMonth.java
@@ -81,6 +81,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.time.Clock;
import java.time.DateTimeException;
+import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -98,6 +99,7 @@ import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.JulianFields;
import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalField;
import java.time.temporal.TemporalQuery;
import java.time.temporal.TemporalUnit;
@@ -688,6 +690,106 @@ public class TCKYearMonth extends AbstractDateTimeTest {
test.plusMonths(-1);
}
+ //-----------------------------------------------------------------------
+ // plus(long, TemporalUnit)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="plus_long_TemporalUnit")
+ Object[][] data_plus_long_TemporalUnit() {
+ return new Object[][] {
+ {YearMonth.of(1, 10), 1, ChronoUnit.YEARS, YearMonth.of(2, 10), null},
+ {YearMonth.of(1, 10), -12, ChronoUnit.YEARS, YearMonth.of(-11, 10), null},
+ {YearMonth.of(1, 10), 0, ChronoUnit.YEARS, YearMonth.of(1, 10), null},
+ {YearMonth.of(999999999, 12), 0, ChronoUnit.YEARS, YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), 0, ChronoUnit.YEARS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 1), -999999999, ChronoUnit.YEARS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 12), 999999999, ChronoUnit.YEARS, YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 10), 1, ChronoUnit.MONTHS, YearMonth.of(1, 11), null},
+ {YearMonth.of(1, 10), -12, ChronoUnit.MONTHS, YearMonth.of(0, 10), null},
+ {YearMonth.of(1, 10), 0, ChronoUnit.MONTHS, YearMonth.of(1, 10), null},
+ {YearMonth.of(999999999, 12), 0, ChronoUnit.MONTHS, YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), 0, ChronoUnit.MONTHS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(-999999999, 2), -1, ChronoUnit.MONTHS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(999999999, 3), 9, ChronoUnit.MONTHS, YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(-1, 10), 1, ChronoUnit.ERAS, YearMonth.of(2, 10), null},
+ {YearMonth.of(5, 10), 1, ChronoUnit.CENTURIES, YearMonth.of(105, 10), null},
+ {YearMonth.of(5, 10), 1, ChronoUnit.DECADES, YearMonth.of(15, 10), null},
+
+ {YearMonth.of(999999999, 12), 1, ChronoUnit.MONTHS, null, DateTimeException.class},
+ {YearMonth.of(-999999999, 1), -1, ChronoUnit.MONTHS, null, DateTimeException.class},
+
+ {YearMonth.of(1, 1), 0, ChronoUnit.DAYS, null, DateTimeException.class},
+ {YearMonth.of(1, 1), 0, ChronoUnit.WEEKS, null, DateTimeException.class},
+ };
+ }
+
+ @Test(groups={"tck"}, dataProvider="plus_long_TemporalUnit")
+ public void test_plus_long_TemporalUnit(YearMonth base, long amount, TemporalUnit unit, YearMonth expectedYearMonth, Class expectedEx) {
+ if (expectedEx == null) {
+ assertEquals(base.plus(amount, unit), expectedYearMonth);
+ } else {
+ try {
+ YearMonth result = base.plus(amount, unit);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // plus(TemporalAmount)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="plus_TemporalAmount")
+ Object[][] data_plus_TemporalAmount() {
+ return new Object[][] {
+ {YearMonth.of(1, 1), Period.ofYears(1), YearMonth.of(2, 1), null},
+ {YearMonth.of(1, 1), Period.ofYears(-12), YearMonth.of(-11, 1), null},
+ {YearMonth.of(1, 1), Period.ofYears(0), YearMonth.of(1, 1), null},
+ {YearMonth.of(999999999, 12), Period.ofYears(0), YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), Period.ofYears(0), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 1), Period.ofYears(-999999999), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 12), Period.ofYears(999999999), YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 1), Period.ofMonths(1), YearMonth.of(1, 2), null},
+ {YearMonth.of(1, 1), Period.ofMonths(-12), YearMonth.of(0, 1), null},
+ {YearMonth.of(1, 1), Period.ofMonths(121), YearMonth.of(11, 2), null},
+ {YearMonth.of(1, 1), Period.ofMonths(0), YearMonth.of(1, 1), null},
+ {YearMonth.of(999999999, 12), Period.ofMonths(0), YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), Period.ofMonths(0), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(-999999999, 2), Period.ofMonths(-1), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(999999999, 11), Period.ofMonths(1), YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 1), Period.ofYears(1).withMonths(2), YearMonth.of(2, 3), null},
+ {YearMonth.of(1, 1), Period.ofYears(-12).withMonths(-1), YearMonth.of(-12, 12), null},
+
+ {YearMonth.of(1, 1), Period.ofMonths(2).withYears(1), YearMonth.of(2, 3), null},
+ {YearMonth.of(1, 1), Period.ofMonths(-1).withYears(-12), YearMonth.of(-12, 12), null},
+
+ {YearMonth.of(1, 1), Period.ofDays(365), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofDays(365), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofHours(365*24), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofMinutes(365*24*60), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofSeconds(365*24*3600), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofNanos(365*24*3600*1000000000), null, DateTimeException.class},
+ };
+ }
+
+ @Test(groups={"tck"}, dataProvider="plus_TemporalAmount")
+ public void test_plus_TemporalAmount(YearMonth base, TemporalAmount temporalAmount, YearMonth expectedYearMonth, Class expectedEx) {
+ if (expectedEx == null) {
+ assertEquals(base.plus(temporalAmount), expectedYearMonth);
+ } else {
+ try {
+ YearMonth result = base.plus(temporalAmount);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
//-----------------------------------------------------------------------
// minusYears()
//-----------------------------------------------------------------------
@@ -803,6 +905,106 @@ public class TCKYearMonth extends AbstractDateTimeTest {
test.minusMonths(1);
}
+ //-----------------------------------------------------------------------
+ // minus(long, TemporalUnit)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="minus_long_TemporalUnit")
+ Object[][] data_minus_long_TemporalUnit() {
+ return new Object[][] {
+ {YearMonth.of(1, 10), 1, ChronoUnit.YEARS, YearMonth.of(0, 10), null},
+ {YearMonth.of(1, 10), 12, ChronoUnit.YEARS, YearMonth.of(-11, 10), null},
+ {YearMonth.of(1, 10), 0, ChronoUnit.YEARS, YearMonth.of(1, 10), null},
+ {YearMonth.of(999999999, 12), 0, ChronoUnit.YEARS, YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), 0, ChronoUnit.YEARS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 1), 999999999, ChronoUnit.YEARS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 12), -999999999, ChronoUnit.YEARS, YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 10), 1, ChronoUnit.MONTHS, YearMonth.of(1, 9), null},
+ {YearMonth.of(1, 10), 12, ChronoUnit.MONTHS, YearMonth.of(0, 10), null},
+ {YearMonth.of(1, 10), 0, ChronoUnit.MONTHS, YearMonth.of(1, 10), null},
+ {YearMonth.of(999999999, 12), 0, ChronoUnit.MONTHS, YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), 0, ChronoUnit.MONTHS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(-999999999, 2), 1, ChronoUnit.MONTHS, YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(999999999, 11), -1, ChronoUnit.MONTHS, YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 10), 1, ChronoUnit.ERAS, YearMonth.of(0, 10), null},
+ {YearMonth.of(5, 10), 1, ChronoUnit.CENTURIES, YearMonth.of(-95, 10), null},
+ {YearMonth.of(5, 10), 1, ChronoUnit.DECADES, YearMonth.of(-5, 10), null},
+
+ {YearMonth.of(999999999, 12), -1, ChronoUnit.MONTHS, null, DateTimeException.class},
+ {YearMonth.of(-999999999, 1), 1, ChronoUnit.MONTHS, null, DateTimeException.class},
+
+ {YearMonth.of(1, 1), 0, ChronoUnit.DAYS, null, DateTimeException.class},
+ {YearMonth.of(1, 1), 0, ChronoUnit.WEEKS, null, DateTimeException.class},
+ };
+ }
+
+ @Test(groups={"tck"}, dataProvider="minus_long_TemporalUnit")
+ public void test_minus_long_TemporalUnit(YearMonth base, long amount, TemporalUnit unit, YearMonth expectedYearMonth, Class expectedEx) {
+ if (expectedEx == null) {
+ assertEquals(base.minus(amount, unit), expectedYearMonth);
+ } else {
+ try {
+ YearMonth result = base.minus(amount, unit);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // minus(TemporalAmount)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="minus_TemporalAmount")
+ Object[][] data_minus_TemporalAmount() {
+ return new Object[][] {
+ {YearMonth.of(1, 1), Period.ofYears(1), YearMonth.of(0, 1), null},
+ {YearMonth.of(1, 1), Period.ofYears(-12), YearMonth.of(13, 1), null},
+ {YearMonth.of(1, 1), Period.ofYears(0), YearMonth.of(1, 1), null},
+ {YearMonth.of(999999999, 12), Period.ofYears(0), YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), Period.ofYears(0), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 1), Period.ofYears(999999999), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(0, 12), Period.ofYears(-999999999), YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 1), Period.ofMonths(1), YearMonth.of(0, 12), null},
+ {YearMonth.of(1, 1), Period.ofMonths(-12), YearMonth.of(2, 1), null},
+ {YearMonth.of(1, 1), Period.ofMonths(121), YearMonth.of(-10, 12), null},
+ {YearMonth.of(1, 1), Period.ofMonths(0), YearMonth.of(1, 1), null},
+ {YearMonth.of(999999999, 12), Period.ofMonths(0), YearMonth.of(999999999, 12), null},
+ {YearMonth.of(-999999999, 1), Period.ofMonths(0), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(-999999999, 2), Period.ofMonths(1), YearMonth.of(-999999999, 1), null},
+ {YearMonth.of(999999999, 11), Period.ofMonths(-1), YearMonth.of(999999999, 12), null},
+
+ {YearMonth.of(1, 1), Period.ofYears(1).withMonths(2), YearMonth.of(-1, 11), null},
+ {YearMonth.of(1, 1), Period.ofYears(-12).withMonths(-1), YearMonth.of(13, 2), null},
+
+ {YearMonth.of(1, 1), Period.ofMonths(2).withYears(1), YearMonth.of(-1, 11), null},
+ {YearMonth.of(1, 1), Period.ofMonths(-1).withYears(-12), YearMonth.of(13, 2), null},
+
+ {YearMonth.of(1, 1), Period.ofDays(365), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofDays(365), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofHours(365*24), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofMinutes(365*24*60), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofSeconds(365*24*3600), null, DateTimeException.class},
+ {YearMonth.of(1, 1), Duration.ofNanos(365*24*3600*1000000000), null, DateTimeException.class},
+ };
+ }
+
+ @Test(groups={"tck"}, dataProvider="minus_TemporalAmount")
+ public void test_minus_TemporalAmount(YearMonth base, TemporalAmount temporalAmount, YearMonth expectedYearMonth, Class expectedEx) {
+ if (expectedEx == null) {
+ assertEquals(base.minus(temporalAmount), expectedYearMonth);
+ } else {
+ try {
+ YearMonth result = base.minus(temporalAmount);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
//-----------------------------------------------------------------------
// adjustInto()
//-----------------------------------------------------------------------
diff --git a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java
index 18882df474e..94f2eb52e64 100644
--- a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java
+++ b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java
@@ -73,8 +73,10 @@ import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
+import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
+import java.time.OffsetDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.JulianFields;
import java.time.temporal.TemporalAccessor;
@@ -619,6 +621,45 @@ public class TCKZoneOffset extends AbstractDateTimeTest {
assertEquals(offset2.hashCode() == offset2b.hashCode(), true);
}
+ //-----------------------------------------------------------------------
+ // adjustInto()
+ //-----------------------------------------------------------------------
+ @Test
+ public void test_adjustInto_ZonedDateTime() {
+ ZoneOffset base = ZoneOffset.ofHoursMinutesSeconds(1, 1, 1);
+ for (String zoneId : ZoneId.getAvailableZoneIds()) {
+ //Do not change offset of ZonedDateTime after adjustInto()
+ ZonedDateTime zonedDateTime_target = ZonedDateTime.of(LocalDate.of(1909, 2, 2), LocalTime.of(10, 10, 10), ZoneId.of(zoneId));
+ ZonedDateTime zonedDateTime_result = (ZonedDateTime)(base.adjustInto(zonedDateTime_target));
+ assertEquals(zonedDateTime_target.getOffset(), zonedDateTime_result.getOffset());
+
+ OffsetDateTime offsetDateTime_target = zonedDateTime_target.toOffsetDateTime();
+ OffsetDateTime offsetDateTime_result = (OffsetDateTime)(base.adjustInto(offsetDateTime_target));
+ assertEquals(base, offsetDateTime_result.getOffset());
+ }
+ }
+
+ @Test
+ public void test_adjustInto_OffsetDateTime() {
+ ZoneOffset base = ZoneOffset.ofHoursMinutesSeconds(1, 1, 1);
+ for (int i=-18; i<=18; i++) {
+ OffsetDateTime offsetDateTime_target = OffsetDateTime.of(LocalDate.of(1909, 2, 2), LocalTime.of(10, 10, 10), ZoneOffset.ofHours(i));
+ OffsetDateTime offsetDateTime_result = (OffsetDateTime)base.adjustInto(offsetDateTime_target);
+ assertEquals(base, offsetDateTime_result.getOffset());
+
+ //Do not change offset of ZonedDateTime after adjustInto()
+ ZonedDateTime zonedDateTime_target = offsetDateTime_target.toZonedDateTime();
+ ZonedDateTime zonedDateTime_result = (ZonedDateTime)(base.adjustInto(zonedDateTime_target));
+ assertEquals(zonedDateTime_target.getOffset(), zonedDateTime_result.getOffset());
+ }
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_adjustInto_dateOnly() {
+ ZoneOffset base = ZoneOffset.ofHoursMinutesSeconds(1, 1, 1);
+ base.adjustInto((LocalDate.of(1909, 2, 2)));
+ }
+
//-----------------------------------------------------------------------
// toString()
//-----------------------------------------------------------------------
diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java b/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java
index 17aadcc1cdb..0077be55315 100644
--- a/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java
+++ b/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java
@@ -162,39 +162,30 @@ public class TCKChronology {
@DataProvider(name = "calendarsystemtype")
Object[][] data_CalendarType() {
return new Object[][] {
- {HijrahChronology.INSTANCE, "islamic", "umalqura"},
- {IsoChronology.INSTANCE, "iso8601", null},
- {JapaneseChronology.INSTANCE, "japanese", null},
- {MinguoChronology.INSTANCE, "roc", null},
- {ThaiBuddhistChronology.INSTANCE, "buddhist", null},
+ {HijrahChronology.INSTANCE, "islamic-umalqura"},
+ {IsoChronology.INSTANCE, "iso8601"},
+ {JapaneseChronology.INSTANCE, "japanese"},
+ {MinguoChronology.INSTANCE, "roc"},
+ {ThaiBuddhistChronology.INSTANCE, "buddhist"},
};
}
@Test(dataProvider = "calendarsystemtype")
- public void test_getCalendarType(Chronology chrono, String calendarType, String variant) {
+ public void test_getCalendarType(Chronology chrono, String calendarType) {
String type = calendarType;
- if (variant != null) {
- type += '-';
- type += variant;
- }
assertEquals(chrono.getCalendarType(), type);
}
@Test(dataProvider = "calendarsystemtype")
- public void test_lookupLocale(Chronology chrono, String calendarType, String variant) {
+ public void test_lookupLocale(Chronology chrono, String calendarType) {
Locale.Builder builder = new Locale.Builder().setLanguage("en").setRegion("CA");
builder.setUnicodeLocaleKeyword("ca", calendarType);
- if (variant != null) {
- builder.setUnicodeLocaleKeyword("cv", variant);
- }
Locale locale = builder.build();
assertEquals(Chronology.ofLocale(locale), chrono);
}
-
/**
* Test lookup by calendarType of each chronology.
- * The calendarType is split on "-" to separate the calendar and variant.
* Verify that the calendar can be found by {@link java.time.chrono.Chronology#ofLocale}.
*/
@Test
@@ -202,15 +193,10 @@ public class TCKChronology {
// Test that all available chronologies can be successfully found using ofLocale
Set chronos = Chronology.getAvailableChronologies();
for (Chronology chrono : chronos) {
- String[] split = chrono.getCalendarType().split("-");
-
Locale.Builder builder = new Locale.Builder().setLanguage("en").setRegion("CA");
- builder.setUnicodeLocaleKeyword("ca", split[0]);
- if (split.length > 1) {
- builder.setUnicodeLocaleKeyword("cv", split[1]);
- }
+ builder.setUnicodeLocaleKeyword("ca", chrono.getCalendarType());
Locale locale = builder.build();
- assertEquals(Chronology.ofLocale(locale), chrono, "Lookup by type and variant");
+ assertEquals(Chronology.ofLocale(locale), chrono, "Lookup by type");
}
}
@@ -218,7 +204,6 @@ public class TCKChronology {
public void test_lookupLocale() {
Locale.Builder builder = new Locale.Builder().setLanguage("en").setRegion("CA");
builder.setUnicodeLocaleKeyword("ca", "xxx");
- builder.setUnicodeLocaleKeyword("cv", "yyy");
Locale locale = builder.build();
Chronology.ofLocale(locale);
diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java b/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java
index c4e44998139..e9d5fb4f1da 100644
--- a/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java
+++ b/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java
@@ -93,7 +93,6 @@ public class TCKChronologySerialization {
//-----------------------------------------------------------------------
@Test(dataProvider="calendars")
public void test_ChronoSerialization(Chronology chrono) throws Exception {
- System.out.printf(" ChronoSerialization: %s%n", chrono);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(chrono);
diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKHijrahChronology.java b/jdk/test/java/time/tck/java/time/chrono/TCKHijrahChronology.java
index 0efd1ab640a..81b3ab740ae 100644
--- a/jdk/test/java/time/tck/java/time/chrono/TCKHijrahChronology.java
+++ b/jdk/test/java/time/tck/java/time/chrono/TCKHijrahChronology.java
@@ -62,16 +62,20 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.time.Clock;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Period;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
import java.time.chrono.Era;
import java.time.chrono.HijrahChronology;
import java.time.chrono.HijrahDate;
+import java.time.chrono.HijrahEra;
import java.time.chrono.IsoChronology;
import java.time.chrono.MinguoChronology;
import java.time.chrono.MinguoDate;
@@ -119,8 +123,11 @@ public class TCKHijrahChronology {
//{HijrahChronology.INSTANCE.date(1324, 7, 3), LocalDate.of(1906, 8, 23)},
//{HijrahChronology.INSTANCE.date(1324, 7, 4), LocalDate.of(1906, 8, 24)},
//{HijrahChronology.INSTANCE.date(1325, 1, 1), LocalDate.of(1907, 2, 13)},
- {HijrahChronology.INSTANCE.date(1434, 7, 1), LocalDate.of(2013, 5, 11)},
+ {HijrahChronology.INSTANCE.date(1434, 7, 1), LocalDate.of(2013, 5, 11)},
+ {HijrahChronology.INSTANCE.date(HijrahEra.AH, 1434, 7, 1), LocalDate.of(2013, 5, 11)},
+ {HijrahChronology.INSTANCE.dateYearDay(HijrahEra.AH, 1434, 178), LocalDate.of(2013, 5, 11)},
+ {HijrahChronology.INSTANCE.dateYearDay(1434, 178), LocalDate.of(2013, 5, 11)},
//{HijrahChronology.INSTANCE.date(1500, 3, 3), LocalDate.of(2079, 1, 5)},
//{HijrahChronology.INSTANCE.date(1500, 10, 28), LocalDate.of(2079, 8, 25)},
//{HijrahChronology.INSTANCE.date(1500, 10, 29), LocalDate.of(2079, 8, 26)},
@@ -142,6 +149,26 @@ public class TCKHijrahChronology {
assertEquals(hijrahDate.get(DAY_OF_WEEK), iso.get(DAY_OF_WEEK), "Hijrah day of week should be same as ISO day of week");
}
+ @Test
+ public void test_dateNow(){
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahDate.now()) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahDate.now(ZoneId.systemDefault())) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahDate.now(Clock.systemDefaultZone())) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahDate.now(Clock.systemDefaultZone().getZone())) ;
+
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahChronology.INSTANCE.dateNow(ZoneId.systemDefault())) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahChronology.INSTANCE.dateNow(Clock.systemDefaultZone())) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(), HijrahChronology.INSTANCE.dateNow(Clock.systemDefaultZone().getZone())) ;
+
+ ZoneId zoneId = ZoneId.of("Europe/Paris");
+ assertEquals(HijrahChronology.INSTANCE.dateNow(zoneId), HijrahChronology.INSTANCE.dateNow(Clock.system(zoneId))) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(zoneId), HijrahChronology.INSTANCE.dateNow(Clock.system(zoneId).getZone())) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(zoneId), HijrahDate.now(Clock.system(zoneId))) ;
+ assertEquals(HijrahChronology.INSTANCE.dateNow(zoneId), HijrahDate.now(Clock.system(zoneId).getZone())) ;
+
+ assertEquals(HijrahChronology.INSTANCE.dateNow(ZoneId.of(ZoneOffset.UTC.getId())), HijrahChronology.INSTANCE.dateNow(Clock.systemUTC())) ;
+ }
+
@DataProvider(name="badDates")
Object[][] data_badDates() {
return new Object[][] {
diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java b/jdk/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
index cd5e859d56a..7802e5bab52 100644
--- a/jdk/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
+++ b/jdk/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
@@ -66,12 +66,15 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.time.Clock;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Period;
import java.time.Year;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
import java.time.chrono.Era;
@@ -182,6 +185,16 @@ public class TCKJapaneseChronology {
{JapaneseChronology.INSTANCE.dateYearDay(1868, 60), LocalDate.of(1868, 2, 29)},
{JapaneseChronology.INSTANCE.dateYearDay(1928, 60), LocalDate.of(1928, 2, 29)},
{JapaneseChronology.INSTANCE.dateYearDay(1912, 60), LocalDate.of(1912, 2, 29)},
+
+ {JapaneseDate.ofYearDay(1996, 60), LocalDate.of(1996, 2, 29)},
+ {JapaneseDate.ofYearDay(1868, 60), LocalDate.of(1868, 2, 29)},
+ {JapaneseDate.ofYearDay(1928, 60), LocalDate.of(1928, 2, 29)},
+ {JapaneseDate.ofYearDay(1912, 60), LocalDate.of(1912, 2, 29)},
+
+ {JapaneseChronology.INSTANCE.dateYearDay(JapaneseEra.HEISEI, 1996 - YDIFF_HEISEI, 60), LocalDate.of(1996, 2, 29)},
+ {JapaneseChronology.INSTANCE.dateYearDay(JapaneseEra.MEIJI, 1868 - YDIFF_MEIJI, 60), LocalDate.of(1868, 2, 29)},
+ {JapaneseChronology.INSTANCE.dateYearDay(JapaneseEra.SHOWA, 1928 - YDIFF_SHOWA, 60), LocalDate.of(1928, 2, 29)},
+// {JapaneseChronology.INSTANCE.dateYearDay(JapaneseEra.TAISHO, 1916 - YDIFF_TAISHO, 60), LocalDate.of(1912, 2, 29)},
};
}
@@ -195,6 +208,26 @@ public class TCKJapaneseChronology {
assertEquals(JapaneseChronology.INSTANCE.date(iso), jdate);
}
+ @Test
+ public void test_dateNow(){
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseDate.now()) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseDate.now(ZoneId.systemDefault())) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseDate.now(Clock.systemDefaultZone())) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseDate.now(Clock.systemDefaultZone().getZone())) ;
+
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseChronology.INSTANCE.dateNow(ZoneId.systemDefault())) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseChronology.INSTANCE.dateNow(Clock.systemDefaultZone())) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(), JapaneseChronology.INSTANCE.dateNow(Clock.systemDefaultZone().getZone())) ;
+
+ ZoneId zoneId = ZoneId.of("Europe/Paris");
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(zoneId), JapaneseChronology.INSTANCE.dateNow(Clock.system(zoneId))) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(zoneId), JapaneseChronology.INSTANCE.dateNow(Clock.system(zoneId).getZone())) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(zoneId), JapaneseDate.now(Clock.system(zoneId))) ;
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(zoneId), JapaneseDate.now(Clock.system(zoneId).getZone())) ;
+
+ assertEquals(JapaneseChronology.INSTANCE.dateNow(ZoneId.of(ZoneOffset.UTC.getId())), JapaneseChronology.INSTANCE.dateNow(Clock.systemUTC())) ;
+ }
+
@DataProvider(name="badDates")
Object[][] data_badDates() {
return new Object[][] {
@@ -232,8 +265,6 @@ public class TCKJapaneseChronology {
return new Object[][] {
{2, JapaneseEra.HEISEI, 1, 1 + YDIFF_HEISEI, false},
{2, JapaneseEra.HEISEI, 100, 100 + YDIFF_HEISEI, true},
- {2, JapaneseEra.HEISEI, 0, YDIFF_HEISEI, true},
- {2, JapaneseEra.HEISEI, -10, -10 + YDIFF_HEISEI, false},
{-1, JapaneseEra.MEIJI, 1, 1 + YDIFF_MEIJI, true},
{-1, JapaneseEra.MEIJI, 4, 4 + YDIFF_MEIJI, false},
diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKThaiBuddhistChronology.java b/jdk/test/java/time/tck/java/time/chrono/TCKThaiBuddhistChronology.java
index 04d9dd982ba..f6c79449638 100644
--- a/jdk/test/java/time/tck/java/time/chrono/TCKThaiBuddhistChronology.java
+++ b/jdk/test/java/time/tck/java/time/chrono/TCKThaiBuddhistChronology.java
@@ -66,12 +66,15 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.time.Clock;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Period;
import java.time.Year;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
import java.time.chrono.Era;
@@ -177,6 +180,15 @@ public class TCKThaiBuddhistChronology {
{ThaiBuddhistChronology.INSTANCE.dateYearDay(400 + YDIFF, 60), LocalDate.of(400, 2, 29)},
{ThaiBuddhistChronology.INSTANCE.dateYearDay(2000 + YDIFF, 60), LocalDate.of(2000, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.dateYearDay(ThaiBuddhistEra.BE, 1916 + YDIFF, 60), LocalDate.of(1916, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.dateYearDay(ThaiBuddhistEra.BEFORE_BE, -1907 - YDIFF, 60), LocalDate.of(1908, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.dateYearDay(ThaiBuddhistEra.BE, 2000 + YDIFF, 60), LocalDate.of(2000, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.dateYearDay(ThaiBuddhistEra.BE, 2400 + YDIFF, 60), LocalDate.of(2400, 2, 29)},
+
+ {ThaiBuddhistChronology.INSTANCE.date(ThaiBuddhistEra.BE, 1916 + YDIFF, 2, 29 ), LocalDate.of(1916, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.date(ThaiBuddhistEra.BEFORE_BE, -1907 - YDIFF, 2, 29), LocalDate.of(1908, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.date(ThaiBuddhistEra.BE, 2000 + YDIFF, 2, 29), LocalDate.of(2000, 2, 29)},
+ {ThaiBuddhistChronology.INSTANCE.date(ThaiBuddhistEra.BE, 2400 + YDIFF, 2, 29), LocalDate.of(2400, 2, 29)},
};
}
@@ -190,6 +202,26 @@ public class TCKThaiBuddhistChronology {
assertEquals(ThaiBuddhistChronology.INSTANCE.date(iso), jdate);
}
+ @Test
+ public void test_dateNow(){
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistDate.now()) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistDate.now(ZoneId.systemDefault())) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistDate.now(Clock.systemDefaultZone())) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistDate.now(Clock.systemDefaultZone().getZone())) ;
+
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistChronology.INSTANCE.dateNow(ZoneId.systemDefault())) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistChronology.INSTANCE.dateNow(Clock.systemDefaultZone())) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(), ThaiBuddhistChronology.INSTANCE.dateNow(Clock.systemDefaultZone().getZone())) ;
+
+ ZoneId zoneId = ZoneId.of("Europe/Paris");
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(zoneId), ThaiBuddhistChronology.INSTANCE.dateNow(Clock.system(zoneId))) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(zoneId), ThaiBuddhistChronology.INSTANCE.dateNow(Clock.system(zoneId).getZone())) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(zoneId), ThaiBuddhistDate.now(Clock.system(zoneId))) ;
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(zoneId), ThaiBuddhistDate.now(Clock.system(zoneId).getZone())) ;
+
+ assertEquals(ThaiBuddhistChronology.INSTANCE.dateNow(ZoneId.of(ZoneOffset.UTC.getId())), ThaiBuddhistChronology.INSTANCE.dateNow(Clock.systemUTC())) ;
+ }
+
@DataProvider(name="badDates")
Object[][] data_badDates() {
return new Object[][] {
diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java
index e8f137f963d..8e2091e9888 100644
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java
+++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java
@@ -90,7 +90,7 @@ import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
import java.time.chrono.ThaiBuddhistChronology;
import java.time.chrono.ThaiBuddhistDate;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
@@ -134,14 +134,14 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_withLocale() {
- DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
DateTimeFormatter test = base.withLocale(Locale.GERMAN);
assertEquals(test.getLocale(), Locale.GERMAN);
}
@Test(expectedExceptions=NullPointerException.class)
public void test_withLocale_null() {
- DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
base.withLocale((Locale) null);
}
@@ -192,7 +192,9 @@ public class TCKDateTimeFormatter {
.appendValue(YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).appendLiteral('-')
.appendValue(DAY_OF_MONTH).appendLiteral('-').appendValue(DAY_OF_YEAR).toFormatter();
DateTimeFormatter f = base.withResolverFields(YEAR, DAY_OF_YEAR);
- assertEquals(f.getResolverFields(), new HashSet<>(Arrays.asList(YEAR, DAY_OF_YEAR)));
+ Set expected = new HashSet<>(Arrays.asList(YEAR, DAY_OF_YEAR));
+ // Use set.equals(); testNG comparison of Collections is ordered
+ assertTrue(f.getResolverFields().equals(expected), "ResolveFields: " + f.getResolverFields());
try {
base.parse("2012-6-30-321", LocalDate::from); // wrong month/day-of-month
fail();
@@ -392,27 +394,27 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_format_TemporalAccessor_simple() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
String result = test.format(LocalDate.of(2008, 6, 30));
assertEquals(result, "ONE30");
}
@Test(expectedExceptions = DateTimeException.class)
public void test_format_TemporalAccessor_noSuchField() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.format(LocalTime.of(11, 30));
}
@Test(expectedExceptions = NullPointerException.class)
public void test_format_TemporalAccessor_null() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.format((TemporalAccessor) null);
}
//-----------------------------------------------------------------------
@Test
public void test_print_TemporalAppendable() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
StringBuilder buf = new StringBuilder();
test.formatTo(LocalDate.of(2008, 6, 30), buf);
assertEquals(buf.toString(), "ONE30");
@@ -420,21 +422,21 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=DateTimeException.class)
public void test_print_TemporalAppendable_noSuchField() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
StringBuilder buf = new StringBuilder();
test.formatTo(LocalTime.of(11, 30), buf);
}
@Test(expectedExceptions=NullPointerException.class)
public void test_print_TemporalAppendable_nullTemporal() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
StringBuilder buf = new StringBuilder();
test.formatTo((TemporalAccessor) null, buf);
}
@Test(expectedExceptions=NullPointerException.class)
public void test_print_TemporalAppendable_nullAppendable() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.formatTo(LocalDate.of(2008, 6, 30), (Appendable) null);
}
@@ -443,7 +445,7 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_parse_CharSequence() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
TemporalAccessor result = test.parse("ONE30");
assertEquals(result.isSupported(DAY_OF_MONTH), true);
assertEquals(result.getLong(DAY_OF_MONTH), 30L);
@@ -466,7 +468,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_parse_CharSequence_null() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parse((String) null);
}
@@ -475,7 +477,7 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_parse_CharSequence_ParsePosition() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(3);
TemporalAccessor result = test.parse("XXXONE30XXX", pos);
assertEquals(pos.getIndex(), 8);
@@ -523,13 +525,13 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_parse_CharSequence_ParsePosition_nullText() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parse((CharSequence) null, new ParsePosition(0));
}
@Test(expectedExceptions=NullPointerException.class)
public void test_parse_CharSequence_ParsePosition_nullParsePosition() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parse("Text", (ParsePosition) null);
}
@@ -594,7 +596,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_parse_Query_String_nullRule() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parse("30", (TemporalQuery>) null);
}
@@ -630,7 +632,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=DateTimeParseException.class)
public void test_parseBest_String_parseErrorLongText() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
try {
test.parseBest("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", ZonedDateTime::from, LocalDate::from);
} catch (DateTimeParseException ex) {
@@ -644,7 +646,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=DateTimeParseException.class)
public void test_parseBest_String_parseIncomplete() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
try {
test.parseBest("ONE30SomethingElse", ZonedDateTime::from, LocalDate::from);
} catch (DateTimeParseException ex) {
@@ -658,32 +660,32 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_parseBest_String_nullText() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parseBest((String) null, ZonedDateTime::from, LocalDate::from);
}
@Test(expectedExceptions=NullPointerException.class)
public void test_parseBest_String_nullRules() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parseBest("30", (TemporalQuery>[]) null);
}
@Test(expectedExceptions=IllegalArgumentException.class)
public void test_parseBest_String_zeroRules() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parseBest("30", new TemporalQuery>[0]);
}
@Test(expectedExceptions=IllegalArgumentException.class)
public void test_parseBest_String_oneRule() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parseBest("30", LocalDate::from);
}
//-----------------------------------------------------------------------
@Test
public void test_parseUnresolved_StringParsePosition() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(0);
TemporalAccessor result = test.parseUnresolved("ONE30XXX", pos);
assertEquals(pos.getIndex(), 5);
@@ -693,7 +695,7 @@ public class TCKDateTimeFormatter {
@Test
public void test_parseUnresolved_StringParsePosition_parseError() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(0);
TemporalAccessor result = test.parseUnresolved("ONEXXX", pos);
assertEquals(pos.getIndex(), 0);
@@ -725,20 +727,20 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_parseUnresolved_StringParsePosition_nullString() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(0);
test.parseUnresolved((String) null, pos);
}
@Test(expectedExceptions=NullPointerException.class)
public void test_parseUnresolved_StringParsePosition_nullParsePosition() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
test.parseUnresolved("ONE30", (ParsePosition) null);
}
@Test(expectedExceptions=IndexOutOfBoundsException.class)
public void test_parseUnresolved_StringParsePosition_invalidPosition() {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(6);
test.parseUnresolved("ONE30", pos);
}
@@ -747,7 +749,7 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_toFormat_format() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
String result = format.format(LocalDate.of(2008, 6, 30));
assertEquals(result, "ONE30");
@@ -755,14 +757,14 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_toFormat_format_null() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
format.format(null);
}
@Test(expectedExceptions=IllegalArgumentException.class)
public void test_toFormat_format_notTemporal() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
format.format("Not a Temporal");
}
@@ -770,7 +772,7 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_toFormat_parseObject_String() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
TemporalAccessor result = (TemporalAccessor) format.parseObject("ONE30");
assertEquals(result.isSupported(DAY_OF_MONTH), true);
@@ -779,7 +781,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=ParseException.class)
public void test_toFormat_parseObject_String_parseError() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
try {
format.parseObject("ONEXXX");
@@ -792,7 +794,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=ParseException.class)
public void test_toFormat_parseObject_String_parseErrorLongText() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
try {
format.parseObject("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
@@ -806,7 +808,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_toFormat_parseObject_String_null() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
format.parseObject((String) null);
}
@@ -814,7 +816,7 @@ public class TCKDateTimeFormatter {
//-----------------------------------------------------------------------
@Test
public void test_toFormat_parseObject_StringParsePosition() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
ParsePosition pos = new ParsePosition(0);
TemporalAccessor result = (TemporalAccessor) format.parseObject("ONE30XXX", pos);
@@ -826,7 +828,7 @@ public class TCKDateTimeFormatter {
@Test
public void test_toFormat_parseObject_StringParsePosition_parseError() throws Exception {
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
ParsePosition pos = new ParsePosition(0);
TemporalAccessor result = (TemporalAccessor) format.parseObject("ONEXXX", pos);
@@ -838,7 +840,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_toFormat_parseObject_StringParsePosition_nullString() throws Exception {
// SimpleDateFormat has this behavior
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
ParsePosition pos = new ParsePosition(0);
format.parseObject((String) null, pos);
@@ -847,7 +849,7 @@ public class TCKDateTimeFormatter {
@Test(expectedExceptions=NullPointerException.class)
public void test_toFormat_parseObject_StringParsePosition_nullParsePosition() throws Exception {
// SimpleDateFormat has this behavior
- DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
Format format = test.toFormat();
format.parseObject("ONE30", (ParsePosition) null);
}
@@ -855,7 +857,7 @@ public class TCKDateTimeFormatter {
@Test
public void test_toFormat_parseObject_StringParsePosition_invalidPosition_tooBig() throws Exception {
// SimpleDateFormat has this behavior
- DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(6);
Format test = dtf.toFormat();
assertNull(test.parseObject("ONE30", pos));
@@ -865,7 +867,7 @@ public class TCKDateTimeFormatter {
@Test
public void test_toFormat_parseObject_StringParsePosition_invalidPosition_tooSmall() throws Exception {
// SimpleDateFormat throws StringIndexOutOfBoundException
- DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
+ DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
ParsePosition pos = new ParsePosition(-1);
Format test = dtf.toFormat();
assertNull(test.parseObject("ONE30", pos));
diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java
index 3ba962ad212..f30eb9906b3 100644
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java
+++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java
@@ -63,6 +63,7 @@ import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
+import static java.time.temporal.ChronoField.INSTANT_SECONDS;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
@@ -1180,6 +1181,52 @@ public class TCKDateTimeFormatters {
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
+ @DataProvider(name="sample_isoInstant")
+ Object[][] provider_sample_isoInstant() {
+ return new Object[][]{
+ {0, 0, "1970-01-01T00:00:00Z", null},
+ {0, null, "1970-01-01T00:00:00Z", null},
+ {0, -1, null, DateTimeException.class},
+
+ {-1, 0, "1969-12-31T23:59:59Z", null},
+ {1, 0, "1970-01-01T00:00:01Z", null},
+ {60, 0, "1970-01-01T00:01:00Z", null},
+ {3600, 0, "1970-01-01T01:00:00Z", null},
+ {86400, 0, "1970-01-02T00:00:00Z", null},
+
+ {0, 1, "1970-01-01T00:00:00.000000001Z", null},
+ {0, 2, "1970-01-01T00:00:00.000000002Z", null},
+ {0, 10, "1970-01-01T00:00:00.000000010Z", null},
+ {0, 100, "1970-01-01T00:00:00.000000100Z", null},
+ };
+ }
+
+ @Test(dataProvider="sample_isoInstant")
+ public void test_print_isoInstant(
+ long instantSecs, Integer nano, String expected, Class> expectedEx) {
+ TemporalAccessor test = buildAccessorInstant(instantSecs, nano);
+ if (expectedEx == null) {
+ assertEquals(DateTimeFormatter.ISO_INSTANT.format(test), expected);
+ } else {
+ try {
+ DateTimeFormatter.ISO_INSTANT.format(test);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(expectedEx.isInstance(ex));
+ }
+ }
+ }
+
+ @Test(dataProvider="sample_isoInstant")
+ public void test_parse_isoInstant(
+ long instantSecs, Integer nano, String input, Class> invalid) {
+ if (input != null) {
+ TemporalAccessor parsed = DateTimeFormatter.ISO_INSTANT.parseUnresolved(input, new ParsePosition(0));
+ assertEquals(parsed.getLong(INSTANT_SECONDS), instantSecs);
+ assertEquals(parsed.getLong(NANO_OF_SECOND), (nano == null ? 0 : nano));
+ }
+ }
+
@Test
public void test_isoInstant_basics() {
assertEquals(DateTimeFormatter.ISO_INSTANT.getChronology(), null);
@@ -1334,6 +1381,15 @@ public class TCKDateTimeFormatters {
return mock;
}
+ private TemporalAccessor buildAccessorInstant(long instantSecs, Integer nano) {
+ MockAccessor mock = new MockAccessor();
+ mock.fields.put(INSTANT_SECONDS, instantSecs);
+ if (nano != null) {
+ mock.fields.put(NANO_OF_SECOND, (long) nano);
+ }
+ return mock;
+ }
+
private void buildCalendrical(Expected expected, String offsetId, String zoneId) {
if (offsetId != null) {
expected.add(ZoneOffset.of(offsetId));
diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java
index 8b6c1340688..9b249f19224 100644
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java
+++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java
@@ -59,6 +59,9 @@
*/
package tck.java.time.format;
+import static java.time.format.ResolverStyle.LENIENT;
+import static java.time.format.ResolverStyle.SMART;
+import static java.time.format.ResolverStyle.STRICT;
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
@@ -88,11 +91,15 @@ import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import static java.time.temporal.ChronoField.YEAR;
import static java.time.temporal.ChronoField.YEAR_OF_ERA;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
import java.time.LocalDate;
import java.time.LocalTime;
+import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
@@ -519,4 +526,350 @@ public class TCKDateTimeParseResolver {
assertEquals(accessor.query(TemporalQuery.localTime()), null);
}
+ //-----------------------------------------------------------------------
+ @DataProvider(name="resolveFourToTime")
+ Object[][] data_resolveFourToTime() {
+ return new Object[][]{
+ // merge
+ {null, 0, 0, 0, 0, LocalTime.of(0, 0, 0, 0), Period.ZERO},
+ {null, 1, 0, 0, 0, LocalTime.of(1, 0, 0, 0), Period.ZERO},
+ {null, 0, 2, 0, 0, LocalTime.of(0, 2, 0, 0), Period.ZERO},
+ {null, 0, 0, 3, 0, LocalTime.of(0, 0, 3, 0), Period.ZERO},
+ {null, 0, 0, 0, 4, LocalTime.of(0, 0, 0, 4), Period.ZERO},
+ {null, 1, 2, 3, 4, LocalTime.of(1, 2, 3, 4), Period.ZERO},
+ {null, 23, 59, 59, 123456789, LocalTime.of(23, 59, 59, 123456789), Period.ZERO},
+
+ {ResolverStyle.STRICT, 14, 59, 60, 123456789, null, null},
+ {ResolverStyle.SMART, 14, 59, 60, 123456789, null, null},
+ {ResolverStyle.LENIENT, 14, 59, 60, 123456789, LocalTime.of(15, 0, 0, 123456789), Period.ZERO},
+
+ {ResolverStyle.STRICT, 23, 59, 60, 123456789, null, null},
+ {ResolverStyle.SMART, 23, 59, 60, 123456789, null, null},
+ {ResolverStyle.LENIENT, 23, 59, 60, 123456789, LocalTime.of(0, 0, 0, 123456789), Period.ofDays(1)},
+
+ {ResolverStyle.STRICT, 24, 0, 0, 0, null, null},
+ {ResolverStyle.SMART, 24, 0, 0, 0, LocalTime.of(0, 0, 0, 0), Period.ofDays(1)},
+ {ResolverStyle.LENIENT, 24, 0, 0, 0, LocalTime.of(0, 0, 0, 0), Period.ofDays(1)},
+
+ {ResolverStyle.STRICT, 24, 1, 0, 0, null, null},
+ {ResolverStyle.SMART, 24, 1, 0, 0, null, null},
+ {ResolverStyle.LENIENT, 24, 1, 0, 0, LocalTime.of(0, 1, 0, 0), Period.ofDays(1)},
+
+ {ResolverStyle.STRICT, 25, 0, 0, 0, null, null},
+ {ResolverStyle.SMART, 25, 0, 0, 0, null, null},
+ {ResolverStyle.LENIENT, 25, 0, 0, 0, LocalTime.of(1, 0, 0, 0), Period.ofDays(1)},
+
+ {ResolverStyle.STRICT, 49, 2, 3, 4, null, null},
+ {ResolverStyle.SMART, 49, 2, 3, 4, null, null},
+ {ResolverStyle.LENIENT, 49, 2, 3, 4, LocalTime.of(1, 2, 3, 4), Period.ofDays(2)},
+
+ {ResolverStyle.STRICT, -1, 2, 3, 4, null, null},
+ {ResolverStyle.SMART, -1, 2, 3, 4, null, null},
+ {ResolverStyle.LENIENT, -1, 2, 3, 4, LocalTime.of(23, 2, 3, 4), Period.ofDays(-1)},
+
+ {ResolverStyle.STRICT, -6, 2, 3, 4, null, null},
+ {ResolverStyle.SMART, -6, 2, 3, 4, null, null},
+ {ResolverStyle.LENIENT, -6, 2, 3, 4, LocalTime.of(18, 2, 3, 4), Period.ofDays(-1)},
+
+ {ResolverStyle.STRICT, 25, 61, 61, 1_123456789, null, null},
+ {ResolverStyle.SMART, 25, 61, 61, 1_123456789, null, null},
+ {ResolverStyle.LENIENT, 25, 61, 61, 1_123456789, LocalTime.of(2, 2, 2, 123456789), Period.ofDays(1)},
+ };
+ }
+
+ @Test(dataProvider="resolveFourToTime")
+ public void test_resolveFourToTime(ResolverStyle style,
+ long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .parseDefaulting(HOUR_OF_DAY, hour)
+ .parseDefaulting(MINUTE_OF_HOUR, min)
+ .parseDefaulting(SECOND_OF_MINUTE, sec)
+ .parseDefaulting(NANO_OF_SECOND, nano).toFormatter();
+
+ ResolverStyle[] styles = (style != null ? new ResolverStyle[] {style} : ResolverStyle.values());
+ for (ResolverStyle s : styles) {
+ if (expectedTime != null) {
+ TemporalAccessor accessor = f.withResolverStyle(s).parse("");
+ assertEquals(accessor.query(TemporalQuery.localDate()), null, "ResolverStyle: " + s);
+ assertEquals(accessor.query(TemporalQuery.localTime()), expectedTime, "ResolverStyle: " + s);
+ assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), excessPeriod, "ResolverStyle: " + s);
+ } else {
+ try {
+ f.withResolverStyle(style).parse("");
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+ }
+
+ @Test(dataProvider="resolveFourToTime")
+ public void test_resolveThreeToTime(ResolverStyle style,
+ long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .parseDefaulting(HOUR_OF_DAY, hour)
+ .parseDefaulting(MINUTE_OF_HOUR, min)
+ .parseDefaulting(SECOND_OF_MINUTE, sec).toFormatter();
+
+ ResolverStyle[] styles = (style != null ? new ResolverStyle[] {style} : ResolverStyle.values());
+ for (ResolverStyle s : styles) {
+ if (expectedTime != null) {
+ TemporalAccessor accessor = f.withResolverStyle(s).parse("");
+ assertEquals(accessor.query(TemporalQuery.localDate()), null, "ResolverStyle: " + s);
+ assertEquals(accessor.query(TemporalQuery.localTime()), expectedTime.minusNanos(nano), "ResolverStyle: " + s);
+ assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), excessPeriod, "ResolverStyle: " + s);
+ } else {
+ try {
+ f.withResolverStyle(style).parse("");
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+ }
+
+ @Test(dataProvider="resolveFourToTime")
+ public void test_resolveFourToDateTime(ResolverStyle style,
+ long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .parseDefaulting(YEAR, 2012).parseDefaulting(MONTH_OF_YEAR, 6).parseDefaulting(DAY_OF_MONTH, 30)
+ .parseDefaulting(HOUR_OF_DAY, hour)
+ .parseDefaulting(MINUTE_OF_HOUR, min)
+ .parseDefaulting(SECOND_OF_MINUTE, sec)
+ .parseDefaulting(NANO_OF_SECOND, nano).toFormatter();
+
+ ResolverStyle[] styles = (style != null ? new ResolverStyle[] {style} : ResolverStyle.values());
+ if (expectedTime != null && excessPeriod != null) {
+ LocalDate expectedDate = LocalDate.of(2012, 6, 30).plus(excessPeriod);
+ for (ResolverStyle s : styles) {
+ TemporalAccessor accessor = f.withResolverStyle(s).parse("");
+ assertEquals(accessor.query(TemporalQuery.localDate()), expectedDate, "ResolverStyle: " + s);
+ assertEquals(accessor.query(TemporalQuery.localTime()), expectedTime, "ResolverStyle: " + s);
+ assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO, "ResolverStyle: " + s);
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="resolveSecondOfDay")
+ Object[][] data_resolveSecondOfDay() {
+ return new Object[][]{
+ {STRICT, 0, 0, 0},
+ {STRICT, 1, 1, 0},
+ {STRICT, 86399, 86399, 0},
+ {STRICT, -1, null, 0},
+ {STRICT, 86400, null, 0},
+
+ {SMART, 0, 0, 0},
+ {SMART, 1, 1, 0},
+ {SMART, 86399, 86399, 0},
+ {SMART, -1, null, 0},
+ {SMART, 86400, null, 0},
+
+ {LENIENT, 0, 0, 0},
+ {LENIENT, 1, 1, 0},
+ {LENIENT, 86399, 86399, 0},
+ {LENIENT, -1, 86399, -1},
+ {LENIENT, 86400, 0, 1},
+ };
+ }
+
+ @Test(dataProvider="resolveSecondOfDay")
+ public void test_resolveSecondOfDay(ResolverStyle style, long value, Integer expectedSecond, int expectedDays) {
+ String str = Long.toString(value);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(SECOND_OF_DAY).toFormatter();
+
+ if (expectedSecond != null) {
+ TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
+ assertEquals(accessor.query(TemporalQuery.localDate()), null);
+ assertEquals(accessor.query(TemporalQuery.localTime()), LocalTime.ofSecondOfDay(expectedSecond));
+ assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ofDays(expectedDays));
+ } else {
+ try {
+ f.withResolverStyle(style).parse(str);
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="resolveMinuteOfDay")
+ Object[][] data_resolveMinuteOfDay() {
+ return new Object[][]{
+ {STRICT, 0, 0, 0},
+ {STRICT, 1, 1, 0},
+ {STRICT, 1439, 1439, 0},
+ {STRICT, -1, null, 0},
+ {STRICT, 1440, null, 0},
+
+ {SMART, 0, 0, 0},
+ {SMART, 1, 1, 0},
+ {SMART, 1439, 1439, 0},
+ {SMART, -1, null, 0},
+ {SMART, 1440, null, 0},
+
+ {LENIENT, 0, 0, 0},
+ {LENIENT, 1, 1, 0},
+ {LENIENT, 1439, 1439, 0},
+ {LENIENT, -1, 1439, -1},
+ {LENIENT, 1440, 0, 1},
+ };
+ }
+
+ @Test(dataProvider="resolveMinuteOfDay")
+ public void test_resolveMinuteOfDay(ResolverStyle style, long value, Integer expectedMinute, int expectedDays) {
+ String str = Long.toString(value);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(MINUTE_OF_DAY).toFormatter();
+
+ if (expectedMinute != null) {
+ TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
+ assertEquals(accessor.query(TemporalQuery.localDate()), null);
+ assertEquals(accessor.query(TemporalQuery.localTime()), LocalTime.ofSecondOfDay(expectedMinute * 60));
+ assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ofDays(expectedDays));
+ } else {
+ try {
+ f.withResolverStyle(style).parse(str);
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="resolveClockHourOfDay")
+ Object[][] data_resolveClockHourOfDay() {
+ return new Object[][]{
+ {STRICT, 1, 1, 0},
+ {STRICT, 24, 0, 0},
+ {STRICT, 0, null, 0},
+ {STRICT, -1, null, 0},
+ {STRICT, 25, null, 0},
+
+ {SMART, 1, 1, 0},
+ {SMART, 24, 0, 0},
+ {SMART, 0, 0, 0},
+ {SMART, -1, null, 0},
+ {SMART, 25, null, 0},
+
+ {LENIENT, 1, 1, 0},
+ {LENIENT, 24, 0, 0},
+ {LENIENT, 0, 0, 0},
+ {LENIENT, -1, 23, -1},
+ {LENIENT, 25, 1, 1},
+ };
+ }
+
+ @Test(dataProvider="resolveClockHourOfDay")
+ public void test_resolveClockHourOfDay(ResolverStyle style, long value, Integer expectedHour, int expectedDays) {
+ String str = Long.toString(value);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(CLOCK_HOUR_OF_DAY).toFormatter();
+
+ if (expectedHour != null) {
+ TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
+ assertEquals(accessor.query(TemporalQuery.localDate()), null);
+ assertEquals(accessor.query(TemporalQuery.localTime()), LocalTime.of(expectedHour, 0));
+ assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ofDays(expectedDays));
+ } else {
+ try {
+ f.withResolverStyle(style).parse(str);
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="resolveClockHourOfAmPm")
+ Object[][] data_resolveClockHourOfAmPm() {
+ return new Object[][]{
+ {STRICT, 1, 1},
+ {STRICT, 12, 0},
+ {STRICT, 0, null},
+ {STRICT, -1, null},
+ {STRICT, 13, null},
+
+ {SMART, 1, 1},
+ {SMART, 12, 0},
+ {SMART, 0, 0},
+ {SMART, -1, null},
+ {SMART, 13, null},
+
+ {LENIENT, 1, 1},
+ {LENIENT, 12, 0},
+ {LENIENT, 0, 0},
+ {LENIENT, -1, -1},
+ {LENIENT, 13, 13},
+ };
+ }
+
+ @Test(dataProvider="resolveClockHourOfAmPm")
+ public void test_resolveClockHourOfAmPm(ResolverStyle style, long value, Integer expectedValue) {
+ String str = Long.toString(value);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(CLOCK_HOUR_OF_AMPM).toFormatter();
+
+ if (expectedValue != null) {
+ TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
+ assertEquals(accessor.query(TemporalQuery.localDate()), null);
+ assertEquals(accessor.query(TemporalQuery.localTime()), null);
+ assertEquals(accessor.isSupported(CLOCK_HOUR_OF_AMPM), false);
+ assertEquals(accessor.isSupported(HOUR_OF_AMPM), true);
+ assertEquals(accessor.getLong(HOUR_OF_AMPM), expectedValue.longValue());
+ } else {
+ try {
+ f.withResolverStyle(style).parse(str);
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="resolveAmPm")
+ Object[][] data_resolveAmPm() {
+ return new Object[][]{
+ {STRICT, 0, 0},
+ {STRICT, 1, 1},
+ {STRICT, -1, null},
+ {STRICT, 2, null},
+
+ {SMART, 0, 0},
+ {SMART, 1, 1},
+ {SMART, -1, null},
+ {SMART, 2, null},
+
+ {LENIENT, 0, 0},
+ {LENIENT, 1, 1},
+ {LENIENT, -1, -1},
+ {LENIENT, 2, 2},
+ };
+ }
+
+ @Test(dataProvider="resolveAmPm")
+ public void test_resolveAmPm(ResolverStyle style, long value, Integer expectedValue) {
+ String str = Long.toString(value);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(AMPM_OF_DAY).toFormatter();
+
+ if (expectedValue != null) {
+ TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
+ assertEquals(accessor.query(TemporalQuery.localDate()), null);
+ assertEquals(accessor.query(TemporalQuery.localTime()), null);
+ assertEquals(accessor.isSupported(AMPM_OF_DAY), true);
+ assertEquals(accessor.getLong(AMPM_OF_DAY), expectedValue.longValue());
+ } else {
+ try {
+ f.withResolverStyle(style).parse(str);
+ fail();
+ } catch (DateTimeParseException ex) {
+ // expected
+ }
+ }
+ }
+
}
diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatSymbols.java b/jdk/test/java/time/tck/java/time/format/TCKDecimalStyle.java
similarity index 77%
rename from jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatSymbols.java
rename to jdk/test/java/time/tck/java/time/format/TCKDecimalStyle.java
index 9deec99814e..f5a4321ad24 100644
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatSymbols.java
+++ b/jdk/test/java/time/tck/java/time/format/TCKDecimalStyle.java
@@ -61,29 +61,30 @@ package tck.java.time.format;
import static org.testng.Assert.assertEquals;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.util.Arrays;
import java.util.Locale;
+import java.util.Set;
import org.testng.annotations.Test;
/**
- * Test DateTimeFormatSymbols.
+ * Test DecimalStyle.
*/
@Test
-public class TCKDateTimeFormatSymbols {
+public class TCKDecimalStyle {
@Test
public void test_getAvailableLocales() {
- Locale[] locales = DateTimeFormatSymbols.getAvailableLocales();
- assertEquals(locales.length > 0, true);
- assertEquals(Arrays.asList(locales).contains(Locale.US), true);
+ Set locales = DecimalStyle.getAvailableLocales();
+ assertEquals(locales.size() > 0, true, "locales: " + locales);
+ assertEquals(locales.contains(Locale.US), true, "Locale.US not found in available Locales");
}
//-----------------------------------------------------------------------
@Test
public void test_of_Locale() {
- DateTimeFormatSymbols loc1 = DateTimeFormatSymbols.of(Locale.CANADA);
+ DecimalStyle loc1 = DecimalStyle.of(Locale.CANADA);
assertEquals(loc1.getZeroDigit(), '0');
assertEquals(loc1.getPositiveSign(), '+');
assertEquals(loc1.getNegativeSign(), '-');
@@ -93,7 +94,7 @@ public class TCKDateTimeFormatSymbols {
//-----------------------------------------------------------------------
@Test
public void test_STANDARD() {
- DateTimeFormatSymbols loc1 = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle loc1 = DecimalStyle.STANDARD;
assertEquals(loc1.getZeroDigit(), '0');
assertEquals(loc1.getPositiveSign(), '+');
assertEquals(loc1.getNegativeSign(), '-');
@@ -103,25 +104,25 @@ public class TCKDateTimeFormatSymbols {
//-----------------------------------------------------------------------
@Test
public void test_zeroDigit() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle base = DecimalStyle.STANDARD;
assertEquals(base.withZeroDigit('A').getZeroDigit(), 'A');
}
@Test
public void test_positiveSign() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle base = DecimalStyle.STANDARD;
assertEquals(base.withPositiveSign('A').getPositiveSign(), 'A');
}
@Test
public void test_negativeSign() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle base = DecimalStyle.STANDARD;
assertEquals(base.withNegativeSign('A').getNegativeSign(), 'A');
}
@Test
public void test_decimalSeparator() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle base = DecimalStyle.STANDARD;
assertEquals(base.withDecimalSeparator('A').getDecimalSeparator(), 'A');
}
@@ -129,7 +130,7 @@ public class TCKDateTimeFormatSymbols {
/* TBD: convertToDigit and convertNumberToI18N are package-private methods
@Test
public void test_convertToDigit_base() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle base = DecimalStyle.STANDARD;
assertEquals(base.convertToDigit('0'), 0);
assertEquals(base.convertToDigit('1'), 1);
assertEquals(base.convertToDigit('9'), 9);
@@ -139,7 +140,7 @@ public class TCKDateTimeFormatSymbols {
@Test
public void test_convertToDigit_altered() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD.withZeroDigit('A');
+ DecimalStyle base = DecimalStyle.STANDARD.withZeroDigit('A');
assertEquals(base.convertToDigit('A'), 0);
assertEquals(base.convertToDigit('B'), 1);
assertEquals(base.convertToDigit('J'), 9);
@@ -150,21 +151,21 @@ public class TCKDateTimeFormatSymbols {
//-----------------------------------------------------------------------
@Test
public void test_convertNumberToI18N_base() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle base = DecimalStyle.STANDARD;
assertEquals(base.convertNumberToI18N("134"), "134");
}
@Test
public void test_convertNumberToI18N_altered() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD.withZeroDigit('A');
+ DecimalStyle base = DecimalStyle.STANDARD.withZeroDigit('A');
assertEquals(base.convertNumberToI18N("134"), "BDE");
}
*/
//-----------------------------------------------------------------------
@Test
public void test_equalsHashCode1() {
- DateTimeFormatSymbols a = DateTimeFormatSymbols.STANDARD;
- DateTimeFormatSymbols b = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle a = DecimalStyle.STANDARD;
+ DecimalStyle b = DecimalStyle.STANDARD;
assertEquals(a.equals(b), true);
assertEquals(b.equals(a), true);
assertEquals(a.hashCode(), b.hashCode());
@@ -172,8 +173,8 @@ public class TCKDateTimeFormatSymbols {
@Test
public void test_equalsHashCode2() {
- DateTimeFormatSymbols a = DateTimeFormatSymbols.STANDARD.withZeroDigit('A');
- DateTimeFormatSymbols b = DateTimeFormatSymbols.STANDARD.withZeroDigit('A');
+ DecimalStyle a = DecimalStyle.STANDARD.withZeroDigit('A');
+ DecimalStyle b = DecimalStyle.STANDARD.withZeroDigit('A');
assertEquals(a.equals(b), true);
assertEquals(b.equals(a), true);
assertEquals(a.hashCode(), b.hashCode());
@@ -181,15 +182,15 @@ public class TCKDateTimeFormatSymbols {
@Test
public void test_equalsHashCode3() {
- DateTimeFormatSymbols a = DateTimeFormatSymbols.STANDARD.withZeroDigit('A');
- DateTimeFormatSymbols b = DateTimeFormatSymbols.STANDARD.withDecimalSeparator('A');
+ DecimalStyle a = DecimalStyle.STANDARD.withZeroDigit('A');
+ DecimalStyle b = DecimalStyle.STANDARD.withDecimalSeparator('A');
assertEquals(a.equals(b), false);
assertEquals(b.equals(a), false);
}
@Test
public void test_equalsHashCode_bad() {
- DateTimeFormatSymbols a = DateTimeFormatSymbols.STANDARD;
+ DecimalStyle a = DecimalStyle.STANDARD;
assertEquals(a.equals(""), false);
assertEquals(a.equals(null), false);
}
@@ -197,14 +198,14 @@ public class TCKDateTimeFormatSymbols {
//-----------------------------------------------------------------------
@Test
public void test_toString_base() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.STANDARD;
- assertEquals(base.toString(), "Symbols[0+-.]");
+ DecimalStyle base = DecimalStyle.STANDARD;
+ assertEquals(base.toString(), "DecimalStyle[0+-.]");
}
@Test
public void test_toString_altered() {
- DateTimeFormatSymbols base = DateTimeFormatSymbols.of(Locale.US).withZeroDigit('A').withDecimalSeparator('@');
- assertEquals(base.toString(), "Symbols[A+-@]");
+ DecimalStyle base = DecimalStyle.of(Locale.US).withZeroDigit('A').withDecimalSeparator('@');
+ assertEquals(base.toString(), "DecimalStyle[A+-@]");
}
}
diff --git a/jdk/test/java/time/tck/java/time/format/TCKInstantPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKInstantPrinterParser.java
new file mode 100644
index 00000000000..ebd90505c2a
--- /dev/null
+++ b/jdk/test/java/time/tck/java/time/format/TCKInstantPrinterParser.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2010-2013, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * * Neither the name of JSR-310 nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package tck.java.time.format;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.ResolverStyle;
+import java.time.temporal.TemporalAccessor;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Test DateTimeFormatterBuilder.appendInstant().
+ */
+@Test
+public class TCKInstantPrinterParser {
+
+ @DataProvider(name="printGrouped")
+ Object[][] data_printGrouped() {
+ return new Object[][] {
+ {0, 0, "1970-01-01T00:00:00Z"},
+
+ {-1, 0, "1969-12-31T23:59:59Z"},
+ {1, 0, "1970-01-01T00:00:01Z"},
+ {60, 0, "1970-01-01T00:01:00Z"},
+ {3600, 0, "1970-01-01T01:00:00Z"},
+ {86400, 0, "1970-01-02T00:00:00Z"},
+
+ {182, 2, "1970-01-01T00:03:02.000000002Z"},
+ {182, 20, "1970-01-01T00:03:02.000000020Z"},
+ {182, 200, "1970-01-01T00:03:02.000000200Z"},
+ {182, 2000, "1970-01-01T00:03:02.000002Z"},
+ {182, 20000, "1970-01-01T00:03:02.000020Z"},
+ {182, 200000, "1970-01-01T00:03:02.000200Z"},
+ {182, 2000000, "1970-01-01T00:03:02.002Z"},
+ {182, 20000000, "1970-01-01T00:03:02.020Z"},
+ {182, 200000000, "1970-01-01T00:03:02.200Z"},
+
+ {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"},
+ {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00Z"},
+ };
+ }
+
+ @Test(dataProvider="printGrouped")
+ public void test_print_grouped(long instantSecs, int nano, String expected) {
+ Instant instant = Instant.ofEpochSecond(instantSecs, nano);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant().toFormatter();
+ assertEquals(f.format(instant), expected);
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="printDigits")
+ Object[][] data_printDigits() {
+ return new Object[][] {
+ {-1, 0, 0, "1970-01-01T00:00:00Z"},
+ {0, 0, 0, "1970-01-01T00:00:00Z"},
+ {1, 0, 0, "1970-01-01T00:00:00.0Z"},
+ {3, 0, 0, "1970-01-01T00:00:00.000Z"},
+ {9, 0, 0, "1970-01-01T00:00:00.000000000Z"},
+
+ {-1, -1, 0, "1969-12-31T23:59:59Z"},
+ {-1, 1, 0, "1970-01-01T00:00:01Z"},
+ {-1, 60, 0, "1970-01-01T00:01:00Z"},
+ {-1, 3600, 0, "1970-01-01T01:00:00Z"},
+ {-1, 86400, 0, "1970-01-02T00:00:00Z"},
+
+ {-1, 182, 2, "1970-01-01T00:03:02.000000002Z"},
+ {-1, 182, 20, "1970-01-01T00:03:02.00000002Z"},
+ {-1, 182, 200, "1970-01-01T00:03:02.0000002Z"},
+ {-1, 182, 2000, "1970-01-01T00:03:02.000002Z"},
+ {-1, 182, 20000, "1970-01-01T00:03:02.00002Z"},
+ {-1, 182, 200000, "1970-01-01T00:03:02.0002Z"},
+ {-1, 182, 2000000, "1970-01-01T00:03:02.002Z"},
+ {-1, 182, 20000000, "1970-01-01T00:03:02.02Z"},
+ {-1, 182, 200000000, "1970-01-01T00:03:02.2Z"},
+
+ {0, 182, 2, "1970-01-01T00:03:02Z"},
+ {0, 182, 20, "1970-01-01T00:03:02Z"},
+ {0, 182, 200, "1970-01-01T00:03:02Z"},
+ {0, 182, 2000, "1970-01-01T00:03:02Z"},
+ {0, 182, 20000, "1970-01-01T00:03:02Z"},
+ {0, 182, 200000, "1970-01-01T00:03:02Z"},
+ {0, 182, 2000000, "1970-01-01T00:03:02Z"},
+ {0, 182, 20000000, "1970-01-01T00:03:02Z"},
+ {0, 182, 200000000, "1970-01-01T00:03:02Z"},
+
+ {1, 182, 2, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 20, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 200, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 2000, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 20000, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 200000, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 2000000, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 20000000, "1970-01-01T00:03:02.0Z"},
+ {1, 182, 200000000, "1970-01-01T00:03:02.2Z"},
+
+ {3, 182, 2, "1970-01-01T00:03:02.000Z"},
+ {3, 182, 20, "1970-01-01T00:03:02.000Z"},
+ {3, 182, 200, "1970-01-01T00:03:02.000Z"},
+ {3, 182, 2000, "1970-01-01T00:03:02.000Z"},
+ {3, 182, 20000, "1970-01-01T00:03:02.000Z"},
+ {3, 182, 200000, "1970-01-01T00:03:02.000Z"},
+ {3, 182, 2000000, "1970-01-01T00:03:02.002Z"},
+ {3, 182, 20000000, "1970-01-01T00:03:02.020Z"},
+ {3, 182, 200000000, "1970-01-01T00:03:02.200Z"},
+
+ {9, 182, 2, "1970-01-01T00:03:02.000000002Z"},
+ {9, 182, 20, "1970-01-01T00:03:02.000000020Z"},
+ {9, 182, 200, "1970-01-01T00:03:02.000000200Z"},
+ {9, 182, 2000, "1970-01-01T00:03:02.000002000Z"},
+ {9, 182, 20000, "1970-01-01T00:03:02.000020000Z"},
+ {9, 182, 200000, "1970-01-01T00:03:02.000200000Z"},
+ {9, 182, 2000000, "1970-01-01T00:03:02.002000000Z"},
+ {9, 182, 20000000, "1970-01-01T00:03:02.020000000Z"},
+ {9, 182, 200000000, "1970-01-01T00:03:02.200000000Z"},
+
+ {9, Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"},
+ {9, Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"},
+ };
+ }
+
+ @Test(dataProvider="printDigits")
+ public void test_print_digits(int fractionalDigits, long instantSecs, int nano, String expected) {
+ Instant instant = Instant.ofEpochSecond(instantSecs, nano);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(fractionalDigits).toFormatter();
+ assertEquals(f.format(instant), expected);
+ }
+
+ //-----------------------------------------------------------------------
+ @DataProvider(name="parseDigits")
+ Object[][] data_parse_digits() {
+ return new Object[][] {
+ {0, 0, "1970-01-01T00:00:00Z"},
+ {0, 0, "1970-01-01T00:00:00Z"},
+ {0, 0, "1970-01-01T00:00:00.0Z"},
+ {0, 0, "1970-01-01T00:00:00.000Z"},
+ {0, 0, "1970-01-01T00:00:00.000000000Z"},
+
+ {-1, 0, "1969-12-31T23:59:59Z"},
+ {1, 0, "1970-01-01T00:00:01Z"},
+ {60, 0, "1970-01-01T00:01:00Z"},
+ {3600, 0, "1970-01-01T01:00:00Z"},
+ {86400, 0, "1970-01-02T00:00:00Z"},
+
+ {182, 234000000, "1970-01-01T00:03:02.234Z"},
+ {182, 234000000, "1970-01-01T00:03:02.2340Z"},
+ {182, 234000000, "1970-01-01T00:03:02.23400Z"},
+ {182, 234000000, "1970-01-01T00:03:02.234000Z"},
+ {182, 234000000, "1970-01-01T00:03:02.234000000Z"},
+
+ {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789Z"},
+
+ {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"},
+ {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"},
+ };
+ }
+
+ @Test(dataProvider="parseDigits")
+ public void test_parse_digitsMinusOne(long instantSecs, int nano, String input) {
+ Instant expected = Instant.ofEpochSecond(instantSecs, nano);
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
+ assertEquals(f.parse(input, Instant::from), expected);
+ assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
+ assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE);
+ }
+
+ @Test(dataProvider="parseDigits")
+ public void test_parse_digitsNine(long instantSecs, int nano, String input) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(9).toFormatter();
+ if (input.charAt(input.length() - 11) == '.') {
+ Instant expected = Instant.ofEpochSecond(instantSecs, nano);
+ assertEquals(f.parse(input, Instant::from), expected);
+ assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
+ assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE);
+ } else {
+ try {
+ f.parse(input, Instant::from);
+ fail();
+ } catch (DateTimeException ex) {
+ // expected
+ }
+ }
+ }
+
+ @Test
+ public void test_parse_endOfDay() {
+ Instant expected = OffsetDateTime.of(1970, 2, 4, 0, 0, 0, 0, ZoneOffset.UTC).toInstant();
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
+ for (ResolverStyle style : ResolverStyle.values()) {
+ TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T24:00:00Z");
+ assertEquals(parsed.query(Instant::from), expected);
+ assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
+ assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE);
+ }
+ }
+
+ @Test
+ public void test_parse_leapSecond() {
+ Instant expected = OffsetDateTime.of(1970, 2, 3, 23, 59, 59, 123456789, ZoneOffset.UTC).toInstant();
+ DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
+ for (ResolverStyle style : ResolverStyle.values()) {
+ TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T23:59:60.123456789Z");
+ assertEquals(parsed.query(Instant::from), expected);
+ assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
+ assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.TRUE);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void test_appendInstant_tooSmall() {
+ new DateTimeFormatterBuilder().appendInstant(-2);
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void test_appendInstant_tooBig() {
+ new DateTimeFormatterBuilder().appendInstant(10);
+ }
+
+}
diff --git a/jdk/test/java/time/tck/java/time/format/TCKTextStyle.java b/jdk/test/java/time/tck/java/time/format/TCKTextStyle.java
index 4e80960fc2f..344a8709ca2 100644
--- a/jdk/test/java/time/tck/java/time/format/TCKTextStyle.java
+++ b/jdk/test/java/time/tck/java/time/format/TCKTextStyle.java
@@ -67,7 +67,7 @@ import java.time.format.TextStyle;
import org.testng.annotations.Test;
/**
- * Test DateTimeFormatSymbols.
+ * Test DecimalStyle.
*/
@Test
public class TCKTextStyle {
diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java b/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java
index 748b5283068..ccb1a4ca7b9 100644
--- a/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java
+++ b/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java
@@ -71,7 +71,6 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoUnit;
-import java.time.temporal.JulianFields;
import java.time.temporal.TemporalField;
import java.time.temporal.ValueRange;
import java.time.temporal.WeekFields;
@@ -161,9 +160,6 @@ public class TCKWeekFields extends AbstractTCKTest {
TemporalField dowField = week.dayOfWeek();
TemporalField womField = week.weekOfMonth();
- DayOfWeek isoDOW = day.getDayOfWeek();
- int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1;
-
for (int i = 1; i <= 15; i++) {
int actualDOW = day.get(dowField);
int actualWOM = day.get(womField);
@@ -197,9 +193,6 @@ public class TCKWeekFields extends AbstractTCKTest {
TemporalField dowField = week.dayOfWeek();
TemporalField woyField = week.weekOfYear();
- DayOfWeek isoDOW = day.getDayOfWeek();
- int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1;
-
for (int i = 1; i <= 15; i++) {
int actualDOW = day.get(dowField);
int actualWOY = day.get(woyField);
@@ -468,6 +461,28 @@ public class TCKWeekFields extends AbstractTCKTest {
@Test(dataProvider="weekFields")
public void test_parse_resolve_localizedWoWBY(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 31);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField wowbyField = week.weekOfWeekBasedYear();
+ TemporalField yowbyField = week.weekBasedYear();
+
+ for (int i = 1; i <= 60; i++) {
+ // Test that with dayOfWeek, week of year and year of week-based-year it computes the date
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(yowbyField).appendLiteral('-')
+ .appendValue(wowbyField).appendLiteral('-')
+ .appendValue(DAY_OF_WEEK).toFormatter();
+ String str = date.get(yowbyField) + "-" + date.get(wowbyField) + "-" +
+ date.get(DAY_OF_WEEK);
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date, " :: " + str + " " + i);
+
+ date = date.plusDays(1);
+ }
+ }
+
+ @Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoWBYDow(DayOfWeek firstDayOfWeek, int minDays) {
LocalDate date = LocalDate.of(2012, 12, 31);
WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
TemporalField dowField = week.dayOfWeek();
diff --git a/jdk/test/java/time/test/java/time/chrono/TestChronologyPerf.java b/jdk/test/java/time/test/java/time/chrono/TestChronologyPerf.java
index 8d73568b146..e8b3a0083b4 100644
--- a/jdk/test/java/time/test/java/time/chrono/TestChronologyPerf.java
+++ b/jdk/test/java/time/test/java/time/chrono/TestChronologyPerf.java
@@ -26,6 +26,8 @@ package test.java.time.chrono;
import java.time.Duration;
import java.time.chrono.Chronology;
+import java.time.chrono.HijrahChronology;
+import java.time.chrono.HijrahDate;
import java.time.temporal.ChronoUnit;
import java.util.Set;
@@ -42,7 +44,19 @@ public class TestChronologyPerf {
Set chronos = Chronology.getAvailableChronologies();
long end = System.nanoTime();
Duration d = Duration.of(end - start, ChronoUnit.NANOS);
- System.out.printf(" Duration of Chronology.getAvailableChronologies(): %s%n", d);
+ System.out.printf(" Cold Duration of Chronology.getAvailableChronologies(): %s%n", d);
+
+ start = System.nanoTime();
+ chronos = Chronology.getAvailableChronologies();
+ end = System.nanoTime();
+ d = Duration.of(end - start, ChronoUnit.NANOS);
+ System.out.printf(" Warm Duration of Chronology.getAvailableChronologies(): %s%n", d);
+
+ start = System.nanoTime();
+ HijrahChronology.INSTANCE.date(1434, 1, 1);
+ end = System.nanoTime();
+ d = Duration.of(end - start, ChronoUnit.NANOS);
+ System.out.printf(" Warm Duration of HijrahDate.date(1434, 1, 1): %s%n", d);
}
}
diff --git a/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java b/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java
index d387c88fd65..cfa478f488d 100644
--- a/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java
+++ b/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java
@@ -109,21 +109,20 @@ public class TestExampleCode {
}
//-----------------------------------------------------------------------
- // Data provider for Hijrah Variant names
+ // Data provider for Hijrah Type names
//-----------------------------------------------------------------------
- @DataProvider(name = "HijrahVariantNames")
+ @DataProvider(name = "HijrahTypeNames")
Object[][] data_of_ummalqura() {
return new Object[][]{
- { "Hijrah-umalqura", "islamic", "umalqura"},
+ { "Hijrah-umalqura", "islamic-umalqura"},
};
}
- @Test(dataProvider= "HijrahVariantNames")
- public void test_HijrahVariantViaLocale(String calendarId, String calendarType, String variant) {
+ @Test(dataProvider= "HijrahTypeNames")
+ public void test_HijrahTypeViaLocale(String calendarId, String calendarType) {
Locale.Builder builder = new Locale.Builder();
builder.setLanguage("en").setRegion("US");
builder.setUnicodeLocaleKeyword("ca", calendarType);
- builder.setUnicodeLocaleKeyword("cv", variant);
Locale locale = builder.build();
Chronology chrono = Chronology.ofLocale(locale);
System.out.printf(" Locale language tag: %s, Chronology ID: %s, type: %s%n",
diff --git a/jdk/test/java/time/test/java/time/chrono/TestJapaneseChronology.java b/jdk/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
new file mode 100644
index 00000000000..b87555dcb51
--- /dev/null
+++ b/jdk/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013, 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 test.java.time.chrono;
+
+import java.time.*;
+import java.time.chrono.*;
+import java.time.temporal.*;
+import java.util.List;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests for the Japanese chronology
+ */
+@Test
+public class TestJapaneseChronology {
+ private static final JapaneseChronology JAPANESE = JapaneseChronology.INSTANCE;
+ private static final Locale jaJPJP = Locale.forLanguageTag("ja-JP-u-ca-japanese");
+
+ @DataProvider(name="transitions")
+ Object[][] transitionData() {
+ return new Object[][] {
+ // Japanese era, yearOfEra, month, dayOfMonth, gregorianYear
+ { JapaneseEra.SEIREKI, Year.MIN_VALUE, 1, 1, Year.MIN_VALUE },
+ { JapaneseEra.SEIREKI, 1867, 12, 31, 1867 },
+ { JapaneseEra.MEIJI, 1, 1, 25, 1868 }, // Note: the dates of Meiji 1 to 5 are incorrect
+ { JapaneseEra.MEIJI, 6, 1, 1, 1873 },
+ // Meiji-Taisho transition isn't accurate. 1912-07-30 is the last day of Meiji
+ // and the first day of Taisho.
+ { JapaneseEra.MEIJI, 45, 7, 29, 1912 },
+ { JapaneseEra.TAISHO, 1, 7, 30, 1912 },
+ // Same for Taisho-Showa transition. 1926-12-25 is the last day of Taisho
+ // and the first day of Showa.
+ { JapaneseEra.TAISHO, 15, 12, 24, 1926 },
+ { JapaneseEra.SHOWA, 1, 12, 25, 1926 },
+ { JapaneseEra.SHOWA, 64, 1, 7, 1989 },
+ { JapaneseEra.HEISEI, 1, 1, 8, 1989 },
+ };
+ }
+
+ @DataProvider(name="day_year_data")
+ Object[][] dayYearData() {
+ return new Object[][] {
+ // Japanese era, yearOfEra, dayOfYear, month, dayOfMonth
+ { JapaneseEra.MEIJI, 45, 211, 7, 29 },
+ { JapaneseEra.TAISHO, 1, 1, 7, 30 },
+ { JapaneseEra.TAISHO, 2, 60, 3, 1 },
+ { JapaneseEra.TAISHO, 15, 358, 12, 24 },
+ { JapaneseEra.SHOWA, 1, 1, 12, 25 },
+ { JapaneseEra.SHOWA, 2, 8, 1, 8 },
+ { JapaneseEra.SHOWA, 64, 7, 1, 7 },
+ { JapaneseEra.HEISEI, 1, 1, 1, 8 },
+ { JapaneseEra.HEISEI, 2, 8, 1, 8 },
+ };
+ }
+
+ @DataProvider(name="range_data")
+ Object[][] rangeData() {
+ return new Object[][] {
+ // field, minSmallest, minLargest, maxSmallest, maxLargest
+ { ChronoField.ERA, -999, -999, 2, 2},
+ { ChronoField.YEAR_OF_ERA, -999999999, 1, 15, 999999999-1989 }, // depends on the current era
+ { ChronoField.DAY_OF_YEAR, 1, 1, 7, 366},
+ };
+ }
+
+ @DataProvider(name="invalid_dates")
+ Object[][] invalidDatesData() {
+ return new Object[][] {
+ // Japanese era, yearOfEra, month, dayOfMonth
+ { JapaneseEra.SEIREKI, Year.MIN_VALUE - 1, 1, 1 },
+ { JapaneseEra.SEIREKI, 1855, 2, 29 },
+ { JapaneseEra.SEIREKI, 1868, 1, 25 },
+ { JapaneseEra.MEIJI, 6, 2, 29 },
+ { JapaneseEra.MEIJI, 45, 7, 30 },
+ { JapaneseEra.MEIJI, 46, 1, 1 },
+ { JapaneseEra.TAISHO, 1, 7, 29 },
+ { JapaneseEra.TAISHO, 2, 2, 29 },
+ { JapaneseEra.TAISHO, 15, 12, 25 },
+ { JapaneseEra.TAISHO, 16, 1, 1 },
+ { JapaneseEra.SHOWA, 1, 12, 24 },
+ { JapaneseEra.SHOWA, 2, 2, 29 },
+ { JapaneseEra.SHOWA, 64, 1, 8 },
+ { JapaneseEra.SHOWA, 65, 1, 1 },
+ { JapaneseEra.HEISEI, 1, 1, 7 },
+ { JapaneseEra.HEISEI, 1, 2, 29 },
+ { JapaneseEra.HEISEI, Year.MAX_VALUE, 12, 31 },
+ };
+ }
+
+ @DataProvider(name="invalid_eraYear")
+ Object[][] invalidEraYearData() {
+ return new Object[][] {
+ // Japanese era, yearOfEra
+ { JapaneseEra.SEIREKI, Year.MIN_VALUE - 1 },
+ { JapaneseEra.SEIREKI, 2012 },
+ { JapaneseEra.MEIJI, -1 },
+ { JapaneseEra.MEIJI, 0 },
+ { JapaneseEra.MEIJI, 46 },
+ { JapaneseEra.TAISHO, -1 },
+ { JapaneseEra.TAISHO, 0 },
+ { JapaneseEra.TAISHO, 16 },
+ { JapaneseEra.SHOWA, -1 },
+ { JapaneseEra.SHOWA, 0 },
+ { JapaneseEra.SHOWA, 65 },
+ { JapaneseEra.HEISEI, -1 },
+ { JapaneseEra.HEISEI, 0 },
+ { JapaneseEra.HEISEI, Year.MAX_VALUE },
+ };
+ }
+
+ @DataProvider(name="invalid_day_year_data")
+ Object[][] invalidDayYearData() {
+ return new Object[][] {
+ // Japanese era, yearOfEra, dayOfYear
+ { JapaneseEra.MEIJI, 45, 240 },
+ { JapaneseEra.TAISHO, 1, 365 },
+ { JapaneseEra.TAISHO, 2, 366 },
+ { JapaneseEra.TAISHO, 15, 359 },
+ { JapaneseEra.SHOWA, 1, 8 },
+ { JapaneseEra.SHOWA, 2, 366 },
+ { JapaneseEra.SHOWA, 64, 8 },
+ { JapaneseEra.HEISEI, 1, 360 },
+ { JapaneseEra.HEISEI, 2, 366 },
+ };
+ }
+
+ @Test
+ public void test_ofLocale() {
+ // must be a singleton
+ assertEquals(Chronology.ofLocale(jaJPJP) == JAPANESE, true);
+ }
+
+ @Test(dataProvider="transitions")
+ public void test_transitions(JapaneseEra era, int yearOfEra, int month, int dayOfMonth, int gregorianYear) {
+ assertEquals(JAPANESE.prolepticYear(era, yearOfEra), gregorianYear);
+
+ JapaneseDate jdate1 = JapaneseDate.of(era, yearOfEra, month, dayOfMonth);
+ JapaneseDate jdate2 = JapaneseDate.of(gregorianYear, month, dayOfMonth);
+ assertEquals(jdate1, jdate2);
+ }
+
+ @Test(dataProvider="range_data")
+ public void test_range(ChronoField field, int minSmallest, int minLargest, int maxSmallest, int maxLargest) {
+ ValueRange range = JAPANESE.range(field);
+ assertEquals(range.getMinimum(), minSmallest);
+ assertEquals(range.getLargestMinimum(), minLargest);
+ assertEquals(range.getSmallestMaximum(), maxSmallest);
+ assertEquals(range.getMaximum(), maxLargest);
+ }
+
+ @Test(dataProvider="day_year_data")
+ public void test_firstDayOfEra(JapaneseEra era, int yearOfEra, int dayOfYear, int month, int dayOfMonth) {
+ JapaneseDate date1 = JAPANESE.dateYearDay(era, yearOfEra, dayOfYear);
+ JapaneseDate date2 = JAPANESE.date(era, yearOfEra, month, dayOfMonth);
+ assertEquals(date1, date2);
+ }
+
+ @Test(dataProvider="invalid_dates", expectedExceptions=DateTimeException.class)
+ public void test_invalidDate(JapaneseEra era, int yearOfEra, int month, int dayOfMonth) {
+ JapaneseDate jdate = JapaneseDate.of(era, yearOfEra, month, dayOfMonth);
+ System.out.printf("No DateTimeException with %s %d.%02d.%02d%n", era, yearOfEra, month, dayOfMonth);
+ }
+
+ @Test(dataProvider="invalid_eraYear", expectedExceptions=DateTimeException.class)
+ public void test_invalidEraYear(JapaneseEra era, int yearOfEra) {
+ int year = JAPANESE.prolepticYear(era, yearOfEra);
+ System.out.printf("No DateTimeException with era=%s, year=%d%n", era, yearOfEra);
+ }
+
+ @Test(dataProvider="invalid_day_year_data", expectedExceptions=DateTimeException.class)
+ public void test_invalidDayYear(JapaneseEra era, int yearOfEra, int dayOfYear) {
+ JapaneseDate date = JAPANESE.dateYearDay(era, yearOfEra, dayOfYear);
+ System.out.printf("No DateTimeException with era=%s, year=%d, dayOfYear=%d%n", era, yearOfEra, dayOfYear);
+ }
+}
diff --git a/jdk/test/java/time/test/java/time/format/AbstractTestPrinterParser.java b/jdk/test/java/time/test/java/time/format/AbstractTestPrinterParser.java
index e11a24dd0c7..023f5c190ad 100644
--- a/jdk/test/java/time/test/java/time/format/AbstractTestPrinterParser.java
+++ b/jdk/test/java/time/test/java/time/format/AbstractTestPrinterParser.java
@@ -63,7 +63,7 @@ import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
@@ -85,7 +85,7 @@ public class AbstractTestPrinterParser {
protected DateTimeFormatterBuilder builder;
protected TemporalAccessor dta;
protected Locale locale;
- protected DateTimeFormatSymbols symbols;
+ protected DecimalStyle decimalStyle;
@BeforeMethod
@@ -94,7 +94,7 @@ public class AbstractTestPrinterParser {
builder = new DateTimeFormatterBuilder();
dta = ZonedDateTime.of(LocalDateTime.of(2011, 6, 30, 12, 30, 40, 0), ZoneId.of("Europe/Paris"));
locale = Locale.ENGLISH;
- symbols = DateTimeFormatSymbols.STANDARD;
+ decimalStyle = DecimalStyle.STANDARD;
}
protected void setCaseSensitive(boolean caseSensitive) {
@@ -114,35 +114,35 @@ public class AbstractTestPrinterParser {
}
protected DateTimeFormatter getFormatter() {
- return builder.toFormatter(locale).withSymbols(symbols);
+ return builder.toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getFormatter(char c) {
- return builder.appendLiteral(c).toFormatter(locale).withSymbols(symbols);
+ return builder.appendLiteral(c).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getFormatter(String s) {
- return builder.appendLiteral(s).toFormatter(locale).withSymbols(symbols);
+ return builder.appendLiteral(s).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getFormatter(TemporalField field) {
- return builder.appendText(field).toFormatter(locale).withSymbols(symbols);
+ return builder.appendText(field).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getFormatter(TemporalField field, TextStyle style) {
- return builder.appendText(field, style).toFormatter(locale).withSymbols(symbols);
+ return builder.appendText(field, style).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getFormatter(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) {
- return builder.appendValue(field, minWidth, maxWidth, signStyle).toFormatter(locale).withSymbols(symbols);
+ return builder.appendValue(field, minWidth, maxWidth, signStyle).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getFormatter(String pattern, String noOffsetText) {
- return builder.appendOffset(pattern, noOffsetText).toFormatter(locale).withSymbols(symbols);
+ return builder.appendOffset(pattern, noOffsetText).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected DateTimeFormatter getPatternFormatter(String pattern) {
- return builder.appendPattern(pattern).toFormatter(locale).withSymbols(symbols);
+ return builder.appendPattern(pattern).toFormatter(locale).withDecimalStyle(decimalStyle);
}
protected static final TemporalAccessor EMPTY_DTA = new TemporalAccessor() {
diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java
index a96dfb6b455..540a0e89a16 100644
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java
@@ -62,7 +62,7 @@ package test.java.time.format;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static org.testng.Assert.assertSame;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
@@ -82,7 +82,7 @@ public class TestDateTimeFormatter {
new DateTimeFormatterBuilder().appendLiteral("ONE")
.appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
.toFormatter(Locale.ENGLISH)
- .withSymbols(DateTimeFormatSymbols.STANDARD);
+ .withDecimalStyle(DecimalStyle.STANDARD);
DateTimeFormatter test = base.withLocale(Locale.ENGLISH);
assertSame(test, base);
}
diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
index 432c0381f06..bdaf22be8f7 100644
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
@@ -65,13 +65,19 @@ import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
import java.text.ParsePosition;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneOffset;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.MinguoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.FormatStyle;
import java.time.format.SignStyle;
import java.time.format.TextStyle;
import java.time.temporal.Temporal;
@@ -268,7 +274,7 @@ public class TestDateTimeFormatterBuilder {
public void test_appendValueReduced() throws Exception {
builder.appendValueReduced(YEAR, 2, 2000);
DateTimeFormatter f = builder.toFormatter();
- assertEquals(f.toString(), "ReducedValue(Year,2,2000)");
+ assertEquals(f.toString(), "ReducedValue(Year,2,2,2000)");
TemporalAccessor parsed = f.parseUnresolved("12", new ParsePosition(0));
assertEquals(parsed.getLong(YEAR), 2012L);
}
@@ -277,8 +283,10 @@ public class TestDateTimeFormatterBuilder {
public void test_appendValueReduced_subsequent_parse() throws Exception {
builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValueReduced(YEAR, 2, 2000);
DateTimeFormatter f = builder.toFormatter();
- assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)ReducedValue(Year,2,2000)");
- TemporalAccessor parsed = f.parseUnresolved("123", new ParsePosition(0));
+ assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)ReducedValue(Year,2,2,2000)");
+ ParsePosition ppos = new ParsePosition(0);
+ TemporalAccessor parsed = f.parseUnresolved("123", ppos);
+ assertNotNull(parsed, "Parse failed: " + ppos.toString());
assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L);
assertEquals(parsed.getLong(YEAR), 2023L);
}
@@ -646,13 +654,13 @@ public class TestDateTimeFormatterBuilder {
{"GGGGG", "Text(Era,NARROW)"},
{"u", "Value(Year)"},
- {"uu", "ReducedValue(Year,2,2000)"},
+ {"uu", "ReducedValue(Year,2,2,2000)"},
{"uuu", "Value(Year,3,19,NORMAL)"},
{"uuuu", "Value(Year,4,19,EXCEEDS_PAD)"},
{"uuuuu", "Value(Year,5,19,EXCEEDS_PAD)"},
{"y", "Value(YearOfEra)"},
- {"yy", "ReducedValue(YearOfEra,2,2000)"},
+ {"yy", "ReducedValue(YearOfEra,2,2,2000)"},
{"yyy", "Value(YearOfEra,3,19,NORMAL)"},
{"yyyy", "Value(YearOfEra,4,19,EXCEEDS_PAD)"},
{"yyyyy", "Value(YearOfEra,5,19,EXCEEDS_PAD)"},
@@ -892,6 +900,109 @@ public class TestDateTimeFormatterBuilder {
assertEquals(test, expected);
}
+ //-----------------------------------------------------------------------
+ @DataProvider(name="localePatterns")
+ Object[][] localizedDateTimePatterns() {
+ return new Object[][] {
+ {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, yyyy h:mm:ss a z"},
+ {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "MMMM d, yyyy h:mm:ss a z"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "MMM d, yyyy h:mm:ss a"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "M/d/yy h:mm a"},
+ {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, yyyy"},
+ {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.US, "MMMM d, yyyy"},
+ {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.US, "MMM d, yyyy"},
+ {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.US, "M/d/yy"},
+ {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"},
+ {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"},
+ {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a"},
+ {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "h:mm a"},
+
+ // French Locale and ISO Chronology
+ {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM yyyy HH' h 'mm z"},
+ {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM yyyy HH:mm:ss z"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM yyyy HH:mm:ss"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/yy HH:mm"},
+ {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM yyyy"},
+ {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM yyyy"},
+ {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM yyyy"},
+ {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/yy"},
+ {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH' h 'mm z"},
+ {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"},
+ {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"},
+ {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"},
+
+ // Japanese Locale and JapaneseChronology
+ {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy'\u5e74'M'\u6708'd'\u65e5' H'\u6642'mm'\u5206'ss'\u79d2' z"},
+ {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd H:mm:ss z"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd H:mm:ss"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd H:mm"},
+ {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy'\u5e74'M'\u6708'd'\u65e5'"},
+ {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd"},
+ {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd"},
+ {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd"},
+ {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H'\u6642'mm'\u5206'ss'\u79d2' z"},
+ {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"},
+ {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"},
+ {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"},
+
+ // Chinese Local and Chronology
+ {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE ahh'\u65f6'mm'\u5206'ss'\u79d2' z"},
+ {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ahh'\u65f6'mm'\u5206'ss'\u79d2'"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d H:mm:ss"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d ah:mm"},
+ {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
+ {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
+ {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d"},
+ {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d"},
+ {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "ahh'\u65f6'mm'\u5206'ss'\u79d2' z"},
+ {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "ahh'\u65f6'mm'\u5206'ss'\u79d2'"},
+ {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "H:mm:ss"},
+ {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"},
+ };
+ }
+
+ @Test(dataProvider="localePatterns")
+ public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle,
+ Chronology chrono, Locale locale, String expected) {
+ String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale);
+ assertEquals(actual, expected, "Pattern " + convertNonAscii(actual));
+ }
+
+ @Test(expectedExceptions=java.lang.IllegalArgumentException.class)
+ public void test_getLocalizedDateTimePatternIAE() {
+ DateTimeFormatterBuilder.getLocalizedDateTimePattern(null, null, IsoChronology.INSTANCE, Locale.US);
+ }
+
+ @Test(expectedExceptions=java.lang.NullPointerException.class)
+ public void test_getLocalizedChronoNPE() {
+ DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT, FormatStyle.SHORT, null, Locale.US);
+ }
+
+ @Test(expectedExceptions=java.lang.NullPointerException.class)
+ public void test_getLocalizedLocaleNPE() {
+ DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, null);
+ }
+
+ /**
+ * Returns a string that includes non-ascii characters after expanding
+ * the non-ascii characters to their Java language \\uxxxx form.
+ * @param input an input string
+ * @return the encoded string.
+ */
+ private String convertNonAscii(String input) {
+ StringBuilder sb = new StringBuilder(input.length() * 6);
+ for (int i = 0; i < input.length(); i++) {
+ char ch = input.charAt(i);
+ if (ch < 255) {
+ sb.append(ch);
+ } else {
+ sb.append("\\u");
+ sb.append(Integer.toHexString(ch));
+ }
+ }
+ return sb.toString();
+ }
+
private static Temporal date(int y, int m, int d) {
return LocalDate.of(y, m, d);
}
diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatSymbols.java b/jdk/test/java/time/test/java/time/format/TestDecimalStyle.java
similarity index 88%
rename from jdk/test/java/time/test/java/time/format/TestDateTimeFormatSymbols.java
rename to jdk/test/java/time/test/java/time/format/TestDecimalStyle.java
index cb3932a3932..b506d547ada 100644
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatSymbols.java
+++ b/jdk/test/java/time/test/java/time/format/TestDecimalStyle.java
@@ -61,29 +61,29 @@ package test.java.time.format;
import static org.testng.Assert.assertSame;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.util.Locale;
import org.testng.annotations.Test;
/**
- * Test DateTimeFormatSymbols.
+ * Test DecimalStyle.
*/
@Test
-public class TestDateTimeFormatSymbols {
+public class TestDecimalStyle {
@Test
public void test_of_Locale_cached() {
- DateTimeFormatSymbols loc1 = DateTimeFormatSymbols.of(Locale.CANADA);
- DateTimeFormatSymbols loc2 = DateTimeFormatSymbols.of(Locale.CANADA);
+ DecimalStyle loc1 = DecimalStyle.of(Locale.CANADA);
+ DecimalStyle loc2 = DecimalStyle.of(Locale.CANADA);
assertSame(loc1, loc2);
}
//-----------------------------------------------------------------------
@Test
public void test_ofDefaultLocale_cached() {
- DateTimeFormatSymbols loc1 = DateTimeFormatSymbols.ofDefaultLocale();
- DateTimeFormatSymbols loc2 = DateTimeFormatSymbols.ofDefaultLocale();
+ DecimalStyle loc1 = DecimalStyle.ofDefaultLocale();
+ DecimalStyle loc2 = DecimalStyle.ofDefaultLocale();
assertSame(loc1, loc2);
}
diff --git a/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java b/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java
index ae940540f6c..c476772ba9b 100644
--- a/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java
+++ b/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java
@@ -82,7 +82,7 @@ import test.java.time.temporal.MockFieldValue;
public class TestFractionPrinterParser extends AbstractTestPrinterParser {
private DateTimeFormatter getFormatter(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) {
- return builder.appendFraction(field, minWidth, maxWidth, decimalPoint).toFormatter(locale).withSymbols(symbols);
+ return builder.appendFraction(field, minWidth, maxWidth, decimalPoint).toFormatter(locale).withDecimalStyle(decimalStyle);
}
//-----------------------------------------------------------------------
diff --git a/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java
index 24852eff096..49ec4d6554f 100644
--- a/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java
+++ b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java
@@ -32,7 +32,7 @@ import java.time.chrono.IsoChronology;
import java.time.chrono.JapaneseChronology;
import java.time.chrono.MinguoChronology;
import java.time.chrono.ThaiBuddhistChronology;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
@@ -129,7 +129,7 @@ public class TestNonIsoFormatter {
ChronoLocalDate> date, String expected) {
DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withChronology(chrono).withLocale(formatLocale)
- .withSymbols(DateTimeFormatSymbols.of(numberingLocale));
+ .withDecimalStyle(DecimalStyle.of(numberingLocale));
String text = dtf.format(date);
assertEquals(text, expected);
}
@@ -139,7 +139,7 @@ public class TestNonIsoFormatter {
ChronoLocalDate> expected, String text) {
DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withChronology(chrono).withLocale(formatLocale)
- .withSymbols(DateTimeFormatSymbols.of(numberingLocale));
+ .withDecimalStyle(DecimalStyle.of(numberingLocale));
TemporalAccessor temporal = dtf.parse(text);
ChronoLocalDate> date = chrono.date(temporal);
assertEquals(date, expected);
diff --git a/jdk/test/java/time/test/java/time/format/TestNumberParser.java b/jdk/test/java/time/test/java/time/format/TestNumberParser.java
index a6fc4a2ee47..3e657582185 100644
--- a/jdk/test/java/time/test/java/time/format/TestNumberParser.java
+++ b/jdk/test/java/time/test/java/time/format/TestNumberParser.java
@@ -169,7 +169,7 @@ public class TestNumberParser extends AbstractTestPrinterParser {
DateTimeFormatter dtf = getFormatter(DAY_OF_MONTH, minWidth, maxWidth, signStyle);
if (subsequentWidth > 0) {
// hacky, to reserve space
- dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols);
+ dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withDecimalStyle(decimalStyle);
}
TemporalAccessor parsed = dtf.parseUnresolved(text, ppos);
if (ppos.getErrorIndex() != -1) {
@@ -189,7 +189,7 @@ public class TestNumberParser extends AbstractTestPrinterParser {
DateTimeFormatter dtf = getFormatter(DAY_OF_WEEK, minWidth, maxWidth, signStyle);
if (subsequentWidth > 0) {
// hacky, to reserve space
- dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols);
+ dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withDecimalStyle(decimalStyle);
}
TemporalAccessor parsed = dtf.parseUnresolved(text, ppos);
if (ppos.getErrorIndex() != -1) {
@@ -326,16 +326,16 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"0", 1, 2, SignStyle.NEVER, 1, 0},
{"5", 1, 2, SignStyle.NEVER, 1, 5},
{"50", 1, 2, SignStyle.NEVER, 2, 50},
- {"500", 1, 2, SignStyle.NEVER, 2, 50},
+ {"500", 1, 2, SignStyle.NEVER, 3, 500},
{"-0", 1, 2, SignStyle.NEVER, 2, 0},
{"-5", 1, 2, SignStyle.NEVER, 2, -5},
{"-50", 1, 2, SignStyle.NEVER, 3, -50},
- {"-500", 1, 2, SignStyle.NEVER, 3, -50},
+ {"-500", 1, 2, SignStyle.NEVER, 4, -500},
{"-AAA", 1, 2, SignStyle.NEVER, 1, null},
{"+0", 1, 2, SignStyle.NEVER, 2, 0},
{"+5", 1, 2, SignStyle.NEVER, 2, 5},
{"+50", 1, 2, SignStyle.NEVER, 3, 50},
- {"+500", 1, 2, SignStyle.NEVER, 3, 50},
+ {"+500", 1, 2, SignStyle.NEVER, 4, 500},
{"+AAA", 1, 2, SignStyle.NEVER, 1, null},
{"50", 2, 2, SignStyle.NEVER, 2, 50},
{"-50", 2, 2, SignStyle.NEVER, 0, null},
@@ -345,16 +345,16 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"0", 1, 2, SignStyle.NOT_NEGATIVE, 1, 0},
{"5", 1, 2, SignStyle.NOT_NEGATIVE, 1, 5},
{"50", 1, 2, SignStyle.NOT_NEGATIVE, 2, 50},
- {"500", 1, 2, SignStyle.NOT_NEGATIVE, 2, 50},
+ {"500", 1, 2, SignStyle.NOT_NEGATIVE, 3, 500},
{"-0", 1, 2, SignStyle.NOT_NEGATIVE, 2, 0},
{"-5", 1, 2, SignStyle.NOT_NEGATIVE, 2, -5},
{"-50", 1, 2, SignStyle.NOT_NEGATIVE, 3, -50},
- {"-500", 1, 2, SignStyle.NOT_NEGATIVE, 3, -50},
+ {"-500", 1, 2, SignStyle.NOT_NEGATIVE, 4, -500},
{"-AAA", 1, 2, SignStyle.NOT_NEGATIVE, 1, null},
{"+0", 1, 2, SignStyle.NOT_NEGATIVE, 2, 0},
{"+5", 1, 2, SignStyle.NOT_NEGATIVE, 2, 5},
{"+50", 1, 2, SignStyle.NOT_NEGATIVE, 3, 50},
- {"+500", 1, 2, SignStyle.NOT_NEGATIVE, 3, 50},
+ {"+500", 1, 2, SignStyle.NOT_NEGATIVE, 4, 500},
{"+AAA", 1, 2, SignStyle.NOT_NEGATIVE, 1, null},
{"50", 2, 2, SignStyle.NOT_NEGATIVE, 2, 50},
{"-50", 2, 2, SignStyle.NOT_NEGATIVE, 0, null},
@@ -364,16 +364,16 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"0", 1, 2, SignStyle.NORMAL, 1, 0},
{"5", 1, 2, SignStyle.NORMAL, 1, 5},
{"50", 1, 2, SignStyle.NORMAL, 2, 50},
- {"500", 1, 2, SignStyle.NORMAL, 2, 50},
+ {"500", 1, 2, SignStyle.NORMAL, 3, 500},
{"-0", 1, 2, SignStyle.NORMAL, 2, 0},
{"-5", 1, 2, SignStyle.NORMAL, 2, -5},
{"-50", 1, 2, SignStyle.NORMAL, 3, -50},
- {"-500", 1, 2, SignStyle.NORMAL, 3, -50},
+ {"-500", 1, 2, SignStyle.NORMAL, 4, -500},
{"-AAA", 1, 2, SignStyle.NORMAL, 1, null},
{"+0", 1, 2, SignStyle.NORMAL, 2, 0},
{"+5", 1, 2, SignStyle.NORMAL, 2, 5},
{"+50", 1, 2, SignStyle.NORMAL, 3, 50},
- {"+500", 1, 2, SignStyle.NORMAL, 3, 50},
+ {"+500", 1, 2, SignStyle.NORMAL, 4, 500},
{"+AAA", 1, 2, SignStyle.NORMAL, 1, null},
{"50", 2, 2, SignStyle.NORMAL, 2, 50},
{"-50", 2, 2, SignStyle.NORMAL, 3, -50},
@@ -383,32 +383,32 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"0", 1, 2, SignStyle.ALWAYS, 1, 0},
{"5", 1, 2, SignStyle.ALWAYS, 1, 5},
{"50", 1, 2, SignStyle.ALWAYS, 2, 50},
- {"500", 1, 2, SignStyle.ALWAYS, 2, 50},
+ {"500", 1, 2, SignStyle.ALWAYS, 3, 500},
{"-0", 1, 2, SignStyle.ALWAYS, 2, 0},
{"-5", 1, 2, SignStyle.ALWAYS, 2, -5},
{"-50", 1, 2, SignStyle.ALWAYS, 3, -50},
- {"-500", 1, 2, SignStyle.ALWAYS, 3, -50},
+ {"-500", 1, 2, SignStyle.ALWAYS, 4, -500},
{"-AAA", 1, 2, SignStyle.ALWAYS, 1, null},
{"+0", 1, 2, SignStyle.ALWAYS, 2, 0},
{"+5", 1, 2, SignStyle.ALWAYS, 2, 5},
{"+50", 1, 2, SignStyle.ALWAYS, 3, 50},
- {"+500", 1, 2, SignStyle.ALWAYS, 3, 50},
+ {"+500", 1, 2, SignStyle.ALWAYS, 4, 500},
{"+AAA", 1, 2, SignStyle.ALWAYS, 1, null},
// exceeds pad
{"0", 1, 2, SignStyle.EXCEEDS_PAD, 1, 0},
{"5", 1, 2, SignStyle.EXCEEDS_PAD, 1, 5},
{"50", 1, 2, SignStyle.EXCEEDS_PAD, 2, 50},
- {"500", 1, 2, SignStyle.EXCEEDS_PAD, 2, 50},
+ {"500", 1, 2, SignStyle.EXCEEDS_PAD, 3, 500},
{"-0", 1, 2, SignStyle.EXCEEDS_PAD, 2, 0},
{"-5", 1, 2, SignStyle.EXCEEDS_PAD, 2, -5},
{"-50", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50},
- {"-500", 1, 2, SignStyle.EXCEEDS_PAD, 3, -50},
+ {"-500", 1, 2, SignStyle.EXCEEDS_PAD, 4, -500},
{"-AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null},
{"+0", 1, 2, SignStyle.EXCEEDS_PAD, 2, 0},
{"+5", 1, 2, SignStyle.EXCEEDS_PAD, 2, 5},
{"+50", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50},
- {"+500", 1, 2, SignStyle.EXCEEDS_PAD, 3, 50},
+ {"+500", 1, 2, SignStyle.EXCEEDS_PAD, 4, 500},
{"+AAA", 1, 2, SignStyle.EXCEEDS_PAD, 1, null},
};
}
@@ -441,9 +441,9 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"543", 1, 3, SignStyle.NEVER, 3, 543},
{"543", 2, 3, SignStyle.NEVER, 3, 543},
{"543", 3, 3, SignStyle.NEVER, 3, 543},
- {"5432", 1, 3, SignStyle.NEVER, 3, 543},
- {"5432", 2, 3, SignStyle.NEVER, 3, 543},
- {"5432", 3, 3, SignStyle.NEVER, 3, 543},
+ {"5432", 1, 3, SignStyle.NEVER, 4, 5432},
+ {"5432", 2, 3, SignStyle.NEVER, 4, 5432},
+ {"5432", 3, 3, SignStyle.NEVER, 4, 5432},
{"5AAA", 2, 3, SignStyle.NEVER, 1, 5},
// not negative
@@ -455,9 +455,9 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"543", 1, 3, SignStyle.NOT_NEGATIVE, 3, 543},
{"543", 2, 3, SignStyle.NOT_NEGATIVE, 3, 543},
{"543", 3, 3, SignStyle.NOT_NEGATIVE, 3, 543},
- {"5432", 1, 3, SignStyle.NOT_NEGATIVE, 3, 543},
- {"5432", 2, 3, SignStyle.NOT_NEGATIVE, 3, 543},
- {"5432", 3, 3, SignStyle.NOT_NEGATIVE, 3, 543},
+ {"5432", 1, 3, SignStyle.NOT_NEGATIVE, 4, 5432},
+ {"5432", 2, 3, SignStyle.NOT_NEGATIVE, 4, 5432},
+ {"5432", 3, 3, SignStyle.NOT_NEGATIVE, 4, 5432},
{"5AAA", 2, 3, SignStyle.NOT_NEGATIVE, 1, 5},
// normal
@@ -469,9 +469,9 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"543", 1, 3, SignStyle.NORMAL, 3, 543},
{"543", 2, 3, SignStyle.NORMAL, 3, 543},
{"543", 3, 3, SignStyle.NORMAL, 3, 543},
- {"5432", 1, 3, SignStyle.NORMAL, 3, 543},
- {"5432", 2, 3, SignStyle.NORMAL, 3, 543},
- {"5432", 3, 3, SignStyle.NORMAL, 3, 543},
+ {"5432", 1, 3, SignStyle.NORMAL, 4, 5432},
+ {"5432", 2, 3, SignStyle.NORMAL, 4, 5432},
+ {"5432", 3, 3, SignStyle.NORMAL, 4, 5432},
{"5AAA", 2, 3, SignStyle.NORMAL, 1, 5},
// always
@@ -483,9 +483,9 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"543", 1, 3, SignStyle.ALWAYS, 3, 543},
{"543", 2, 3, SignStyle.ALWAYS, 3, 543},
{"543", 3, 3, SignStyle.ALWAYS, 3, 543},
- {"5432", 1, 3, SignStyle.ALWAYS, 3, 543},
- {"5432", 2, 3, SignStyle.ALWAYS, 3, 543},
- {"5432", 3, 3, SignStyle.ALWAYS, 3, 543},
+ {"5432", 1, 3, SignStyle.ALWAYS, 4, 5432},
+ {"5432", 2, 3, SignStyle.ALWAYS, 4, 5432},
+ {"5432", 3, 3, SignStyle.ALWAYS, 4, 5432},
{"5AAA", 2, 3, SignStyle.ALWAYS, 1, 5},
// exceeds pad
@@ -497,9 +497,9 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"543", 1, 3, SignStyle.EXCEEDS_PAD, 3, 543},
{"543", 2, 3, SignStyle.EXCEEDS_PAD, 3, 543},
{"543", 3, 3, SignStyle.EXCEEDS_PAD, 3, 543},
- {"5432", 1, 3, SignStyle.EXCEEDS_PAD, 3, 543},
- {"5432", 2, 3, SignStyle.EXCEEDS_PAD, 3, 543},
- {"5432", 3, 3, SignStyle.EXCEEDS_PAD, 3, 543},
+ {"5432", 1, 3, SignStyle.EXCEEDS_PAD, 4, 5432},
+ {"5432", 2, 3, SignStyle.EXCEEDS_PAD, 4, 5432},
+ {"5432", 3, 3, SignStyle.EXCEEDS_PAD, 4, 5432},
{"5AAA", 2, 3, SignStyle.EXCEEDS_PAD, 1, 5},
};
}
@@ -533,8 +533,8 @@ public class TestNumberParser extends AbstractTestPrinterParser {
{"5432", 4, 54, 32},
{"5432A", 4, 54, 32},
- {"54321", 4, 54, 32},
- {"54321A", 4, 54, 32},
+ {"54321", 5, 543, 21},
+ {"54321A", 5, 543, 21},
};
}
@@ -544,7 +544,7 @@ public class TestNumberParser extends AbstractTestPrinterParser {
ParsePosition pos = new ParsePosition(0);
DateTimeFormatter f = builder
.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL)
- .appendValue(DAY_OF_MONTH, 2).toFormatter(locale).withSymbols(symbols);
+ .appendValue(DAY_OF_MONTH, 2).toFormatter(locale).withDecimalStyle(decimalStyle);
TemporalAccessor parsed = f.parseUnresolved(input, pos);
if (pos.getErrorIndex() != -1) {
assertEquals(pos.getErrorIndex(), parseLen);
diff --git a/jdk/test/java/time/test/java/time/format/TestReducedParser.java b/jdk/test/java/time/test/java/time/format/TestReducedParser.java
index b8ae45f8542..237b5b9416d 100644
--- a/jdk/test/java/time/test/java/time/format/TestReducedParser.java
+++ b/jdk/test/java/time/test/java/time/format/TestReducedParser.java
@@ -59,13 +59,18 @@
*/
package test.java.time.format;
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
+import static java.time.temporal.ChronoField.YEAR_OF_ERA;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotNull;
import java.text.ParsePosition;
import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
@@ -77,9 +82,15 @@ import org.testng.annotations.Test;
*/
@Test
public class TestReducedParser extends AbstractTestPrinterParser {
+ private static final boolean STRICT = true;
+ private static final boolean LENIENT = false;
private DateTimeFormatter getFormatter0(TemporalField field, int width, int baseValue) {
- return builder.appendValueReduced(field, width, baseValue).toFormatter(locale).withSymbols(symbols);
+ return builder.appendValueReduced(field, width, baseValue).toFormatter(locale).withDecimalStyle(decimalStyle);
+ }
+
+ private DateTimeFormatter getFormatter0(TemporalField field, int minWidth, int maxWidth, int baseValue) {
+ return builder.appendValueReduced(field, minWidth, maxWidth, baseValue).toFormatter(locale).withDecimalStyle(decimalStyle);
}
//-----------------------------------------------------------------------
@@ -109,89 +120,242 @@ public class TestReducedParser extends AbstractTestPrinterParser {
}
//-----------------------------------------------------------------------
- @DataProvider(name="Parse")
- Object[][] provider_parse() {
+ // Parse data and values that are consistent whether strict or lenient
+ // The data is the ChronoField, width, baseValue, text, startPos, endPos, value
+ //-----------------------------------------------------------------------
+ @DataProvider(name="ParseAll")
+ Object[][] provider_parseAll() {
return new Object[][] {
// negative zero
{YEAR, 1, 2010, "-0", 0, 0, null},
// general
{YEAR, 2, 2010, "Xxx12Xxx", 3, 5, 2012},
- {YEAR, 2, 2010, "12345", 0, 2, 2012},
{YEAR, 2, 2010, "12-45", 0, 2, 2012},
- // insufficient digits
- {YEAR, 2, 2010, "0", 0, 0, null},
- {YEAR, 2, 2010, "1", 0, 0, null},
- {YEAR, 2, 2010, "1", 1, 1, null},
- {YEAR, 2, 2010, "1-2", 0, 0, null},
- {YEAR, 2, 2010, "9", 0, 0, null},
-
// other junk
{YEAR, 2, 2010, "A0", 0, 0, null},
- {YEAR, 2, 2010, "0A", 0, 0, null},
{YEAR, 2, 2010, " 1", 0, 0, null},
{YEAR, 2, 2010, "-1", 0, 0, null},
{YEAR, 2, 2010, "-10", 0, 0, null},
+ {YEAR, 2, 2000, " 1", 0, 0, null},
// parse OK 1
- {YEAR, 1, 2010, "0", 0, 1, 2010},
+ {YEAR, 1, 2010, "1", 0, 1, 2011},
+ {YEAR, 1, 2010, "3", 1, 1, null},
{YEAR, 1, 2010, "9", 0, 1, 2019},
- {YEAR, 1, 2010, "10", 0, 1, 2011},
{YEAR, 1, 2005, "0", 0, 1, 2010},
{YEAR, 1, 2005, "4", 0, 1, 2014},
{YEAR, 1, 2005, "5", 0, 1, 2005},
{YEAR, 1, 2005, "9", 0, 1, 2009},
- {YEAR, 1, 2005, "10", 0, 1, 2011},
+ {YEAR, 1, 2010, "1-2", 0, 1, 2011},
// parse OK 2
{YEAR, 2, 2010, "00", 0, 2, 2100},
{YEAR, 2, 2010, "09", 0, 2, 2109},
{YEAR, 2, 2010, "10", 0, 2, 2010},
{YEAR, 2, 2010, "99", 0, 2, 2099},
- {YEAR, 2, 2010, "100", 0, 2, 2010},
// parse OK 2
{YEAR, 2, -2005, "05", 0, 2, -2005},
{YEAR, 2, -2005, "00", 0, 2, -2000},
{YEAR, 2, -2005, "99", 0, 2, -1999},
{YEAR, 2, -2005, "06", 0, 2, -1906},
- {YEAR, 2, -2005, "100", 0, 2, -1910},
- };
+
+ {YEAR, 2, -2005, "43", 0, 2, -1943},
+ };
}
- @Test(dataProvider="Parse")
- public void test_parse(TemporalField field, int width, int baseValue, String input, int pos, int parseLen, Integer parseVal) {
+ @Test(dataProvider="ParseAll")
+ public void test_parseAllStrict(TemporalField field, int width, int baseValue, String input, int pos, int parseLen, Integer parseVal) {
ParsePosition ppos = new ParsePosition(pos);
+ setStrict(true);
TemporalAccessor parsed = getFormatter0(field, width, baseValue).parseUnresolved(input, ppos);
if (ppos.getErrorIndex() != -1) {
- assertEquals(ppos.getErrorIndex(), parseLen);
+ assertEquals(ppos.getErrorIndex(), parseLen, "error case parse position");
+ assertEquals(parsed, parseVal, "unexpected parse result");
} else {
- assertEquals(ppos.getIndex(), parseLen);
+ assertEquals(ppos.getIndex(), parseLen, "parse position");
assertParsed(parsed, YEAR, parseVal != null ? (long) parseVal : null);
}
}
- @Test(dataProvider="Parse")
- public void test_parseLenient(TemporalField field, int width, int baseValue, String input, int pos, int parseLen, Integer parseVal) {
- setStrict(false);
+ @Test(dataProvider="ParseAll")
+ public void test_parseAllLenient(TemporalField field, int width, int baseValue, String input, int pos, int parseLen, Integer parseVal) {
ParsePosition ppos = new ParsePosition(pos);
+ setStrict(false);
TemporalAccessor parsed = getFormatter0(field, width, baseValue).parseUnresolved(input, ppos);
if (ppos.getErrorIndex() != -1) {
- assertEquals(ppos.getErrorIndex(), parseLen);
+ assertEquals(ppos.getErrorIndex(), parseLen, "error case parse position");
+ assertEquals(parsed, parseVal, "unexpected parse result");
} else {
- assertEquals(ppos.getIndex(), parseLen);
+ assertEquals(ppos.getIndex(), parseLen, "parse position");
assertParsed(parsed, YEAR, parseVal != null ? (long) parseVal : null);
}
}
+ //-----------------------------------------------------------------------
+ // Parse data and values in strict and lenient modes.
+ // The data is the ChronoField, minWidth, maxWidth, baseValue, text, startPos,
+ // Strict Pair(endPos, value), Lenient Pair(endPos, value)
+ //-----------------------------------------------------------------------
+ @DataProvider(name="ParseLenientSensitive")
+ Object[][] provider_parseLenientSensitive() {
+ return new Object[][] {
+ // few digits supplied
+ {YEAR, 2, 2, 2010, "3", 0, strict(0, null), lenient(1, 3)},
+ {YEAR, 2, 2, 2010, "4", 0, strict(0, null), lenient(1, 4)},
+ {YEAR, 2, 2, 2010, "5", 1, strict(1, null), lenient(1, null)},
+ {YEAR, 2, 2, 2010, "6-2", 0, strict(0, null), lenient(1, 6)},
+ {YEAR, 2, 2, 2010, "9", 0, strict(0, null), lenient(1, 9)},
+
+ // other junk
+ {YEAR, 1, 4, 2000, "7A", 0, strict(1, 2007), lenient(1, 2007)},
+ {YEAR, 2, 2, 2010, "8A", 0, strict(0, null), lenient(1, 8)},
+
+ // Negative sign cases
+ {YEAR, 2, 4, 2000, "-1", 0, strict(0, null), lenient(2, -1)},
+ {YEAR, 2, 4, 2000, "-10", 0, strict(0, null), lenient(3, -10)},
+
+ // Positive sign cases
+ {YEAR, 2, 4, 2000, "+1", 0, strict(0, null), lenient(2, 1)},
+ {YEAR, 2, 4, 2000, "+10", 0, strict(0, null), lenient(3, 2010)},
+
+ // No sign cases
+ {YEAR, 1, 1, 2005, "21", 0, strict(1, 2012), lenient(2, 21)},
+ {YEAR, 1, 2, 2010, "12", 0, strict(2, 12), lenient(2, 12)},
+ {YEAR, 1, 4, 2000, "87", 0, strict(2, 87), lenient(2, 87)},
+ {YEAR, 1, 4, 2000, "9876", 0, strict(4, 9876), lenient(4, 9876)},
+ {YEAR, 2, 2, 2010, "321", 0, strict(2, 2032), lenient(3, 321)},
+ {YEAR, 2, 4, 2010, "2", 0, strict(0, null), lenient(1, 2)},
+ {YEAR, 2, 4, 2010, "21", 0, strict(2, 2021), lenient(2, 2021)},
+ {YEAR, 2, 4, 2010, "321", 0, strict(3, 321), lenient(3, 321)},
+ {YEAR, 2, 4, 2010, "4321", 0, strict(4, 4321), lenient(4, 4321)},
+ {YEAR, 2, 4, 2010, "54321", 0, strict(4, 5432), lenient(5, 54321)},
+ {YEAR, 2, 8, 2010, "87654321", 3, strict(8, 54321), lenient(8, 54321)},
+ {YEAR, 2, 9, 2010, "987654321", 0, strict(9, 987654321), lenient(9, 987654321)},
+ {YEAR, 3, 3, 2010, "765", 0, strict(3, 2765), lenient(3, 2765)},
+ {YEAR, 3, 4, 2010, "76", 0, strict(0, null), lenient(2, 76)},
+ {YEAR, 3, 4, 2010, "765", 0, strict(3, 2765), lenient(3, 2765)},
+ {YEAR, 3, 4, 2010, "7654", 0, strict(4, 7654), lenient(4, 7654)},
+ {YEAR, 3, 4, 2010, "76543", 0, strict(4, 7654), lenient(5, 76543)},
+
+ // Negative baseValue
+ {YEAR, 2, 4, -2005, "123", 0, strict(3, 123), lenient(3, 123)},
+ };
+ }
+
+ //-----------------------------------------------------------------------
+ // Parsing tests for strict mode
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="ParseLenientSensitive")
+ public void test_parseStrict(TemporalField field, int minWidth, int maxWidth, int baseValue, String input, int pos,
+ Pair strict, Pair lenient) {
+ ParsePosition ppos = new ParsePosition(pos);
+ setStrict(true);
+ TemporalAccessor parsed = getFormatter0(field, minWidth, maxWidth, baseValue).parseUnresolved(input, ppos);
+ if (ppos.getErrorIndex() != -1) {
+ assertEquals(ppos.getErrorIndex(), strict.parseLen, "error case parse position");
+ assertEquals(parsed, strict.parseVal, "unexpected parse result");
+ } else {
+ assertEquals(ppos.getIndex(), strict.parseLen, "parse position");
+ assertParsed(parsed, YEAR, strict.parseVal != null ? (long) strict.parseVal : null);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // Parsing tests for lenient mode
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="ParseLenientSensitive")
+ public void test_parseLenient(TemporalField field, int minWidth, int maxWidth, int baseValue, String input, int pos,
+ Pair strict, Pair lenient) {
+ ParsePosition ppos = new ParsePosition(pos);
+ setStrict(false);
+ TemporalAccessor parsed = getFormatter0(field, minWidth, maxWidth, baseValue).parseUnresolved(input, ppos);
+ if (ppos.getErrorIndex() != -1) {
+ assertEquals(ppos.getErrorIndex(), lenient.parseLen, "error case parse position");
+ assertEquals(parsed, lenient.parseVal, "unexpected parse result");
+ } else {
+ assertEquals(ppos.getIndex(), lenient.parseLen, "parse position");
+ assertParsed(parsed, YEAR, lenient.parseVal != null ? (long) lenient.parseVal : null);
+ }
+ }
+
private void assertParsed(TemporalAccessor parsed, TemporalField field, Long value) {
if (value == null) {
- assertEquals(parsed, null);
+ assertEquals(parsed, null, "Parsed Value");
} else {
- assertEquals(parsed.isSupported(field), true);
- assertEquals(parsed.getLong(field), (long) value);
+ assertEquals(parsed.isSupported(field), true, "isSupported: " + field);
+ assertEquals(parsed.getLong(field), (long) value, "Temporal.getLong: " + field);
+ }
+ }
+
+
+ //-----------------------------------------------------------------------
+ // Cases and values in adjacent parsing mode
+ //-----------------------------------------------------------------------
+ @DataProvider(name="ParseAdjacent")
+ Object[][] provider_parseAdjacent() {
+ return new Object[][] {
+ // general
+ {"yyMMdd", "19990703", LENIENT, 0, 8, 1999, 7, 3},
+ {"yyMMdd", "19990703", STRICT, 0, 6, 2019, 99, 7},
+ {"yyMMdd", "990703", LENIENT, 0, 6, 2099, 7, 3},
+ {"yyMMdd", "990703", STRICT, 0, 6, 2099, 7, 3},
+ {"yyMMdd", "200703", LENIENT, 0, 6, 2020, 7, 3},
+ {"yyMMdd", "200703", STRICT, 0, 6, 2020, 7, 3},
+ {"ddMMyy", "230714", LENIENT, 0, 6, 2014, 7, 23},
+ {"ddMMyy", "230714", STRICT, 0, 6, 2014, 7, 23},
+ {"ddMMyy", "25062001", LENIENT, 0, 8, 2001, 20, 2506},
+ {"ddMMyy", "25062001", STRICT, 0, 6, 2020, 6, 25},
+ {"ddMMy", "27052002", LENIENT, 0, 8, 2002, 5, 27},
+ {"ddMMy", "27052002", STRICT, 0, 8, 2002, 5, 27},
+ };
+ }
+
+ @Test(dataProvider="ParseAdjacent")
+ public void test_parseAdjacent(String pattern, String input, boolean strict, int pos, int parseLen, int year, int month, int day) {
+ ParsePosition ppos = new ParsePosition(0);
+ builder = new DateTimeFormatterBuilder();
+ setStrict(strict);
+ builder.appendPattern(pattern);
+ DateTimeFormatter dtf = builder.toFormatter();
+
+ TemporalAccessor parsed = dtf.parseUnresolved(input, ppos);
+ assertNotNull(parsed, String.format("parse failed: ppos: %s, formatter: %s%n", ppos.toString(), dtf));
+ if (ppos.getErrorIndex() != -1) {
+ assertEquals(ppos.getErrorIndex(), parseLen, "error case parse position");
+ } else {
+ assertEquals(ppos.getIndex(), parseLen, "parse position");
+ assertParsed(parsed, YEAR_OF_ERA, Long.valueOf(year));
+ assertParsed(parsed, MONTH_OF_YEAR, Long.valueOf(month));
+ assertParsed(parsed, DAY_OF_MONTH, Long.valueOf(day));
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // Class to structure the test data
+ //-----------------------------------------------------------------------
+
+ private static Pair strict(int parseLen, Integer parseVal) {
+ return new Pair(parseLen, parseVal, STRICT);
+ }
+ private static Pair lenient(int parseLen, Integer parseVal) {
+ return new Pair(parseLen, parseVal, LENIENT);
+ }
+
+ private static class Pair {
+ public final int parseLen;
+ public final Integer parseVal;
+ private final boolean strict;
+ public Pair(int parseLen, Integer parseVal, boolean strict) {
+ this.parseLen = parseLen;
+ this.parseVal = parseVal;
+ this.strict = strict;
+ }
+ public String toString() {
+ return (strict ? "strict" : "lenient") + "(" + parseLen + "," + parseVal + ")";
}
}
diff --git a/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java b/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java
index b213b80fece..5ff2cd5eed8 100644
--- a/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java
+++ b/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java
@@ -59,6 +59,7 @@
*/
package test.java.time.format;
+import java.text.ParsePosition;
import static java.time.temporal.ChronoField.YEAR;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
@@ -66,6 +67,11 @@ import static org.testng.Assert.fail;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.ChronoField.YEAR_OF_ERA;
+import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import org.testng.annotations.DataProvider;
@@ -79,7 +85,11 @@ import test.java.time.temporal.MockFieldValue;
public class TestReducedPrinter extends AbstractTestPrinterParser {
private DateTimeFormatter getFormatter0(TemporalField field, int width, int baseValue) {
- return builder.appendValueReduced(field, width, baseValue).toFormatter(locale).withSymbols(symbols);
+ return builder.appendValueReduced(field, width, baseValue).toFormatter(locale).withDecimalStyle(decimalStyle);
+ }
+
+ private DateTimeFormatter getFormatter0(TemporalField field, int minWidth, int maxWidth, int baseValue) {
+ return builder.appendValueReduced(field, minWidth, maxWidth, baseValue).toFormatter(locale).withDecimalStyle(decimalStyle);
}
//-----------------------------------------------------------------------
@@ -99,66 +109,76 @@ public class TestReducedPrinter extends AbstractTestPrinterParser {
@DataProvider(name="Pivot")
Object[][] provider_pivot() {
return new Object[][] {
- {1, 2010, 2010, "0"},
- {1, 2010, 2011, "1"},
- {1, 2010, 2012, "2"},
- {1, 2010, 2013, "3"},
- {1, 2010, 2014, "4"},
- {1, 2010, 2015, "5"},
- {1, 2010, 2016, "6"},
- {1, 2010, 2017, "7"},
- {1, 2010, 2018, "8"},
- {1, 2010, 2019, "9"},
- {1, 2010, 2009, "9"},
- {1, 2010, 2020, "0"},
+ {1, 1, 2010, 2010, "0"},
+ {1, 1, 2010, 2011, "1"},
+ {1, 1, 2010, 2012, "2"},
+ {1, 1, 2010, 2013, "3"},
+ {1, 1, 2010, 2014, "4"},
+ {1, 1, 2010, 2015, "5"},
+ {1, 1, 2010, 2016, "6"},
+ {1, 1, 2010, 2017, "7"},
+ {1, 1, 2010, 2018, "8"},
+ {1, 1, 2010, 2019, "9"},
+ {1, 1, 2010, 2009, "9"},
+ {1, 1, 2010, 2020, "0"},
- {2, 2010, 2010, "10"},
- {2, 2010, 2011, "11"},
- {2, 2010, 2021, "21"},
- {2, 2010, 2099, "99"},
- {2, 2010, 2100, "00"},
- {2, 2010, 2109, "09"},
- {2, 2010, 2009, "09"},
- {2, 2010, 2110, "10"},
+ {2, 2, 2010, 2010, "10"},
+ {2, 2, 2010, 2011, "11"},
+ {2, 2, 2010, 2021, "21"},
+ {2, 2, 2010, 2099, "99"},
+ {2, 2, 2010, 2100, "00"},
+ {2, 2, 2010, 2109, "09"},
+ {2, 2, 2010, 2009, "09"},
+ {2, 2, 2010, 2110, "10"},
- {2, 2005, 2005, "05"},
- {2, 2005, 2099, "99"},
- {2, 2005, 2100, "00"},
- {2, 2005, 2104, "04"},
- {2, 2005, 2004, "04"},
- {2, 2005, 2105, "05"},
+ {2, 2, 2005, 2005, "05"},
+ {2, 2, 2005, 2099, "99"},
+ {2, 2, 2005, 2100, "00"},
+ {2, 2, 2005, 2104, "04"},
+ {2, 2, 2005, 2004, "04"},
+ {2, 2, 2005, 2105, "05"},
- {3, 2005, 2005, "005"},
- {3, 2005, 2099, "099"},
- {3, 2005, 2100, "100"},
- {3, 2005, 2999, "999"},
- {3, 2005, 3000, "000"},
- {3, 2005, 3004, "004"},
- {3, 2005, 2004, "004"},
- {3, 2005, 3005, "005"},
+ {3, 3, 2005, 2005, "005"},
+ {3, 3, 2005, 2099, "099"},
+ {3, 3, 2005, 2100, "100"},
+ {3, 3, 2005, 2999, "999"},
+ {3, 3, 2005, 3000, "000"},
+ {3, 3, 2005, 3004, "004"},
+ {3, 3, 2005, 2004, "004"},
+ {3, 3, 2005, 3005, "005"},
- {9, 2005, 2005, "000002005"},
- {9, 2005, 2099, "000002099"},
- {9, 2005, 2100, "000002100"},
- {9, 2005, 999999999, "999999999"},
- {9, 2005, 1000000000, "000000000"},
- {9, 2005, 1000002004, "000002004"},
- {9, 2005, 2004, "000002004"},
- {9, 2005, 1000002005, "000002005"},
+ {9, 9, 2005, 2005, "000002005"},
+ {9, 9, 2005, 2099, "000002099"},
+ {9, 9, 2005, 2100, "000002100"},
+ {9, 9, 2005, 999999999, "999999999"},
+ {9, 9, 2005, 1000000000, "000000000"},
+ {9, 9, 2005, 1000002004, "000002004"},
+ {9, 9, 2005, 2004, "000002004"},
+ {9, 9, 2005, 1000002005, "000002005"},
- {2, -2005, -2005, "05"},
- {2, -2005, -2000, "00"},
- {2, -2005, -1999, "99"},
- {2, -2005, -1904, "04"},
- {2, -2005, -2006, "06"},
- {2, -2005, -1905, "05"},
- };
+ {2, 2, -2005, -2005, "05"},
+ {2, 2, -2005, -2000, "00"},
+ {2, 2, -2005, -1999, "99"},
+ {2, 2, -2005, -1904, "04"},
+ {2, 2, -2005, -2006, "06"},
+ {2, 2, -2005, -1905, "05"},
+
+ {2, 4, 2005, 2099, "99"},
+ {2, 4, 2005, 2100, "00"},
+ {2, 4, 2005, 9999, "9999"},
+ {2, 4, 2005, 1000000000, "00"},
+ {2, 4, 2005, 1000002004, "2004"},
+ {2, 4, 2005, 2004, "2004"},
+ {2, 4, 2005, 2005, "05"},
+ {2, 4, 2005, 2104, "04"},
+ {2, 4, 2005, 2105, "2105"},
+ };
}
@Test(dataProvider="Pivot")
- public void test_pivot(int width, int baseValue, int value, String result) throws Exception {
+ public void test_pivot(int minWidth, int maxWidth, int baseValue, int value, String result) throws Exception {
try {
- getFormatter0(YEAR, width, baseValue).formatTo(new MockFieldValue(YEAR, value), buf);
+ getFormatter0(YEAR, minWidth, maxWidth, baseValue).formatTo(new MockFieldValue(YEAR, value), buf);
if (result == null) {
fail("Expected exception");
}
@@ -174,7 +194,34 @@ public class TestReducedPrinter extends AbstractTestPrinterParser {
//-----------------------------------------------------------------------
public void test_toString() throws Exception {
- assertEquals(getFormatter0(YEAR, 2, 2005).toString(), "ReducedValue(Year,2,2005)");
+ assertEquals(getFormatter0(YEAR, 2, 2, 2005).toString(), "ReducedValue(Year,2,2,2005)");
+ }
+
+ //-----------------------------------------------------------------------
+ // Cases and values in adjacent parsing mode
+ //-----------------------------------------------------------------------
+ @DataProvider(name="PrintAdjacent")
+ Object[][] provider_printAdjacent() {
+ return new Object[][] {
+ // general
+ {"yyMMdd", "990703", 1999, 7, 3},
+ {"yyMMdd", "990703", 2099, 7, 3},
+ {"yyMMdd", "200703", 2020, 7, 3},
+ {"ddMMyy", "030714", 2014, 7, 3},
+ {"ddMMyy", "030720", 2020, 7, 3},
+ {"ddMMy", "03072001", 2001, 7, 3},
+ };
+ }
+
+ @Test(dataProvider="PrintAdjacent")
+ public void test_printAdjacent(String pattern, String text, int year, int month, int day) {
+ builder = new DateTimeFormatterBuilder();
+ builder.appendPattern(pattern);
+ DateTimeFormatter dtf = builder.toFormatter();
+
+ LocalDate ld = LocalDate.of(year, month, day);
+ String actual = dtf.format(ld);
+ assertEquals(actual, text, "formatter output: " + dtf);
}
}
diff --git a/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
index 0175c223826..7ab8804a9ad 100644
--- a/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
+++ b/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
@@ -28,7 +28,7 @@ import static org.testng.Assert.assertEquals;
import java.text.DateFormatSymbols;
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatSymbols;
+import java.time.format.DecimalStyle;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
@@ -55,7 +55,7 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser {
protected static DateTimeFormatter getFormatter(Locale locale, TextStyle style) {
return new DateTimeFormatterBuilder().appendZoneText(style)
.toFormatter(locale)
- .withSymbols(DateTimeFormatSymbols.of(locale));
+ .withDecimalStyle(DecimalStyle.of(locale));
}
public void test_printText() {
@@ -148,7 +148,7 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser {
public void test_ParseText(String expected, String text, Set preferred, Locale locale, TextStyle style) {
DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneText(style, preferred)
.toFormatter(locale)
- .withSymbols(DateTimeFormatSymbols.of(locale));
+ .withDecimalStyle(DecimalStyle.of(locale));
String ret = fmt.parse(text, TemporalQuery.zone()).getId();
@@ -209,7 +209,7 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser {
}
return db.appendZoneText(style)
.toFormatter(locale)
- .withSymbols(DateTimeFormatSymbols.of(locale));
+ .withDecimalStyle(DecimalStyle.of(locale));
}
}
diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java
index 94413a2aa60..a8895a0cc81 100644
--- a/jdk/test/java/util/Base64/TestBase64.java
+++ b/jdk/test/java/util/Base64/TestBase64.java
@@ -23,6 +23,7 @@
/**
* @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530 8007379 8008925
+ * 8014217
* @summary tests java.util.Base64
*/
@@ -110,6 +111,14 @@ public class TestBase64 {
// illegal ending unit
checkIAE(new Runnable() { public void run() { Base64.getMimeDecoder().decode("$=#"); }});
+ checkIOE(new Testable() { public void test() throws IOException {
+ byte[] bytes = "AA=".getBytes("ASCII");
+ try (InputStream stream =
+ Base64.getDecoder().wrap(new ByteArrayInputStream(bytes))) {
+ while (stream.read() != -1);
+ }
+ }});
+
// test return value from decode(ByteBuffer, ByteBuffer)
testDecBufRet();
diff --git a/jdk/test/java/util/Locale/LocaleProviders.java b/jdk/test/java/util/Locale/LocaleProviders.java
index 97a5c2a7dbb..e5324e4dd91 100644
--- a/jdk/test/java/util/Locale/LocaleProviders.java
+++ b/jdk/test/java/util/Locale/LocaleProviders.java
@@ -118,27 +118,67 @@ public class LocaleProviders {
if (System.getProperty("os.name").startsWith("Windows")) {
NumberFormat nf = NumberFormat.getInstance(Locale.US);
try {
- double ver = nf.parse(System.getProperty("os.version")).doubleValue();
+ double ver = nf.parse(System.getProperty("os.version"))
+ .doubleValue();
System.out.printf("Windows version: %.1f\n", ver);
if (ver >= 6.0) {
- LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(LocaleNameProvider.class, Locale.ENGLISH);
+ LocaleProviderAdapter lda =
+ LocaleProviderAdapter.getAdapter(
+ LocaleNameProvider.class, Locale.ENGLISH);
LocaleProviderAdapter.Type type = lda.getAdapterType();
if (type == LocaleProviderAdapter.Type.HOST) {
+ LocaleNameProvider lnp = lda.getLocaleNameProvider();
Locale mkmk = Locale.forLanguageTag("mk-MK");
String result = mkmk.getDisplayLanguage(Locale.ENGLISH);
- if (!"Macedonian (FYROM)".equals(result)) {
- throw new RuntimeException("Windows locale name provider did not return expected localized language name for \"mk\". Returned name was \"" + result + "\"");
+ String hostResult =
+ lnp.getDisplayLanguage(mkmk.getLanguage(),
+ Locale.ENGLISH);
+ System.out.printf(" Display language name for" +
+ " (mk_MK): result(HOST): \"%s\", returned: \"%s\"\n",
+ hostResult, result);
+ if (result == null ||
+ hostResult != null &&
+ !result.equals(hostResult)) {
+ throw new RuntimeException("Display language name" +
+ " mismatch for \"mk\". Returned name was" +
+ " \"" + result + "\", result(HOST): \"" +
+ hostResult + "\"");
}
result = Locale.US.getDisplayLanguage(Locale.ENGLISH);
- if (!"English".equals(result)) {
- throw new RuntimeException("Windows locale name provider did not return expected localized language name for \"en\". Returned name was \"" + result + "\"");
+ hostResult =
+ lnp.getDisplayLanguage(Locale.US.getLanguage(),
+ Locale.ENGLISH);
+ System.out.printf(" Display language name for" +
+ " (en_US): result(HOST): \"%s\", returned: \"%s\"\n",
+ hostResult, result);
+ if (result == null ||
+ hostResult != null &&
+ !result.equals(hostResult)) {
+ throw new RuntimeException("Display language name" +
+ " mismatch for \"en\". Returned name was" +
+ " \"" + result + "\", result(HOST): \"" +
+ hostResult + "\"");
}
- result = Locale.US.getDisplayCountry(Locale.ENGLISH);
- if (ver >= 6.1 && !"United States".equals(result)) {
- throw new RuntimeException("Windows locale name provider did not return expected localized country name for \"US\". Returned name was \"" + result + "\"");
+ if (ver >= 6.1) {
+ result = Locale.US.getDisplayCountry(Locale.ENGLISH);
+ hostResult = lnp.getDisplayCountry(
+ Locale.US.getCountry(), Locale.ENGLISH);
+ System.out.printf(" Display country name for" +
+ " (en_US): result(HOST): \"%s\", returned: \"%s\"\n",
+ hostResult, result);
+ if (result == null ||
+ hostResult != null &&
+ !result.equals(hostResult)) {
+ throw new RuntimeException("Display country name" +
+ " mismatch for \"US\". Returned name was" +
+ " \"" + result + "\", result(HOST): \"" +
+ hostResult + "\"");
+ }
}
} else {
- throw new RuntimeException("Windows Host LocaleProviderAdapter was not selected for English locale.");
+ throw new RuntimeException("Windows Host" +
+ " LocaleProviderAdapter was not selected for" +
+ " English locale.");
}
}
} catch (ParseException pe) {
diff --git a/jdk/test/java/util/Locale/LocaleProviders.sh b/jdk/test/java/util/Locale/LocaleProviders.sh
index 3b1f96fd196..4d8bd06ff08 100644
--- a/jdk/test/java/util/Locale/LocaleProviders.sh
+++ b/jdk/test/java/util/Locale/LocaleProviders.sh
@@ -24,7 +24,7 @@
#
# @test
# @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8010666
-# 8013086
+# 8013086 8013233
# @summary tests for "java.locale.providers" system property
# @compile -XDignore.symbol.file LocaleProviders.java
# @run shell/timeout=600 LocaleProviders.sh
diff --git a/jdk/test/java/util/Objects/BasicObjectsTest.java b/jdk/test/java/util/Objects/BasicObjectsTest.java
index f87d0675a14..3a1cad9cd32 100644
--- a/jdk/test/java/util/Objects/BasicObjectsTest.java
+++ b/jdk/test/java/util/Objects/BasicObjectsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, 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
@@ -23,12 +23,13 @@
/*
* @test
- * @bug 6797535 6889858 6891113
+ * @bug 6797535 6889858 6891113 8013712 8011800 8014365
* @summary Basic tests for methods in java.util.Objects
* @author Joseph D. Darcy
*/
import java.util.*;
+import java.util.function.*;
public class BasicObjectsTest {
public static void main(String... args) {
@@ -162,47 +163,52 @@ public class BasicObjectsTest {
private static int testRequireNonNull() {
int errors = 0;
- String s;
- // Test 1-arg variant
+ final String RNN_1 = "1-arg requireNonNull";
+ final String RNN_2 = "2-arg requireNonNull";
+ final String RNN_3 = "Supplier requireNonNull";
+
+ Function rnn1 = s -> Objects.requireNonNull(s);
+ Function rnn2 = s -> Objects.requireNonNull(s, "trousers");
+ Function rnn3 = s -> Objects.requireNonNull(s, () -> "trousers");
+
+ errors += testRNN_NonNull(rnn1, RNN_1);
+ errors += testRNN_NonNull(rnn2, RNN_2);
+ errors += testRNN_NonNull(rnn3, RNN_3);
+
+ errors += testRNN_Null(rnn1, RNN_1, null);
+ errors += testRNN_Null(rnn2, RNN_2, "trousers");
+ errors += testRNN_Null(rnn3, RNN_3, "trousers");
+ return errors;
+ }
+
+ private static int testRNN_NonNull(Function testFunc,
+ String testFuncName) {
+ int errors = 0;
try {
- s = Objects.requireNonNull("pants");
+ String s = testFunc.apply("pants");
if (s != "pants") {
- System.err.printf("1-arg non-null failed to return its arg");
+ System.err.printf(testFuncName + " failed to return its arg");
errors++;
}
} catch (NullPointerException e) {
- System.err.printf("1-arg nonNull threw unexpected NPE");
+ System.err.printf(testFuncName + " threw unexpected NPE");
errors++;
}
+ return errors;
+ }
+ private static int testRNN_Null(Function testFunc,
+ String testFuncName,
+ String expectedMessage) {
+ int errors = 0;
try {
- s = Objects.requireNonNull(null);
- System.err.printf("1-arg nonNull failed to throw NPE");
+ String s = testFunc.apply(null);
+ System.err.printf(testFuncName + " failed to throw NPE");
errors++;
} catch (NullPointerException e) {
- // Expected
- }
-
- // Test 2-arg variant
- try {
- s = Objects.requireNonNull("pants", "trousers");
- if (s != "pants") {
- System.err.printf("2-arg nonNull failed to return its arg");
- errors++;
- }
- } catch (NullPointerException e) {
- System.err.printf("2-arg nonNull threw unexpected NPE");
- errors++;
- }
-
- try {
- s = Objects.requireNonNull(null, "pantaloons");
- System.err.printf("2-arg nonNull failed to throw NPE");
- errors++;
- } catch (NullPointerException e) {
- if (e.getMessage() != "pantaloons") {
- System.err.printf("2-arg nonNull threw NPE w/ bad detail msg");
+ if (e.getMessage() != expectedMessage) {
+ System.err.printf(testFuncName + " threw NPE w/ bad detail msg");
errors++;
}
}
diff --git a/jdk/test/sun/util/calendar/zi/Rule.java b/jdk/test/sun/util/calendar/zi/Rule.java
index 8e3a1189bb9..e8c79da9263 100644
--- a/jdk/test/sun/util/calendar/zi/Rule.java
+++ b/jdk/test/sun/util/calendar/zi/Rule.java
@@ -106,6 +106,7 @@ class Rule {
final int y = year;
RuleRec[] recs = new RuleRec[rules.size()];
rules.toArray(recs);
+
Arrays.sort(recs, new Comparator() {
public int compare(RuleRec r1, RuleRec r2) {
int n = r1.getMonthNum() - r2.getMonthNum();
@@ -117,7 +118,7 @@ class Rule {
r1.getDay(), r1.getTime().getTime());
long t2 = Time.getLocalTime(y, r2.getMonth(),
r2.getDay(), r2.getTime().getTime());
- return (int)(t1 - t2);
+ return Long.compare(t1, t2);
}
public boolean equals(Object o) {
return this == o;
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/VERSION b/jdk/test/sun/util/calendar/zi/tzdata/VERSION
index 85db871ccf3..8ad1064e058 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/VERSION
+++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2012i
+tzdata2013c
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/africa b/jdk/test/sun/util/calendar/zi/tzdata/africa
index 7db9b3d269d..2f5d3c5e3fc 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/africa
+++ b/jdk/test/sun/util/calendar/zi/tzdata/africa
@@ -27,9 +27,9 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2013-02-21):
#
# A good source for time zone historical data outside the U.S. is
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -48,6 +48,10 @@
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
# 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
+# .
+#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
@@ -139,8 +143,12 @@ Zone Africa/Porto-Novo 0:10:28 - LMT 1912
1:00 - WAT
# Botswana
+# From Paul Eggert (2013-02-21):
+# Milne says they were regulated by the Cape Town Signal in 1899;
+# assume they switched to 2:00 when Cape Town did.
# 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
@@ -212,6 +220,11 @@ Zone Africa/Djibouti 2:52:36 - LMT 1911 Jul
# Egypt
+# Milne says Cairo used 2:05:08.9, the local mean time of the Abbasizeh
+# observatory; round to nearest. Milne also says that the official time for
+# Egypt was mean noon at the Great Pyramid, 2:04:30.5, but apparently this
+# did not apply to Cairo, Alexandria, or Port Said.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Egypt 1940 only - Jul 15 0:00 1:00 S
Rule Egypt 1940 only - Oct 1 0:00 0 -
@@ -352,7 +365,7 @@ Rule Egypt 2010 only - Sep 10 0:00 1:00 S
Rule Egypt 2010 only - Sep lastThu 23:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Cairo 2:05:00 - LMT 1900 Oct
+Zone Africa/Cairo 2:05:09 - LMT 1900 Oct
2:00 Egypt EE%sT
# Equatorial Guinea
@@ -447,6 +460,20 @@ Zone Africa/Monrovia -0:43:08 - LMT 1882
# Libya
+# From Even Scharning (2012-11-10):
+# Libya set their time one hour back at 02:00 on Saturday November 10.
+# http://www.libyaherald.com/2012/11/04/clocks-to-go-back-an-hour-on-saturday/
+# Here is an official source [in Arabic]: http://ls.ly/fb6Yc
+#
+# Steffen Thorsen forwarded a translation (2012-11-10) in
+# http://mm.icann.org/pipermail/tz/2012-November/018451.html
+#
+# From Tim Parenti (2012-11-11):
+# Treat the 2012-11-10 change as a zone change from UTC+2 to UTC+1.
+# The DST rules planned for 2013 and onward roughly mirror those of Europe
+# (either two days before them or five days after them, so as to fall on
+# lastFri instead of lastSun).
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Libya 1951 only - Oct 14 2:00 1:00 S
Rule Libya 1952 only - Jan 1 0:00 0 -
@@ -461,17 +488,21 @@ Rule Libya 1986 only - Apr 4 0:00 1:00 S
Rule Libya 1986 only - Oct 3 0:00 0 -
Rule Libya 1987 1989 - Apr 1 0:00 1:00 S
Rule Libya 1987 1989 - Oct 1 0:00 0 -
+Rule Libya 1997 only - Apr 4 0:00 1:00 S
+Rule Libya 1997 only - Oct 4 0:00 0 -
+Rule Libya 2013 max - Mar lastFri 1:00 1:00 S
+Rule Libya 2013 max - Oct lastFri 2:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Tripoli 0:52:44 - LMT 1920
1:00 Libya CE%sT 1959
2:00 - EET 1982
1:00 Libya CE%sT 1990 May 4
-# The following entries are from Shanks & Pottenger;
+# The 1996 and 1997 entries are from Shanks & Pottenger;
# the IATA SSIM data contain some obvious errors.
2:00 - EET 1996 Sep 30
- 1:00 - CET 1997 Apr 4
- 1:00 1:00 CEST 1997 Oct 4
- 2:00 - EET
+ 1:00 Libya CE%sT 1997 Oct 4
+ 2:00 - EET 2012 Nov 10 2:00
+ 1:00 Libya CE%sT
# Madagascar
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -838,6 +869,41 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou
# 3:00 am Friday, July 20, 2012 and will again be advanced by 60 minutes
# August 20, 2012 from 2:00 am.
+# From Paul Eggert (2013-03-06):
+# Morocco's daylight-saving transitions due to Ramadan seem to be
+# 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
+# .
+#
+# To estimate what the Moroccan government will do in future years,
+# transition dates for 2013 through 2021 were determined by running
+# the following program under GNU Emacs 24.3:
+#
+# (let ((islamic-year 1434))
+# (while (< islamic-year 1444)
+# (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)))))
+# (setq islamic-year (+ 1 islamic-year))))
+#
+# with the results hand-edited for 2020-2022, when the normal spring-forward
+# date falls during the estimated Ramadan.
+#
+# From 2023 through 2038 Ramadan is not predicted to overlap with
+# daylight saving time. Starting in 2039 there will be overlap again,
+# but 32-bit time_t values roll around in 2038 so for now do not worry
+# about dates after 2038.
+
# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Morocco 1939 only - Sep 12 0:00 1:00 S
@@ -863,10 +929,28 @@ 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 max - Apr lastSun 2:00 1:00 S
+Rule Morocco 2012 2019 - Apr lastSun 2:00 1:00 S
Rule Morocco 2012 max - Sep lastSun 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 9 3:00 0 -
+Rule Morocco 2013 only - Aug 8 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 - May 24 2:00 1:00 S
+Rule Morocco 2021 only - May 13 2:00 1:00 S
+Rule Morocco 2022 only - May 3 2:00 1:00 S
+Rule Morocco 2023 max - Apr lastSun 2:00 1:00 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/antarctica b/jdk/test/sun/util/calendar/zi/tzdata/antarctica
index 64b71d5c052..daa03ea830c 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/antarctica
+++ b/jdk/test/sun/util/calendar/zi/tzdata/antarctica
@@ -73,38 +73,8 @@ Rule ChileAQ 2009 only - Mar Sun>=9 3:00u 0 -
Rule ChileAQ 2010 only - Apr Sun>=1 3:00u 0 -
Rule ChileAQ 2011 only - May Sun>=2 3:00u 0 -
Rule ChileAQ 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule ChileAQ 2012 only - Apr Sun>=23 3:00u 0 -
-Rule ChileAQ 2012 only - Sep Sun>=2 4:00u 1:00 S
-Rule ChileAQ 2013 max - Mar Sun>=9 3:00u 0 -
-Rule ChileAQ 2013 max - Oct Sun>=9 4:00u 1:00 S
-
-# These rules are stolen from the `australasia' file.
-Rule AusAQ 1917 only - Jan 1 0:01 1:00 -
-Rule AusAQ 1917 only - Mar 25 2:00 0 -
-Rule AusAQ 1942 only - Jan 1 2:00 1:00 -
-Rule AusAQ 1942 only - Mar 29 2:00 0 -
-Rule AusAQ 1942 only - Sep 27 2:00 1:00 -
-Rule AusAQ 1943 1944 - Mar lastSun 2:00 0 -
-Rule AusAQ 1943 only - Oct 3 2:00 1:00 -
-Rule ATAQ 1967 only - Oct Sun>=1 2:00s 1:00 -
-Rule ATAQ 1968 only - Mar lastSun 2:00s 0 -
-Rule ATAQ 1968 1985 - Oct lastSun 2:00s 1:00 -
-Rule ATAQ 1969 1971 - Mar Sun>=8 2:00s 0 -
-Rule ATAQ 1972 only - Feb lastSun 2:00s 0 -
-Rule ATAQ 1973 1981 - Mar Sun>=1 2:00s 0 -
-Rule ATAQ 1982 1983 - Mar lastSun 2:00s 0 -
-Rule ATAQ 1984 1986 - Mar Sun>=1 2:00s 0 -
-Rule ATAQ 1986 only - Oct Sun>=15 2:00s 1:00 -
-Rule ATAQ 1987 1990 - Mar Sun>=15 2:00s 0 -
-Rule ATAQ 1987 only - Oct Sun>=22 2:00s 1:00 -
-Rule ATAQ 1988 1990 - Oct lastSun 2:00s 1:00 -
-Rule ATAQ 1991 1999 - Oct Sun>=1 2:00s 1:00 -
-Rule ATAQ 1991 2005 - Mar lastSun 2:00s 0 -
-Rule ATAQ 2000 only - Aug lastSun 2:00s 1:00 -
-Rule ATAQ 2001 max - Oct Sun>=1 2:00s 1:00 -
-Rule ATAQ 2006 only - Apr Sun>=1 2:00s 0 -
-Rule ATAQ 2007 only - Mar lastSun 2:00s 0 -
-Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 -
+Rule ChileAQ 2012 max - Apr Sun>=23 3:00u 0 -
+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
@@ -147,10 +117,7 @@ Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 -
#
# From Steffen Thorsen (2010-03-10):
-# We got these changes from the Australian Antarctic Division:
-# - Macquarie Island will stay on UTC+11 for winter and therefore not
-# switch back from daylight savings time when other parts of Australia do
-# on 4 April.
+# We got these changes from the Australian Antarctic Division: ...
#
# - Casey station reverted to its normal time of UTC+8 on 5 March 2010.
# The change to UTC+11 is being considered as a regular summer thing but
@@ -161,9 +128,6 @@ Rule ATAQ 2008 max - Apr Sun>=1 2:00s 0 -
#
# - Mawson station stays on UTC+5.
#
-# In addition to the Rule changes for Casey/Davis, it means that Macquarie
-# will no longer be like Hobart and will have to have its own Zone created.
-#
# Background:
#
# http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
@@ -190,12 +154,6 @@ Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
6:00 - MAWT 2009 Oct 18 2:00
# Mawson Time
5:00 - MAWT
-Zone Antarctica/Macquarie 0 - zzz 1911
- 10:00 - EST 1916 Oct 1 2:00
- 10:00 1:00 EST 1917 Feb
- 10:00 AusAQ EST 1967
- 10:00 ATAQ EST 2010 Apr 4 3:00
- 11:00 - MIST # Macquarie Island Time
# References:
#
# Casey Weather (1998-02-26)
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/asia b/jdk/test/sun/util/calendar/zi/tzdata/asia
index 9ef3ef8df54..7818c029a60 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/asia
+++ b/jdk/test/sun/util/calendar/zi/tzdata/asia
@@ -27,9 +27,9 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2013-02-21):
#
# A good source for time zone historical data outside the U.S. is
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -48,6 +48,10 @@
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
# 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
+# .
+#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
@@ -302,9 +306,12 @@ Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
8:00 - BNT
# Burma / Myanmar
+
+# 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:36 - RMT 1920 # Rangoon Mean Time?
+ 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
@@ -407,7 +414,8 @@ Zone Asia/Harbin 8:26:44 - LMT 1928 # or Haerbin
8:00 PRC C%sT
# Zhongyuan Time ("Central plain Time")
# most of China
-Zone Asia/Shanghai 8:05:52 - LMT 1928
+# 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)
@@ -504,6 +512,10 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar
8:00 PRC C%sT
+# Hong Kong (Xianggang)
+
+# Milne gives 7:36:41.7; round this.
+
# From Lee Yiu Chung (2009-10-24):
# I found there are some mistakes for the...DST rule for Hong
# Kong. [According] to the DST record from Hong Kong Observatory (actually,
@@ -570,7 +582,6 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar
# The Japanese surrender of Hong Kong was signed 1945-09-15.
# For lack of anything better, use start of those days as the transition times.
-# Hong Kong (Xianggang)
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule HK 1941 only - Apr 1 3:30 1:00 S
Rule HK 1941 only - Sep 30 3:30 0 -
@@ -592,7 +603,7 @@ Rule HK 1973 only - Dec 30 3:30 1:00 S
Rule HK 1979 only - May Sun>=8 3:30 1:00 S
Rule HK 1979 only - Oct Sun>=16 3:30 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30
+Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30
8:00 HK HK%sT 1941 Dec 25
9:00 - JST 1945 Sep 15
8:00 HK HK%sT
@@ -669,6 +680,9 @@ Zone Asia/Macau 7:34:20 - LMT 1912
###############################################################################
# Cyprus
+#
+# Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT.
+#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Cyprus 1975 only - Apr 13 0:00 1:00 S
Rule Cyprus 1975 only - Oct 12 0:00 0 -
@@ -1222,7 +1236,6 @@ Rule Zion 2012 only - Mar Fri>=26 2:00 1:00 D
Rule Zion 2012 only - Sep 23 2:00 0 S
# From Ephraim Silverberg (2012-10-18):
-
# Yesterday, the Interior Ministry Committee, after more than a year
# past, approved sending the proposed June 2011 changes to the Time
# Decree Law back to the Knesset for second and third (final) votes
@@ -1235,6 +1248,10 @@ Rule Zion 2012 only - Sep 23 2:00 0 S
# later (i.e. at 02:00 the first Monday after October 2).
# [Rosh Hashana holidays are factored in until 2100.]
+# From Ephraim Silverberg (2012-11-05):
+# The Knesset passed today (in second and final readings) the amendment to the
+# Time Decree Law making the changes ... law.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Zion 2013 max - Mar Fri>=23 2:00 1:00 D
Rule Zion 2013 2026 - Oct Sun>=2 2:00 0 S
@@ -1824,8 +1841,11 @@ Zone Asia/Kathmandu 5:41:16 - LMT 1920
5:45 - NPT # Nepal Time
# Oman
+
+# Milne says 3:54:24 was the meridian of the Muscat Tidal Observatory.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Muscat 3:54:20 - LMT 1920
+Zone Asia/Muscat 3:54:24 - LMT 1920
4:00 - GST
# Pakistan
@@ -2072,8 +2092,7 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# occurred before our cutoff date of 1970.
# However, as we get more information, we may need to add entries
# for parts of the West Bank as they transitioned from Israel's rules
-# to Palestine's rules. If you have more info about this, please
-# send it to tz@elsie.nci.nih.gov for incorporation into future editions.
+# to Palestine's rules.
# From IINS News Service - Israel - 1998-03-23 10:38:07 Israel time,
# forwarded by Ephraim Silverberg:
@@ -2295,11 +2314,20 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
#
-# From Arthur David Olson (2012-03-27):
-# The timeanddate article for 2012 says that "the end date has not yet been
-# announced" and that "Last year, both...paused daylight saving time during...
-# Ramadan. It is not yet known [for] 2012."
-# For now, assume both switch back on the last Friday in September. XXX
+# From Steffen Thorsen (2013-03-26):
+# The following news sources tells that Palestine will "start daylight saving
+# time from midnight on Friday, March 29, 2013" (translated).
+# [These are in Arabic and are for Gaza and for Ramallah, respectively.]
+# http://www.samanews.com/index.php?act=Show&id=154120
+# http://safa.ps/details/news/99844/%D8%B1%D8%A7%D9%85-%D8%A7%D9%84%D9%84%D9%87-%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-29-%D8%A7%D9%84%D8%AC%D8%A7%D8%B1%D9%8A.html
+
+# From Paul Eggert (2013-04-15):
+# For future dates, guess the last Thursday in March at 24:00 through
+# the first Friday on or after September 21 at 01:00. This is consistent with
+# the predictions in today's editions of the following URLs,
+# which are for Gaza and Hebron respectively:
+# http://www.timeanddate.com/worldclock/timezone.html?n=702
+# http://www.timeanddate.com/worldclock/timezone.html?n=2364
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
@@ -2313,19 +2341,20 @@ Rule Palestine 1999 2005 - Apr Fri>=15 0:00 1:00 S
Rule Palestine 1999 2003 - Oct Fri>=15 0:00 0 -
Rule Palestine 2004 only - Oct 1 1:00 0 -
Rule Palestine 2005 only - Oct 4 2:00 0 -
-Rule Palestine 2006 2008 - Apr 1 0:00 1:00 S
+Rule Palestine 2006 2007 - Apr 1 0:00 1:00 S
Rule Palestine 2006 only - Sep 22 0:00 0 -
Rule Palestine 2007 only - Sep Thu>=8 2:00 0 -
-Rule Palestine 2008 only - Aug lastFri 0:00 0 -
-Rule Palestine 2009 only - Mar lastFri 0:00 1:00 S
-Rule Palestine 2009 only - Sep Fri>=1 2:00 0 -
-Rule Palestine 2010 only - Mar lastSat 0:01 1:00 S
+Rule Palestine 2008 2009 - Mar lastFri 0:00 1:00 S
+Rule Palestine 2008 only - Sep 1 0:00 0 -
+Rule Palestine 2009 only - Sep Fri>=1 1:00 0 -
+Rule Palestine 2010 only - Mar 26 0:00 1:00 S
Rule Palestine 2010 only - Aug 11 0:00 0 -
-
-# From Arthur David Olson (2011-09-20):
-# 2011 transitions per http://www.timeanddate.com as of 2011-09-20.
-# From Paul Eggert (2012-10-12):
-# 2012 transitions per http://www.timeanddate.com as of 2012-10-12.
+Rule Palestine 2011 only - Apr 1 0:01 1:00 S
+Rule Palestine 2011 only - Aug 1 0:00 0 -
+Rule Palestine 2011 only - Aug 30 0:00 1:00 S
+Rule Palestine 2011 only - Sep 30 0:00 0 -
+Rule Palestine 2012 max - Mar lastThu 24:00 1:00 S
+Rule Palestine 2012 max - Sep Fri>=21 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@@ -2333,26 +2362,20 @@ 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 2011 Apr 2 12:01
- 2:00 1:00 EEST 2011 Aug 1
- 2:00 - EET 2012 Mar 30
- 2:00 1:00 EEST 2012 Sep 21 1:00
- 2:00 - EET
+ 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 Palestine EE%sT 2011 Aug 1
+ 2:00 - EET 2012
+ 2:00 Palestine EE%sT
Zone Asia/Hebron 2:20:23 - LMT 1900 Oct
2:00 Zion EET 1948 May 15
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
- 2:00 1:00 EEST 2008 Sep
- 2:00 Palestine EE%sT 2011 Apr 1 12:01
- 2:00 1:00 EEST 2011 Aug 1
- 2:00 - EET 2011 Aug 30
- 2:00 1:00 EEST 2011 Sep 30 3:00
- 2:00 - EET 2012 Mar 30
- 2:00 1:00 EEST 2012 Sep 21 1:00
- 2:00 - EET
+ 2:00 Palestine EE%sT
# Paracel Is
# no information
@@ -2421,6 +2444,13 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
# no information
# Sri Lanka
+
+# From Paul Eggert (2013-02-21):
+# Milne says "Madras mean time use from May 1, 1898. Prior to this Colombo
+# mean time, 5h. 4m. 21.9s. F., was used." But 5:04:21.9 differs considerably
+# from Colombo's meridian 5:19:24, so for now ignore Milne and stick with
+# Shanks and Pottenger.
+
# 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,
@@ -2720,6 +2750,12 @@ Zone Asia/Tashkent 4:37:12 - LMT 1924 May 2
# Vietnam
+# From Paul Eggert (2013-02-21):
+# Milne gives 7:16:56 for the meridian of Saigon in 1899, as being
+# used in Lower Laos, Cambodia, and Annam. But this is quite a ways
+# from Saigon's location. For now, ignore this and stick with Shanks
+# 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.
@@ -2733,6 +2769,10 @@ Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jun 9
7:00 - ICT
# Yemen
+
+# Milne says 2:59:54 was the meridian of the saluting battery at Aden,
+# and that Yemen was at 1:55:56, the meridian of the Hagia Sophia.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Aden 3:00:48 - LMT 1950
+Zone Asia/Aden 2:59:54 - LMT 1950
3:00 - AST
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/australasia b/jdk/test/sun/util/calendar/zi/tzdata/australasia
index 7f83448f3fb..db954a81dcd 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/australasia
+++ b/jdk/test/sun/util/calendar/zi/tzdata/australasia
@@ -241,9 +241,26 @@ Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb
# no times are set
#
# Macquarie
-# permanent occupation (scientific station) since 1948;
-# sealing and penguin oil station operated 1888/1917
-# like Australia/Hobart
+# 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
+#
+# .
+# Guess that it was like Australia/Hobart while inhabited before 2010.
+#
+# From Steffen Thorsen (2010-03-10):
+# We got these changes from the Australian Antarctic Division:
+# - Macquarie Island will stay on UTC+11 for winter and therefore not
+# switch back from daylight savings time when other parts of Australia do
+# on 4 April.
+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
+ 0 - zzz 1948 Mar 25
+ 10:00 Aus EST 1967
+ 10:00 AT EST 2010 Apr 4 3:00
+ 11:00 - MIST # Macquarie I Standard Time
# Christmas
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -269,6 +286,9 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
6:30 - CCT # Cocos Islands Time
# Fiji
+
+# Milne gives 11:55:44 for Suva.
+
# From Alexander Krivenyshev (2009-11-10):
# According to Fiji Broadcasting Corporation, Fiji plans to re-introduce DST
# from November 29th 2009 to April 25th 2010.
@@ -362,7 +382,7 @@ Rule Fiji 2010 max - Oct Sun>=18 2:00 1:00 S
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
Rule Fiji 2012 max - Jan Sun>=18 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Fiji 11:53:40 - 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
@@ -803,9 +823,9 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2013-02-21):
# 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).
@@ -823,6 +843,10 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
# 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
+# .
+#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/europe b/jdk/test/sun/util/calendar/zi/tzdata/europe
index 9a0d0b9db94..268504d0983 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/europe
+++ b/jdk/test/sun/util/calendar/zi/tzdata/europe
@@ -27,7 +27,7 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
# From Paul Eggert (2006-03-22):
# A good source for time zone historical data outside the U.S. is
@@ -53,6 +53,12 @@
# William Willett, The Waste of Daylight, 19th edition
# (1914-03)
#
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# . He writes:
+# "It is requested that corrections and additions to these tables
+# 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),
#
# History of Summer Time
@@ -689,6 +695,8 @@ Zone Europe/Andorra 0:06:04 - LMT 1901
# Austria
+# Milne says Vienna time was 1:05:21.
+
# From Paul Eggert (2006-03-22): Shanks & Pottenger give 1918-06-16 and
# 1945-11-18, but the Austrian Federal Office of Metrology and
# Surveying (BEV) gives 1918-09-16 and for Vienna gives the "alleged"
@@ -706,7 +714,7 @@ Rule Austria 1948 only - Apr 18 2:00s 1:00 S
Rule Austria 1980 only - Apr 6 0:00 1:00 S
Rule Austria 1980 only - Sep 28 0:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Vienna 1:05:20 - LMT 1893 Apr
+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
@@ -1262,6 +1270,21 @@ Zone Europe/Berlin 0:53:28 - LMT 1893 Apr
1:00 Germany CE%sT 1980
1:00 EU CE%sT
+# From Tobias Conradi (2011-09-12):
+# Busingen , 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:
+# 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.
+
+Link Europe/Zurich Europe/Busingen
+
# Georgia
# Please see the "asia" file for Asia/Tbilisi.
# Herodotus (Histories, IV.45) says Georgia north of the Phasis (now Rioni)
@@ -2066,6 +2089,70 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# 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).
+
+# From Arthur David Olson (2012-05-09):
+# Regarding the instant when clocks in time-zone-shifting parts of Russia
+# 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:
+# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which
+# 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).
+#
+# None of the sources indicates a time of day for changing clocks.
+#
+# Go with 2011-09-13 0:00s.
+
# 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,
@@ -2293,14 +2380,32 @@ Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15
# [parts of] Respublika Sakha (Yakutiya).
# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Bulunskij, Verkhoyanskij, Tomponskij, Ust'-Majskij,
-# Ust'-Yanskij.
+# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
Zone Asia/Vladivostok 8:47:44 - 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
+
+# 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 2004
+ 10:00 Russia VLA%sT 2011 Mar 27 2:00s
+ 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725?
+ 10:00 - YAKT
+
#
# Sakhalinskaya oblast'.
# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
@@ -2319,14 +2424,26 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
# From Oscar van Vlijmen (2009-11-29):
# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
-# Nizhnekolymskij, Ojmyakonskij, Srednekolymskij.
+# Nizhnekolymskij, ... Srednekolymskij.
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
-#
+
+# From Arthur David Olson (2012-05-09):
+# Ojmyakonskij and the Kuril Islands switched from
+# Magadan time to Vladivostok time in 2011.
+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
+
# From Oscar van Vlijmen (2001-08-25): [This region consists of]
# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
#
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/northamerica b/jdk/test/sun/util/calendar/zi/tzdata/northamerica
index c3033267404..858bf811ac9 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/northamerica
+++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica
@@ -29,7 +29,7 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
# From Paul Eggert (1999-03-22):
# A reliable and entertaining source about time zones is
@@ -1042,6 +1042,9 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
# William Willett, The Waste of Daylight, 19th edition
# (1914-03)
#
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# .
+#
# See the `europe' file for Greenland.
# Canada
@@ -2577,6 +2580,8 @@ Zone America/Antigua -4:07:12 - LMT 1912 Mar 2
# Bahamas
#
+# For 1899 Milne gives -5:09:29.5; round that.
+#
# From Sue Williams (2006-12-07):
# The Bahamas announced about a month ago that they plan to change their DST
# rules to sync with the U.S. starting in 2007....
@@ -2586,11 +2591,14 @@ Zone America/Antigua -4:07:12 - LMT 1912 Mar 2
Rule Bahamas 1964 1975 - Oct lastSun 2:00 0 S
Rule Bahamas 1964 1975 - Apr lastSun 2:00 1:00 D
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Nassau -5:09:24 - LMT 1912 Mar 2
+Zone America/Nassau -5:09:30 - LMT 1912 Mar 2
-5:00 Bahamas E%sT 1976
-5:00 US E%sT
# Barbados
+
+# For 1899 Milne gives -3:58:29.2; round that.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Barb 1977 only - Jun 12 2:00 1:00 D
Rule Barb 1977 1978 - Oct Sun>=1 2:00 0 S
@@ -2598,8 +2606,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:28 - LMT 1924 # Bridgetown
- -3:58:28 - 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
@@ -2617,6 +2625,9 @@ Zone America/Belize -5:52:48 - LMT 1912 Apr
# Bermuda
+# For 1899 Milne gives -4:19:18.3 as the meridian of the clock tower,
+# Bermuda dockyard, Ireland I; round that.
+
# From Dan Jones, reporting in The Royal Gazette (2006-06-26):
# Next year, however, clocks in the US will go forward on the second Sunday
@@ -2626,7 +2637,7 @@ 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:04 - LMT 1930 Jan 1 2:00 # Hamilton
+Zone Atlantic/Bermuda -4:19:18 - LMT 1930 Jan 1 2:00 # Hamilton
-4:00 - AST 1974 Apr 28 2:00
-4:00 Bahamas A%sT 1976
-4:00 US A%sT
@@ -2638,6 +2649,9 @@ Zone America/Cayman -5:25:32 - LMT 1890 # Georgetown
-5:00 - EST
# Costa Rica
+
+# Milne gives -5:36:13.3 as San Jose 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
Rule CR 1979 1980 - Jun Sun>=1 0:00 0 S
@@ -2648,14 +2662,19 @@ 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'.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Costa_Rica -5:36:20 - LMT 1890 # San Jose
- -5:36:20 - SJMT 1921 Jan 15 # San Jose Mean Time
+Zone America/Costa_Rica -5:36:13 - LMT 1890 # San Jose
+ -5:36:13 - SJMT 1921 Jan 15 # San Jose Mean Time
-6:00 CR C%sT
# Coco
# no information; probably like America/Costa_Rica
# Cuba
+# From Paul Eggert (2013-02-21):
+# Milne gives -5:28:50.45 for the observatory at Havana, -5:29:23.57
+# for the port, and -5:30 for meteorological observations.
+# For now, stick with Shanks & Pottenger.
+
# From Arthur David Olson (1999-03-29):
# The 1999-03-28 exhibition baseball game held in Havana, Cuba, between
# the Cuban National Team and the Baltimore Orioles was carried live on
@@ -3004,24 +3023,21 @@ Zone America/Guatemala -6:02:04 - LMT 1918 Oct 5
# apparently using the same start and end date as USA/Canada.
# So this means they have already changed their time.
#
-# (Sources in French):
-#
# http://www.alterpresse.org/spip.php?article12510
-#
-#
# http://radiovision2000haiti.net/home/?p=13253
-#
#
-# Our coverage:
-#
-# http://www.timeanddate.com/news/time/haiti-dst-2012.html
-#
-
# From Arthur David Olson (2012-03-11):
# The alterpresse.org source seems to show a US-style leap from 2:00 a.m. to
# 3:00 a.m. rather than the traditional Haitian jump at midnight.
-# Assume a US-style fall back as well XXX.
-# Do not yet assume that the change carries forward past 2012 XXX.
+# Assume a US-style fall back as well.
+
+# From Steffen Thorsen (2013-03-10):
+# It appears that Haiti is observing DST this year as well, same rules
+# as US/Canada. They did it last year as well, and it looks like they
+# are going to observe DST every year now...
+#
+# http://radiovision2000haiti.net/public/haiti-avis-changement-dheure-dimanche/
+# http://www.canalplushaiti.net/?p=6714
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Haiti 1983 only - May 8 0:00 1:00 D
@@ -3033,8 +3049,8 @@ Rule Haiti 1988 1997 - Apr Sun>=1 1:00s 1:00 D
Rule Haiti 1988 1997 - Oct lastSun 1:00s 0 S
Rule Haiti 2005 2006 - Apr Sun>=1 0:00 1:00 D
Rule Haiti 2005 2006 - Oct lastSun 0:00 0 S
-Rule Haiti 2012 only - Mar Sun>=8 2:00 1:00 D
-Rule Haiti 2012 only - Nov Sun>=1 2:00 0 S
+Rule Haiti 2012 max - Mar Sun>=8 2:00 1:00 D
+Rule Haiti 2012 max - Nov Sun>=1 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Port-au-Prince -4:49:20 - LMT 1890
-4:49 - PPMT 1917 Jan 24 12:00 # P-a-P MT
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/southamerica b/jdk/test/sun/util/calendar/zi/tzdata/southamerica
index 0d6797eab6b..d1865d3f19b 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/southamerica
+++ b/jdk/test/sun/util/calendar/zi/tzdata/southamerica
@@ -27,13 +27,17 @@
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
-# tz@elsie.nci.nih.gov for general use in the future).
+# tz@iana.org for general use in the future).
# From Paul Eggert (2006-03-22):
# 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).
#
+# For data circa 1899, a common source is:
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# .
+#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
@@ -404,21 +408,11 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
#
# is the official page for the Province Government).
#
-# There's also a note in only one of the major national papers (La Nación) at
-#
+# There's also a note in only one of the major national papers ...
# http://www.lanacion.com.ar/nota.asp?nota_id=1107912
-#
#
-# The press release says:
-# (...) anunció que el próximo domingo a las 00:00 los puntanos deberán
-# atrasar una hora sus relojes.
-#
-# A partir de entonces, San Luis establecerá el huso horario propio de
-# la Provincia. De esta manera, durante el periodo del calendario anual
-# 2009, el cambio horario quedará comprendido entre las 00:00 del tercer
-# domingo de marzo y las 24:00 del segundo sábado de octubre.
-# Quick&dirty translation
-# (...) announced that next Sunday, at 00:00, Puntanos (the San Luis
+# The press release says [quick and dirty translation]:
+# ... announced that next Sunday, at 00:00, Puntanos (the San Luis
# inhabitants) will have to turn back one hour their clocks
#
# Since then, San Luis will establish its own Province timezone. Thus,
@@ -480,6 +474,9 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
# rules...San Luis is still using "Western ARgentina Time" and it got
# stuck on Summer daylight savings time even though the summer is over.
+# From Paul Eggert (2013-02-21):
+# Milne says Cordoba time was -4:16:48.2. Round to the nearest second.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
#
# Buenos Aires (BA), Capital Federal (CF),
@@ -835,9 +832,9 @@ Zone America/La_Paz -4:32:36 - LMT 1890
# 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 Brandão at
+# I just send a e-mail to Zulmira Brandao at
# http://pcdsh01.on.br/ the
-# oficial agency about time in Brazil, and she confirmed that the old rule is
+# official agency about time in Brazil, and she confirmed that the old rule is
# still in force.
# From Guilherme Bernardes Rodrigues (2011-10-14)
@@ -1266,9 +1263,13 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
# b. Saturday, September 1, 2012, clocks should go forward 60 minutes; that is,
# at 23:59:59, instead of passing to 0:00, the time should be adjusted to be
# 01:00 on September 2.
-#
-# Note that...this is yet another "temporary" change that will be reevaluated
-# AGAIN in 2013.
+
+# From Steffen Thorsen (2013-02-15):
+# According to several news sources, Chile has extended DST this year,
+# they will end DST later and start DST earlier than planned. They
+# hope to save energy. The new end date is 2013-04-28 00:00 and new
+# 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
# NOTE: ChileAQ rules for Antarctic bases are stored separately in the
# 'antarctica' file.
@@ -1311,10 +1312,8 @@ Rule Chile 2009 only - Mar Sun>=9 3:00u 0 -
Rule Chile 2010 only - Apr Sun>=1 3:00u 0 -
Rule Chile 2011 only - May Sun>=2 3:00u 0 -
Rule Chile 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule Chile 2012 only - Apr Sun>=23 3:00u 0 -
-Rule Chile 2012 only - Sep Sun>=2 4:00u 1:00 S
-Rule Chile 2013 max - Mar Sun>=9 3:00u 0 -
-Rule Chile 2013 max - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 2012 max - Apr Sun>=23 3:00u 0 -
+Rule Chile 2012 max - Sep Sun>=2 4:00u 1:00 S
# IATA SSIM anomalies: (1992-02) says 1992-03-14;
# (1996-09) says 1998-03-08. Ignore these.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -1336,17 +1335,23 @@ Zone Pacific/Easter -7:17:44 - LMT 1890
# San Felix, and Antarctic bases, are like America/Santiago.
# Colombia
+
+# Milne gives 4:56:16.4 for Bogota 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
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:20 - LMT 1884 Mar 13
- -4:56:20 - BMT 1914 Nov 23 # Bogota Mean Time
+Zone America/Bogota -4:56:16 - LMT 1884 Mar 13
+ -4:56:16 - BMT 1914 Nov 23 # Bogota Mean Time
-5:00 CO CO%sT # Colombia Time
# Malpelo, Providencia, San Andres
# no information; probably like America/Bogota
# Curacao
+
+# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
#
# From Paul Eggert (2006-03-22):
# Shanks & Pottenger say that The Bottom and Philipsburg have been at
@@ -1363,7 +1368,7 @@ Zone America/Bogota -4:56:20 - LMT 1884 Mar 13
# though, as far as we know.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Curacao -4:35:44 - 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
@@ -1377,6 +1382,8 @@ Link America/Curacao America/Kralendijk # Bonaire, Sint Estatius and Saba
# Ecuador
#
+# Milne says the Sentral 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.
# (2007-02-27) and
@@ -1582,7 +1589,16 @@ Rule Para 2005 2009 - Mar Sun>=8 0:00 0 -
# forward 60 minutes, in all the territory of the Paraguayan Republic.
# ...
Rule Para 2010 max - Oct Sun>=1 0:00 1:00 S
-Rule Para 2010 max - Apr Sun>=8 0:00 0 -
+Rule Para 2010 2012 - Apr Sun>=8 0:00 0 -
+#
+# From Steffen Thorsen (2013-03-07):
+# 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):
+# The change in Paraguay is now final. Decree number 10780
+# http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.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
diff --git a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
index ef380cd19fb..cbcdc075bf7 100644
--- a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
+++ b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
@@ -65,7 +65,6 @@ 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 -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I
-AQ -5430+15857 Antarctica/Macquarie Macquarie Island Station, Macquarie Island
AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF)
AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN)
@@ -81,6 +80,7 @@ AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
AS -1416-17042 Pacific/Pago_Pago
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
+AU -5430+15857 Antarctica/Macquarie Macquarie Island
AU -4253+14719 Australia/Hobart Tasmania - most locations
AU -3956+14352 Australia/Currie Tasmania - King Island
AU -3749+14458 Australia/Melbourne Victoria
@@ -182,7 +182,8 @@ CW +1211-06900 America/Curacao
CX -1025+10543 Indian/Christmas
CY +3510+03322 Asia/Nicosia
CZ +5005+01426 Europe/Prague
-DE +5230+01322 Europe/Berlin
+DE +5230+01322 Europe/Berlin most locations
+DE +4742+00841 Europe/Busingen Busingen
DJ +1136+04309 Africa/Djibouti
DK +5540+01235 Europe/Copenhagen
DM +1518-06124 America/Dominica
@@ -364,8 +365,10 @@ RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk
RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River
RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal
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