Merge files from jdk11u/jdk-11.0.13-ga into the expected_upstream branch
List of files:
ojluni/src/main/java/java/text/DateFormat.java
ojluni/src/main/java/java/text/DateFormatSymbols.java
ojluni/src/main/java/java/text/DecimalFormat.java
ojluni/src/main/java/java/text/DecimalFormatSymbols.java
ojluni/src/main/java/java/text/MessageFormat.java
ojluni/src/main/java/java/text/NumberFormat.java
ojluni/src/main/java/java/text/SimpleDateFormat.java
Generated by tools/expected_upstream/ojluni_refresh_files.py
Test: N/A
Change-Id: Ifa908962909b43554576619bd04802730cb73e27
diff --git a/ojluni/src/main/java/java/text/DateFormat.java b/ojluni/src/main/java/java/text/DateFormat.java
index 5e70d67..2ee443c 100644
--- a/ojluni/src/main/java/java/text/DateFormat.java
+++ b/ojluni/src/main/java/java/text/DateFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -97,6 +97,13 @@
* DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
* }</pre>
* </blockquote>
+ *
+ * <p>If the specified locale contains "ca" (calendar), "rg" (region override),
+ * and/or "tz" (timezone) <a href="../util/Locale.html#def_locale_extension">Unicode
+ * extensions</a>, the calendar, the country and/or the time zone for formatting
+ * are overridden. If both "ca" and "rg" are specified, the calendar from the "ca"
+ * extension supersedes the implicit one from the "rg" extension.
+ *
* <p>You can use a DateFormat to parse also.
* <blockquote>
* <pre>{@code
@@ -133,7 +140,7 @@
* on the screen.
* </ul>
*
- * <h3><a name="synchronization">Synchronization</a></h3>
+ * <h3><a id="synchronization">Synchronization</a></h3>
*
* <p>
* Date formats are not synchronized.
@@ -141,6 +148,25 @@
* If multiple threads access a format concurrently, it must be synchronized
* externally.
*
+ * @implSpec
+ * <ul><li>The {@link #format(Date, StringBuffer, FieldPosition)} and
+ * {@link #parse(String, ParsePosition)} methods may throw
+ * {@code NullPointerException}, if any of their parameter is {@code null}.
+ * The subclass may provide its own implementation and specification about
+ * {@code NullPointerException}.</li>
+ * <li>The {@link #setCalendar(Calendar)}, {@link
+ * #setNumberFormat(NumberFormat)} and {@link #setTimeZone(TimeZone)} methods
+ * do not throw {@code NullPointerException} when their parameter is
+ * {@code null}, but any subsequent operations on the same instance may throw
+ * {@code NullPointerException}.</li>
+ * <li>The {@link #getCalendar()}, {@link #getNumberFormat()} and
+ * {@link getTimeZone()} methods may return {@code null}, if the respective
+ * values of this instance is set to {@code null} through the corresponding
+ * setter methods. For Example: {@link #getTimeZone()} may return {@code null},
+ * if the {@code TimeZone} value of this instance is set as
+ * {@link #setTimeZone(java.util.TimeZone) setTimeZone(null)}.</li>
+ * </ul>
+ *
* @see Format
* @see NumberFormat
* @see SimpleDateFormat
@@ -148,6 +174,7 @@
* @see java.util.GregorianCalendar
* @see java.util.TimeZone
* @author Mark Davis, Chen-Lieh Huang, Alan Liu
+ * @since 1.1
*/
public abstract class DateFormat extends Format {
@@ -175,127 +202,128 @@
* Useful constant for ERA field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int ERA_FIELD = 0;
+ public static final int ERA_FIELD = 0;
/**
* Useful constant for YEAR field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int YEAR_FIELD = 1;
+ public static final int YEAR_FIELD = 1;
/**
* Useful constant for MONTH field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int MONTH_FIELD = 2;
+ public static final int MONTH_FIELD = 2;
/**
* Useful constant for DATE field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int DATE_FIELD = 3;
+ public static final int DATE_FIELD = 3;
/**
* Useful constant for one-based HOUR_OF_DAY field alignment.
* Used in FieldPosition of date/time formatting.
* HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
* For example, 23:59 + 01:00 results in 24:59.
*/
- public final static int HOUR_OF_DAY1_FIELD = 4;
+ public static final int HOUR_OF_DAY1_FIELD = 4;
/**
* Useful constant for zero-based HOUR_OF_DAY field alignment.
* Used in FieldPosition of date/time formatting.
* HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
* For example, 23:59 + 01:00 results in 00:59.
*/
- public final static int HOUR_OF_DAY0_FIELD = 5;
+ public static final int HOUR_OF_DAY0_FIELD = 5;
/**
* Useful constant for MINUTE field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int MINUTE_FIELD = 6;
+ public static final int MINUTE_FIELD = 6;
/**
* Useful constant for SECOND field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int SECOND_FIELD = 7;
+ public static final int SECOND_FIELD = 7;
/**
* Useful constant for MILLISECOND field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int MILLISECOND_FIELD = 8;
+ public static final int MILLISECOND_FIELD = 8;
/**
* Useful constant for DAY_OF_WEEK field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int DAY_OF_WEEK_FIELD = 9;
+ public static final int DAY_OF_WEEK_FIELD = 9;
/**
* Useful constant for DAY_OF_YEAR field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int DAY_OF_YEAR_FIELD = 10;
+ public static final int DAY_OF_YEAR_FIELD = 10;
/**
* Useful constant for DAY_OF_WEEK_IN_MONTH field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
+ public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
/**
* Useful constant for WEEK_OF_YEAR field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int WEEK_OF_YEAR_FIELD = 12;
+ public static final int WEEK_OF_YEAR_FIELD = 12;
/**
* Useful constant for WEEK_OF_MONTH field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int WEEK_OF_MONTH_FIELD = 13;
+ public static final int WEEK_OF_MONTH_FIELD = 13;
/**
* Useful constant for AM_PM field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int AM_PM_FIELD = 14;
+ public static final int AM_PM_FIELD = 14;
/**
* Useful constant for one-based HOUR field alignment.
* Used in FieldPosition of date/time formatting.
* HOUR1_FIELD is used for the one-based 12-hour clock.
* For example, 11:30 PM + 1 hour results in 12:30 AM.
*/
- public final static int HOUR1_FIELD = 15;
+ public static final int HOUR1_FIELD = 15;
/**
* Useful constant for zero-based HOUR field alignment.
* Used in FieldPosition of date/time formatting.
* HOUR0_FIELD is used for the zero-based 12-hour clock.
* For example, 11:30 PM + 1 hour results in 00:30 AM.
*/
- public final static int HOUR0_FIELD = 16;
+ public static final int HOUR0_FIELD = 16;
/**
* Useful constant for TIMEZONE field alignment.
* Used in FieldPosition of date/time formatting.
*/
- public final static int TIMEZONE_FIELD = 17;
+ public static final int TIMEZONE_FIELD = 17;
// Proclaim serial compatibility with 1.1 FCS
private static final long serialVersionUID = 7218322306649953788L;
/**
- * Overrides Format.
- * Formats a time object into a time string. Examples of time objects
- * are a time value expressed in milliseconds and a Date object.
- * @param obj must be a Number or a Date.
- * @param toAppendTo the string buffer for the returning time string.
- * @return the string buffer passed in as toAppendTo, with formatted text appended.
- * @param fieldPosition keeps track of the position of the field
- * within the returned string.
- * On input: an alignment field,
- * if desired. On output: the offsets of the alignment field. For
- * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
- * if the given fieldPosition is DateFormat.YEAR_FIELD, the
- * begin index and end index of fieldPosition will be set to
- * 0 and 4, respectively.
- * Notice that if the same time field appears
- * more than once in a pattern, the fieldPosition will be set for the first
- * occurrence of that time field. For instance, formatting a Date to
- * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
- * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
- * the begin index and end index of fieldPosition will be set to
- * 5 and 8, respectively, for the first occurrence of the timezone
- * pattern character 'z'.
+ * Formats the given {@code Object} into a date-time string. The formatted
+ * string is appended to the given {@code StringBuffer}.
+ *
+ * @param obj Must be a {@code Date} or a {@code Number} representing a
+ * millisecond offset from the <a href="../util/Calendar.html#Epoch">Epoch</a>.
+ * @param toAppendTo The string buffer for the returning date-time string.
+ * @param fieldPosition keeps track on the position of the field within
+ * the returned string. For example, given a date-time text
+ * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
+ * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
+ * {@code fieldPosition} will be set to 0 and 4, respectively.
+ * Notice that if the same date-time field appears more than once in a
+ * pattern, the {@code fieldPosition} will be set for the first occurrence
+ * of that date-time field. For instance, formatting a {@code Date} to the
+ * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
+ * pattern {@code "h a z (zzzz)"} and the alignment field
+ * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
+ * {@code fieldPosition} will be set to 5 and 8, respectively, for the
+ * first occurrence of the timezone pattern character {@code 'z'}.
+ * @return the string buffer passed in as {@code toAppendTo},
+ * with formatted text appended.
+ * @exception IllegalArgumentException if the {@code Format} cannot format
+ * the given {@code obj}.
* @see java.text.Format
*/
public final StringBuffer format(Object obj, StringBuffer toAppendTo,
@@ -311,34 +339,35 @@
}
/**
- * Formats a Date into a date/time string.
- * @param date a Date to be formatted into a date/time string.
- * @param toAppendTo the string buffer for the returning date/time string.
- * @param fieldPosition keeps track of the position of the field
- * within the returned string.
- * On input: an alignment field,
- * if desired. On output: the offsets of the alignment field. For
- * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
- * if the given fieldPosition is DateFormat.YEAR_FIELD, the
- * begin index and end index of fieldPosition will be set to
- * 0 and 4, respectively.
- * Notice that if the same time field appears
- * more than once in a pattern, the fieldPosition will be set for the first
- * occurrence of that time field. For instance, formatting a Date to
- * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
- * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
- * the begin index and end index of fieldPosition will be set to
- * 5 and 8, respectively, for the first occurrence of the timezone
- * pattern character 'z'.
- * @return the string buffer passed in as toAppendTo, with formatted text appended.
+ * Formats a {@link Date} into a date-time string. The formatted
+ * string is appended to the given {@code StringBuffer}.
+ *
+ * @param date a Date to be formatted into a date-time string.
+ * @param toAppendTo the string buffer for the returning date-time string.
+ * @param fieldPosition keeps track on the position of the field within
+ * the returned string. For example, given a date-time text
+ * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
+ * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
+ * {@code fieldPosition} will be set to 0 and 4, respectively.
+ * Notice that if the same date-time field appears more than once in a
+ * pattern, the {@code fieldPosition} will be set for the first occurrence
+ * of that date-time field. For instance, formatting a {@code Date} to the
+ * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
+ * pattern {@code "h a z (zzzz)"} and the alignment field
+ * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
+ * {@code fieldPosition} will be set to 5 and 8, respectively, for the
+ * first occurrence of the timezone pattern character {@code 'z'}.
+ * @return the string buffer passed in as {@code toAppendTo}, with formatted
+ * text appended.
*/
public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition);
/**
- * Formats a Date into a date/time string.
- * @param date the time value to be formatted into a time string.
- * @return the formatted time string.
+ * Formats a {@link Date} into a date-time string.
+ *
+ * @param date the time value to be formatted into a date-time string.
+ * @return the formatted date-time string.
*/
public final String format(Date date)
{
@@ -418,7 +447,7 @@
* index information as described above.
* @return A <code>Date</code> parsed from the string. In case of
* error, returns null.
- * @exception NullPointerException if <code>pos</code> is null.
+ * @throws NullPointerException if {@code source} or {@code pos} is null.
*/
public Object parseObject(String source, ParsePosition pos) {
return parse(source, pos);
@@ -455,7 +484,7 @@
* @see java.util.Locale.Category#FORMAT
* @return a time formatter.
*/
- public final static DateFormat getTimeInstance()
+ public static final DateFormat getTimeInstance()
{
return get(DEFAULT, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
}
@@ -472,7 +501,7 @@
* SHORT for "h:mm a" in the US locale.
* @return a time formatter.
*/
- public final static DateFormat getTimeInstance(int style)
+ public static final DateFormat getTimeInstance(int style)
{
return get(style, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
}
@@ -485,7 +514,7 @@
* @param aLocale the given locale.
* @return a time formatter.
*/
- public final static DateFormat getTimeInstance(int style,
+ public static final DateFormat getTimeInstance(int style,
Locale aLocale)
{
return get(style, 0, 1, aLocale);
@@ -501,7 +530,7 @@
* @see java.util.Locale.Category#FORMAT
* @return a date formatter.
*/
- public final static DateFormat getDateInstance()
+ public static final DateFormat getDateInstance()
{
return get(0, DEFAULT, 2, Locale.getDefault(Locale.Category.FORMAT));
}
@@ -518,7 +547,7 @@
* SHORT for "M/d/yy" in the US locale.
* @return a date formatter.
*/
- public final static DateFormat getDateInstance(int style)
+ public static final DateFormat getDateInstance(int style)
{
return get(0, style, 2, Locale.getDefault(Locale.Category.FORMAT));
}
@@ -531,7 +560,7 @@
* @param aLocale the given locale.
* @return a date formatter.
*/
- public final static DateFormat getDateInstance(int style,
+ public static final DateFormat getDateInstance(int style,
Locale aLocale)
{
return get(0, style, 2, aLocale);
@@ -547,7 +576,7 @@
* @see java.util.Locale.Category#FORMAT
* @return a date/time formatter.
*/
- public final static DateFormat getDateTimeInstance()
+ public static final DateFormat getDateTimeInstance()
{
return get(DEFAULT, DEFAULT, 3, Locale.getDefault(Locale.Category.FORMAT));
}
@@ -566,7 +595,7 @@
* SHORT for "h:mm a" in the US locale.
* @return a date/time formatter.
*/
- public final static DateFormat getDateTimeInstance(int dateStyle,
+ public static final DateFormat getDateTimeInstance(int dateStyle,
int timeStyle)
{
return get(timeStyle, dateStyle, 3, Locale.getDefault(Locale.Category.FORMAT));
@@ -580,7 +609,7 @@
* @param aLocale the given locale.
* @return a date/time formatter.
*/
- public final static DateFormat
+ public static final DateFormat
getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale)
{
return get(timeStyle, dateStyle, 3, aLocale);
@@ -592,7 +621,7 @@
*
* @return a date/time formatter
*/
- public final static DateFormat getInstance() {
+ public static final DateFormat getInstance() {
return getDateTimeInstance(SHORT, SHORT);
}
@@ -934,107 +963,107 @@
/**
* Constant identifying the era field.
*/
- public final static Field ERA = new Field("era", Calendar.ERA);
+ public static final Field ERA = new Field("era", Calendar.ERA);
/**
* Constant identifying the year field.
*/
- public final static Field YEAR = new Field("year", Calendar.YEAR);
+ public static final Field YEAR = new Field("year", Calendar.YEAR);
/**
* Constant identifying the month field.
*/
- public final static Field MONTH = new Field("month", Calendar.MONTH);
+ public static final Field MONTH = new Field("month", Calendar.MONTH);
/**
* Constant identifying the day of month field.
*/
- public final static Field DAY_OF_MONTH = new
+ public static final Field DAY_OF_MONTH = new
Field("day of month", Calendar.DAY_OF_MONTH);
/**
* Constant identifying the hour of day field, where the legal values
* are 1 to 24.
*/
- public final static Field HOUR_OF_DAY1 = new Field("hour of day 1",-1);
+ public static final Field HOUR_OF_DAY1 = new Field("hour of day 1",-1);
/**
* Constant identifying the hour of day field, where the legal values
* are 0 to 23.
*/
- public final static Field HOUR_OF_DAY0 = new
+ public static final Field HOUR_OF_DAY0 = new
Field("hour of day", Calendar.HOUR_OF_DAY);
/**
* Constant identifying the minute field.
*/
- public final static Field MINUTE =new Field("minute", Calendar.MINUTE);
+ public static final Field MINUTE =new Field("minute", Calendar.MINUTE);
/**
* Constant identifying the second field.
*/
- public final static Field SECOND =new Field("second", Calendar.SECOND);
+ public static final Field SECOND =new Field("second", Calendar.SECOND);
/**
* Constant identifying the millisecond field.
*/
- public final static Field MILLISECOND = new
+ public static final Field MILLISECOND = new
Field("millisecond", Calendar.MILLISECOND);
/**
* Constant identifying the day of week field.
*/
- public final static Field DAY_OF_WEEK = new
+ public static final Field DAY_OF_WEEK = new
Field("day of week", Calendar.DAY_OF_WEEK);
/**
* Constant identifying the day of year field.
*/
- public final static Field DAY_OF_YEAR = new
+ public static final Field DAY_OF_YEAR = new
Field("day of year", Calendar.DAY_OF_YEAR);
/**
* Constant identifying the day of week field.
*/
- public final static Field DAY_OF_WEEK_IN_MONTH =
+ public static final Field DAY_OF_WEEK_IN_MONTH =
new Field("day of week in month",
Calendar.DAY_OF_WEEK_IN_MONTH);
/**
* Constant identifying the week of year field.
*/
- public final static Field WEEK_OF_YEAR = new
+ public static final Field WEEK_OF_YEAR = new
Field("week of year", Calendar.WEEK_OF_YEAR);
/**
* Constant identifying the week of month field.
*/
- public final static Field WEEK_OF_MONTH = new
+ public static final Field WEEK_OF_MONTH = new
Field("week of month", Calendar.WEEK_OF_MONTH);
/**
* Constant identifying the time of day indicator
* (e.g. "a.m." or "p.m.") field.
*/
- public final static Field AM_PM = new
+ public static final Field AM_PM = new
Field("am pm", Calendar.AM_PM);
/**
* Constant identifying the hour field, where the legal values are
* 1 to 12.
*/
- public final static Field HOUR1 = new Field("hour 1", -1);
+ public static final Field HOUR1 = new Field("hour 1", -1);
/**
* Constant identifying the hour field, where the legal values are
* 0 to 11.
*/
- public final static Field HOUR0 = new
+ public static final Field HOUR0 = new
Field("hour", Calendar.HOUR);
/**
* Constant identifying the time zone field.
*/
- public final static Field TIME_ZONE = new Field("time zone", -1);
+ public static final Field TIME_ZONE = new Field("time zone", -1);
}
}
diff --git a/ojluni/src/main/java/java/text/DateFormatSymbols.java b/ojluni/src/main/java/java/text/DateFormatSymbols.java
index 4fcde4e..7fecda2 100644
--- a/ojluni/src/main/java/java/text/DateFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DateFormatSymbols.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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
@@ -49,6 +49,7 @@
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
@@ -82,6 +83,10 @@
* </pre>
* </blockquote>
*
+ * <p>If the locale contains "rg" (region override)
+ * <a href="../util/Locale.html#def_locale_extension">Unicode extension</a>,
+ * the symbols are overridden for the designated region.
+ *
* <p>
* <code>DateFormatSymbols</code> objects are cloneable. When you obtain
* a <code>DateFormatSymbols</code> object, feel free to modify the
@@ -98,6 +103,7 @@
* @see SimpleDateFormat
* @see java.util.SimpleTimeZone
* @author Chen-Lieh Huang
+ * @since 1.1
*/
public class DateFormatSymbols implements Serializable, Cloneable {
@@ -221,7 +227,7 @@
* </ul>
* The zone ID is <em>not</em> localized; it's one of the valid IDs of
* the {@link java.util.TimeZone TimeZone} class that are not
- * <a href="../java/util/TimeZone.html#CustomID">custom IDs</a>.
+ * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
* All other entries are localized names.
* @see java.util.TimeZone
* @serial
@@ -388,6 +394,12 @@
/**
* Gets month strings. For example: "January", "February", etc.
+ * An array with either 12 or 13 elements will be returned depending
+ * on whether or not {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER}
+ * is supported. Use
+ * {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+ * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
+ * etc. to index the result array.
*
* <p>If the language requires different forms for formatting and
* stand-alone usages, this method returns month names in the
@@ -399,6 +411,8 @@
* Calendar Elements in the Unicode Locale Data Markup Language
* (LDML) specification</a> for more details.
*
+ * @implSpec This method returns 13 elements since
+ * {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER} is supported.
* @return the month strings.
*/
public String[] getMonths() {
@@ -407,7 +421,9 @@
/**
* Sets month strings. For example: "January", "February", etc.
- * @param newMonths the new month strings.
+ * @param newMonths the new month strings. The array should
+ * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+ * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
*/
public void setMonths(String[] newMonths) {
months = Arrays.copyOf(newMonths, newMonths.length);
@@ -416,9 +432,15 @@
/**
* Gets short month strings. For example: "Jan", "Feb", etc.
+ * An array with either 12 or 13 elements will be returned depending
+ * on whether or not {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER}
+ * is supported. Use
+ * {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+ * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
+ * etc. to index the result array.
*
* <p>If the language requires different forms for formatting and
- * stand-alone usages, This method returns short month names in
+ * stand-alone usages, this method returns short month names in
* the formatting form. For example, the preferred abbreviation
* for January in the Catalan language is <em>de gen.</em> in the
* formatting form, while it is <em>gen.</em> in the stand-alone
@@ -427,6 +449,8 @@
* Calendar Elements in the Unicode Locale Data Markup Language
* (LDML) specification</a> for more details.
*
+ * @implSpec This method returns 13 elements since
+ * {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER} is supported.
* @return the short month strings.
*/
public String[] getShortMonths() {
@@ -435,7 +459,9 @@
/**
* Sets short month strings. For example: "Jan", "Feb", etc.
- * @param newShortMonths the new short month strings.
+ * @param newShortMonths the new short month strings. The array should
+ * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+ * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
*/
public void setShortMonths(String[] newShortMonths) {
shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
@@ -444,8 +470,10 @@
/**
* Gets weekday strings. For example: "Sunday", "Monday", etc.
- * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
- * <code>Calendar.MONDAY</code>, etc. to index the result array.
+ * @return the weekday strings. Use
+ * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+ * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index
+ * the result array.
*/
public String[] getWeekdays() {
return Arrays.copyOf(weekdays, weekdays.length);
@@ -454,8 +482,8 @@
/**
* Sets weekday strings. For example: "Sunday", "Monday", etc.
* @param newWeekdays the new weekday strings. The array should
- * be indexed by <code>Calendar.SUNDAY</code>,
- * <code>Calendar.MONDAY</code>, etc.
+ * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+ * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc.
*/
public void setWeekdays(String[] newWeekdays) {
weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
@@ -464,8 +492,10 @@
/**
* Gets short weekday strings. For example: "Sun", "Mon", etc.
- * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
- * <code>Calendar.MONDAY</code>, etc. to index the result array.
+ * @return the short weekday strings. Use
+ * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+ * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index
+ * the result array.
*/
public String[] getShortWeekdays() {
return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
@@ -474,8 +504,8 @@
/**
* Sets short weekday strings. For example: "Sun", "Mon", etc.
* @param newShortWeekdays the new short weekday strings. The array should
- * be indexed by <code>Calendar.SUNDAY</code>,
- * <code>Calendar.MONDAY</code>, etc.
+ * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+ * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc.
*/
public void setShortWeekdays(String[] newShortWeekdays) {
shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
@@ -635,7 +665,9 @@
hashCode = 11 * hashCode + Arrays.hashCode(ampms);
hashCode = 11 * hashCode + Arrays.deepHashCode(getZoneStringsWrapper());
hashCode = 11 * hashCode + Objects.hashCode(localPatternChars);
- cachedHashCode = hashCode;
+ if (hashCode != 0) {
+ cachedHashCode = hashCode;
+ }
}
return hashCode;
@@ -675,12 +707,12 @@
private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
= new ConcurrentHashMap<>(3);
- private transient int lastZoneIndex = 0;
+ private transient int lastZoneIndex;
/**
* Cached hash code
*/
- transient volatile int cachedHashCode = 0;
+ transient volatile int cachedHashCode;
/**
* Initializes this DateFormatSymbols with the locale data. This method uses
@@ -699,15 +731,18 @@
}
dfs = new DateFormatSymbols(false);
+ // check for region override
+ Locale override = CalendarDataUtility.findRegionOverride(locale);
+
// Initialize the fields from the ResourceBundle for locale.
LocaleProviderAdapter adapter
- = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
+ = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, override);
// Avoid any potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
ResourceBundle resource
- = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
+ = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(override);
dfs.locale = locale;
// JRE and CLDR use different keys
@@ -742,16 +777,6 @@
dfs = y;
}
}
- // If the bundle's locale isn't the target locale, put another cache
- // entry for the bundle's locale.
- Locale bundleLocale = resource.getLocale();
- if (!bundleLocale.equals(locale)) {
- SoftReference<DateFormatSymbols> z
- = cachedInstances.putIfAbsent(bundleLocale, ref);
- if (z != null && z.get() == null) {
- cachedInstances.replace(bundleLocale, z, ref);
- }
- }
}
// Copy the field values from dfs to this instance.
diff --git a/ojluni/src/main/java/java/text/DecimalFormat.java b/ojluni/src/main/java/java/text/DecimalFormat.java
index a0020ba..950df6d 100644
--- a/ojluni/src/main/java/java/text/DecimalFormat.java
+++ b/ojluni/src/main/java/java/text/DecimalFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -172,75 +172,79 @@
* are not localized.
*
* <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
- * location, localized, and meaning.">
- * <tr style="background-color: rgb(204, 204, 255);">
- * <th align=left>Symbol
- * <th align=left>Location
- * <th align=left>Localized?
- * <th align=left>Meaning
- * <tr valign=top>
- * <td><code>0</code>
+ * <table class="striped">
+ * <caption style="display:none">Chart showing symbol, location, localized, and meaning.</caption>
+ * <thead>
+ * <tr>
+ * <th scope="col" style="text-align:left">Symbol
+ * <th scope="col" style="text-align:left">Location
+ * <th scope="col" style="text-align:left">Localized?
+ * <th scope="col" style="text-align:left">Meaning
+ * </thead>
+ * <tbody>
+ * <tr style="vertical-align:top">
+ * <th scope="row"><code>0</code>
* <td>Number
* <td>Yes
* <td>Digit
- * <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- * <td><code>#</code>
+ * <tr style="vertical-align: top">
+ * <th scope="row"><code>#</code>
* <td>Number
* <td>Yes
* <td>Digit, zero shows as absent
- * <tr valign=top>
- * <td><code>.</code>
+ * <tr style="vertical-align:top">
+ * <th scope="row"><code>.</code>
* <td>Number
* <td>Yes
* <td>Decimal separator or monetary decimal separator
- * <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- * <td><code>-</code>
+ * <tr style="vertical-align: top">
+ * <th scope="row"><code>-</code>
* <td>Number
* <td>Yes
* <td>Minus sign
- * <tr valign=top>
- * <td><code>,</code>
+ * <tr style="vertical-align:top">
+ * <th scope="row"><code>,</code>
* <td>Number
* <td>Yes
* <td>Grouping separator
- * <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- * <td><code>E</code>
+ * <tr style="vertical-align: top">
+ * <th scope="row"><code>E</code>
* <td>Number
* <td>Yes
* <td>Separates mantissa and exponent in scientific notation.
* <em>Need not be quoted in prefix or suffix.</em>
- * <tr valign=top>
- * <td><code>;</code>
+ * <tr style="vertical-align:top">
+ * <th scope="row"><code>;</code>
* <td>Subpattern boundary
* <td>Yes
* <td>Separates positive and negative subpatterns
- * <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- * <td><code>%</code>
+ * <tr style="vertical-align: top">
+ * <th scope="row"><code>%</code>
* <td>Prefix or suffix
* <td>Yes
* <td>Multiply by 100 and show as percentage
- * <tr valign=top>
- * <td><code>\u2030</code>
+ * <tr style="vertical-align:top">
+ * <th scope="row"><code>\u2030</code>
* <td>Prefix or suffix
* <td>Yes
* <td>Multiply by 1000 and show as per mille value
- * <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- * <td><code>¤</code> (<code>\u00A4</code>)
+ * <tr style="vertical-align: top">
+ * <th scope="row"><code>¤</code> (<code>\u00A4</code>)
* <td>Prefix or suffix
* <td>No
* <td>Currency sign, replaced by currency symbol. If
* doubled, replaced by international currency symbol.
* If present in a pattern, the monetary decimal separator
* is used instead of the decimal separator.
- * <tr valign=top>
- * <td><code>'</code>
+ * <tr style="vertical-align:top">
+ * <th scope="row"><code>'</code>
* <td>Prefix or suffix
* <td>No
* <td>Used to quote special characters in a prefix or suffix,
* for example, <code>"'#'#"</code> formats 123 to
* <code>"#123"</code>. To create a single quote
* itself, use two in a row: <code>"# o''clock"</code>.
+ * </tbody>
* </table>
* </blockquote>
*
@@ -327,7 +331,7 @@
* and <code>isParseIntegerOnly()</code> are false.
* </ul>
*
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
*
* <p>
* Decimal formats are generally not synchronized.
@@ -371,12 +375,13 @@
* }
* }</pre></blockquote>
*
- * @see <a href="https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
+ * @see <a href="http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
* @see NumberFormat
* @see DecimalFormatSymbols
* @see ParsePosition
* @author Mark Davis
* @author Alan Liu
+ * @since 1.1
*/
public class DecimalFormat extends NumberFormat {
@@ -475,8 +480,14 @@
* @param number the number to format
* @param toAppendTo the <code>StringBuffer</code> to which the formatted
* text is to be appended
- * @param pos On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param pos keeps track on the position of the field within the
+ * returned string. For example, for formatting a number
+ * {@code 1234567.89} in {@code Locale.US} locale,
+ * if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 9, respectively for the output string
+ * {@code 1,234,567.89}.
* @return the value passed in as <code>toAppendTo</code>
* @exception IllegalArgumentException if <code>number</code> is
* null or not an instance of <code>Number</code>.
@@ -512,8 +523,16 @@
* Formats a double to produce a string.
* @param number The double to format
* @param result where the text is to be appended
- * @param fieldPosition On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param fieldPosition keeps track on the position of the field within
+ * the returned string. For example, for formatting
+ * a number {@code 1234567.89} in {@code Locale.US}
+ * locale, if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 9, respectively for the output string
+ * {@code 1,234,567.89}.
+ * @exception NullPointerException if {@code result} or
+ * {@code fieldPosition} is {@code null}
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
* @return The formatted number string
@@ -630,8 +649,16 @@
* Format a long to produce a string.
* @param number The long to format
* @param result where the text is to be appended
- * @param fieldPosition On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param fieldPosition keeps track on the position of the field within
+ * the returned string. For example, for formatting
+ * a number {@code 123456789} in {@code Locale.US}
+ * locale, if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 11, respectively for the output string
+ * {@code 123,456,789}.
+ * @exception NullPointerException if {@code result} or
+ * {@code fieldPosition} is {@code null}
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
* @return The formatted number string
@@ -718,8 +745,14 @@
* Formats a BigDecimal to produce a string.
* @param number The BigDecimal to format
* @param result where the text is to be appended
- * @param fieldPosition On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param fieldPosition keeps track on the position of the field within
+ * the returned string. For example, for formatting
+ * a number {@code 1234567.89} in {@code Locale.US}
+ * locale, if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 9, respectively for the output string
+ * {@code 1,234,567.89}.
* @return The formatted number string
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
@@ -771,8 +804,14 @@
* Format a BigInteger to produce a string.
* @param number The BigInteger to format
* @param result where the text is to be appended
- * @param fieldPosition On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param fieldPosition keeps track on the position of the field within
+ * the returned string. For example, for formatting
+ * a number {@code 123456789} in {@code Locale.US}
+ * locale, if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 11, respectively for the output string
+ * {@code 123,456,789}.
* @return The formatted number string
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
@@ -968,7 +1007,7 @@
* Decimal : min = 0. max = 3.
*
*/
- private void checkAndSetFastPathStatus() {
+ private boolean checkAndSetFastPathStatus() {
boolean fastPathWasOn = isFastPath;
@@ -998,12 +1037,27 @@
} else
isFastPath = false;
+ resetFastPathData(fastPathWasOn);
+ fastPathCheckNeeded = false;
+
+ /*
+ * Returns true after successfully checking the fast path condition and
+ * setting the fast path data. The return value is used by the
+ * fastFormat() method to decide whether to call the resetFastPathData
+ * method to reinitialize fast path data or is it already initialized
+ * in this method.
+ */
+ return true;
+ }
+
+ private void resetFastPathData(boolean fastPathWasOn) {
// Since some instance properties may have changed while still falling
// in the fast-path case, we need to reinitialize fastPathData anyway.
if (isFastPath) {
// We need to instantiate fastPathData if not already done.
- if (fastPathData == null)
+ if (fastPathData == null) {
fastPathData = new FastPathData();
+ }
// Sets up the locale specific constants used when formatting.
// '0' is our default representation of zero.
@@ -1011,22 +1065,25 @@
fastPathData.groupingChar = symbols.getGroupingSeparator();
// Sets up fractional constants related to currency/decimal pattern.
- fastPathData.fractionalMaxIntBound = (isCurrencyFormat) ? 99 : 999;
- fastPathData.fractionalScaleFactor = (isCurrencyFormat) ? 100.0d : 1000.0d;
+ fastPathData.fractionalMaxIntBound = (isCurrencyFormat)
+ ? 99 : 999;
+ fastPathData.fractionalScaleFactor = (isCurrencyFormat)
+ ? 100.0d : 1000.0d;
// Records the need for adding prefix or suffix
- fastPathData.positiveAffixesRequired =
- (positivePrefix.length() != 0) || (positiveSuffix.length() != 0);
- fastPathData.negativeAffixesRequired =
- (negativePrefix.length() != 0) || (negativeSuffix.length() != 0);
+ fastPathData.positiveAffixesRequired
+ = !positivePrefix.isEmpty() || !positiveSuffix.isEmpty();
+ fastPathData.negativeAffixesRequired
+ = !negativePrefix.isEmpty() || !negativeSuffix.isEmpty();
// Creates a cached char container for result, with max possible size.
int maxNbIntegralDigits = 10;
int maxNbGroups = 3;
- int containerSize =
- Math.max(positivePrefix.length(), negativePrefix.length()) +
- maxNbIntegralDigits + maxNbGroups + 1 + maximumFractionDigits +
- Math.max(positiveSuffix.length(), negativeSuffix.length());
+ int containerSize
+ = Math.max(positivePrefix.length(), negativePrefix.length())
+ + maxNbIntegralDigits + maxNbGroups + 1
+ + maximumFractionDigits
+ + Math.max(positiveSuffix.length(), negativeSuffix.length());
fastPathData.fastPathContainer = new char[containerSize];
@@ -1038,17 +1095,18 @@
// Sets up fixed index positions for integral and fractional digits.
// Sets up decimal point in cached result container.
- int longestPrefixLength =
- Math.max(positivePrefix.length(), negativePrefix.length());
- int decimalPointIndex =
- maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
+ int longestPrefixLength
+ = Math.max(positivePrefix.length(),
+ negativePrefix.length());
+ int decimalPointIndex
+ = maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
- fastPathData.integralLastIndex = decimalPointIndex - 1;
+ fastPathData.integralLastIndex = decimalPointIndex - 1;
fastPathData.fractionalFirstIndex = decimalPointIndex + 1;
- fastPathData.fastPathContainer[decimalPointIndex] =
- isCurrencyFormat ?
- symbols.getMonetaryDecimalSeparator() :
- symbols.getDecimalSeparator();
+ fastPathData.fastPathContainer[decimalPointIndex]
+ = isCurrencyFormat
+ ? symbols.getMonetaryDecimalSeparator()
+ : symbols.getDecimalSeparator();
} else if (fastPathWasOn) {
// Previous state was fast-path and is no more.
@@ -1059,8 +1117,6 @@
fastPathData.charsPositivePrefix = null;
fastPathData.charsNegativePrefix = null;
}
-
- fastPathCheckNeeded = false;
}
/**
@@ -1554,9 +1610,11 @@
* @return the formatted result for {@code d} as a string.
*/
String fastFormat(double d) {
+ boolean isDataSet = false;
// (Re-)Evaluates fast-path status if needed.
- if (fastPathCheckNeeded)
- checkAndSetFastPathStatus();
+ if (fastPathCheckNeeded) {
+ isDataSet = checkAndSetFastPathStatus();
+ }
if (!isFastPath )
// DecimalFormat instance is not in a fast-path state.
@@ -1580,9 +1638,21 @@
if (d > MAX_INT_AS_DOUBLE)
// Filters out values that are outside expected fast-path range
return null;
- else
+ else {
+ if (!isDataSet) {
+ /*
+ * If the fast path data is not set through
+ * checkAndSetFastPathStatus() and fulfil the
+ * fast path conditions then reset the data
+ * directly through resetFastPathData()
+ */
+ resetFastPathData(isFastPath);
+ }
fastDoubleFormat(d, negative);
+ }
+
+
// Returns a new string from updated fastPathContainer.
return new String(fastPathData.fastPathContainer,
fastPathData.firstUsedIndex,
@@ -1918,7 +1988,7 @@
Format.Field signAttribute) {
int start = result.length();
- if (string.length() > 0) {
+ if (!string.isEmpty()) {
result.append(string);
for (int counter = 0, max = positions.length; counter < max;
counter++) {
@@ -1996,7 +2066,7 @@
// special case NaN
if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
pos.index = pos.index + symbols.getNaN().length();
- return new Double(Double.NaN);
+ return Double.valueOf(Double.NaN);
}
boolean[] status = new boolean[STATUS_LENGTH];
@@ -2007,19 +2077,19 @@
// special case INFINITY
if (status[STATUS_INFINITE]) {
if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
- return new Double(Double.POSITIVE_INFINITY);
+ return Double.valueOf(Double.POSITIVE_INFINITY);
} else {
- return new Double(Double.NEGATIVE_INFINITY);
+ return Double.valueOf(Double.NEGATIVE_INFINITY);
}
}
if (multiplier == 0) {
if (digitList.isZero()) {
- return new Double(Double.NaN);
+ return Double.valueOf(Double.NaN);
} else if (status[STATUS_POSITIVE]) {
- return new Double(Double.POSITIVE_INFINITY);
+ return Double.valueOf(Double.POSITIVE_INFINITY);
} else {
- return new Double(Double.NEGATIVE_INFINITY);
+ return Double.valueOf(Double.NEGATIVE_INFINITY);
}
}
@@ -2093,8 +2163,8 @@
!isParseIntegerOnly();
}
- return gotDouble ?
- (Number)new Double(doubleResult) : (Number)new Long(longResult);
+ // cast inside of ?: because of binary numeric promotion, JLS 15.25
+ return gotDouble ? (Number)doubleResult : (Number)longResult;
}
}
@@ -2873,7 +2943,7 @@
} else {
string = symbols.getCurrencySymbol();
}
- if (string.length() > 0) {
+ if (!string.isEmpty()) {
if (positions == null) {
positions = new ArrayList<>(2);
}
@@ -3160,13 +3230,6 @@
isCurrencyFormat = false;
useExponentialNotation = false;
- // Two variables are used to record the subrange of the pattern
- // occupied by phase 1. This is used during the processing of the
- // second pattern (the one representing negative numbers) to ensure
- // that no deviation exists in phase 1 between the two patterns.
- int phaseOneStart = 0;
- int phaseOneLength = 0;
-
int start = 0;
for (int j = 1; j >= 0 && start < pattern.length(); --j) {
boolean inQuote = false;
@@ -3217,9 +3280,6 @@
ch == groupingSeparator ||
ch == decimalSeparator) {
phase = 1;
- if (j == 1) {
- phaseOneStart = pos;
- }
--pos; // Reprocess this character
continue;
} else if (ch == CURRENCY_SIGN) {
@@ -3290,17 +3350,29 @@
break;
case 1:
- // Phase one must be identical in the two sub-patterns. We
- // enforce this by doing a direct comparison. While
- // processing the first sub-pattern, we just record its
- // length. While processing the second, we compare
- // characters.
- if (j == 1) {
- ++phaseOneLength;
- } else {
- if (--phaseOneLength == 0) {
- phase = 2;
- affix = suffix;
+ // The negative subpattern (j = 0) serves only to specify the
+ // negative prefix and suffix, so all the phase 1 characters
+ // e.g. digits, zeroDigit, groupingSeparator,
+ // decimalSeparator, exponent are ignored
+ if (j == 0) {
+ while (pos < pattern.length()) {
+ char negPatternChar = pattern.charAt(pos);
+ if (negPatternChar == digit
+ || negPatternChar == zeroDigit
+ || negPatternChar == groupingSeparator
+ || negPatternChar == decimalSeparator) {
+ ++pos;
+ } else if (pattern.regionMatches(pos, exponent,
+ 0, exponent.length())) {
+ pos = pos + exponent.length();
+ } else {
+ // Not a phase 1 character, consider it as
+ // suffix and parse it in phase 2
+ --pos; //process it again in outer loop
+ phase = 2;
+ affix = suffix;
+ break;
+ }
}
continue;
}
@@ -3354,7 +3426,6 @@
while (pos < pattern.length() &&
pattern.charAt(pos) == zeroDigit) {
++minExponentDigits;
- ++phaseOneLength;
++pos;
}
@@ -3373,7 +3444,6 @@
phase = 2;
affix = suffix;
--pos;
- --phaseOneLength;
continue;
}
break;
@@ -3444,7 +3514,7 @@
}
}
- if (pattern.length() == 0) {
+ if (pattern.isEmpty()) {
posPrefixPattern = posSuffixPattern = "";
setMinimumIntegerDigits(0);
setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
diff --git a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
index 55a344f..acaf3bf 100644
--- a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -42,14 +42,9 @@
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.text.spi.DecimalFormatSymbolsProvider;
-import java.util.ArrayList;
import java.util.Currency;
-import java.util.List;
import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
@@ -62,10 +57,15 @@
* of these symbols, you can get the <code>DecimalFormatSymbols</code> object from
* your <code>DecimalFormat</code> and modify it.
*
+ * <p>If the locale contains "rg" (region override)
+ * <a href="../util/Locale.html#def_locale_extension">Unicode extension</a>,
+ * the symbols are overridden for the designated region.
+ *
* @see java.util.Locale
* @see DecimalFormat
* @author Mark Davis
* @author Alan Liu
+ * @since 1.1
*/
public class DecimalFormatSymbols implements Cloneable, Serializable {
@@ -384,6 +384,7 @@
*/
public String getCurrencySymbol()
{
+ initializeCurrency(locale);
return currencySymbol;
}
@@ -396,6 +397,7 @@
*/
public void setCurrencySymbol(String currency)
{
+ initializeCurrency(locale);
currencySymbol = currency;
}
@@ -408,6 +410,7 @@
*/
public String getInternationalCurrencySymbol()
{
+ initializeCurrency(locale);
return intlCurrencySymbol;
}
@@ -429,6 +432,7 @@
*/
public void setInternationalCurrencySymbol(String currencyCode)
{
+ initializeCurrency(locale);
intlCurrencySymbol = currencyCode;
currency = null;
if (currencyCode != null) {
@@ -449,6 +453,7 @@
* @since 1.4
*/
public Currency getCurrency() {
+ initializeCurrency(locale);
return currency;
}
@@ -468,6 +473,7 @@
if (currency == null) {
throw new NullPointerException();
}
+ initializeCurrency(locale);
this.currency = currency;
intlCurrencySymbol = currency.getCurrencyCode();
currencySymbol = currency.getSymbol(locale);
@@ -507,14 +513,15 @@
{
return exponential;
}
- /**
- * Returns the string used to separate the mantissa from the exponent.
- * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
- *
- * @return the exponent separator string
- * @see #setExponentSeparator(java.lang.String)
- * @since 1.6
- */
+
+ /**
+ * Returns the string used to separate the mantissa from the exponent.
+ * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
+ *
+ * @return the exponent separator string
+ * @see #setExponentSeparator(java.lang.String)
+ * @since 1.6
+ */
public String getExponentSeparator()
{
return exponentialSeparator;
@@ -528,22 +535,22 @@
exponential = exp;
}
- /**
- * Sets the string used to separate the mantissa from the exponent.
- * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
- *
- * @param exp the exponent separator string
- * @exception NullPointerException if <code>exp</code> is null
- * @see #getExponentSeparator()
- * @since 1.6
- */
+ /**
+ * Sets the string used to separate the mantissa from the exponent.
+ * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
+ *
+ * @param exp the exponent separator string
+ * @exception NullPointerException if <code>exp</code> is null
+ * @see #getExponentSeparator()
+ * @since 1.6
+ */
public void setExponentSeparator(String exp)
{
if (exp == null) {
throw new NullPointerException();
}
exponentialSeparator = exp;
- }
+ }
//------------------------------------------------------------
@@ -582,7 +589,7 @@
patternSeparator == other.patternSeparator &&
infinity.equals(other.infinity) &&
NaN.equals(other.NaN) &&
- currencySymbol.equals(other.currencySymbol) &&
+ getCurrencySymbol().equals(other.getCurrencySymbol()) && // possible currency init occurs here
intlCurrencySymbol.equals(other.intlCurrencySymbol) &&
currency == other.currency &&
monetarySeparator == other.monetarySeparator &&
@@ -607,13 +614,18 @@
private void initialize( Locale locale ) {
this.locale = locale;
+ // check for region override
+ Locale override = locale.getUnicodeLocaleType("nu") == null ?
+ CalendarDataUtility.findRegionOverride(locale) :
+ locale;
+
// get resource bundle data
- LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+ LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, override);
// Avoid potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
- Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();
+ Object[] data = adapter.getLocaleResources(override).getDecimalFormatSymbolsData();
String[] numberElements = (String[]) data[0];
decimalSeparator = numberElements[0].charAt(0);
@@ -629,18 +641,45 @@
infinity = numberElements[9];
NaN = numberElements[10];
+ // maybe filled with previously cached values, or null.
+ intlCurrencySymbol = (String) data[1];
+ currencySymbol = (String) data[2];
+
+ // Currently the monetary decimal separator is the same as the
+ // standard decimal separator for all locales that we support.
+ // If that changes, add a new entry to NumberElements.
+ monetarySeparator = decimalSeparator;
+ }
+
+ /**
+ * Lazy initialization for currency related fields
+ */
+ private void initializeCurrency(Locale locale) {
+ if (currencyInitialized) {
+ return;
+ }
+
// Try to obtain the currency used in the locale's country.
// Check for empty country string separately because it's a valid
// country ID for Locale (and used for the C locale), but not a valid
// ISO 3166 country code, and exceptions are expensive.
- if (locale.getCountry().length() > 0) {
+ if (!locale.getCountry().isEmpty()) {
try {
currency = Currency.getInstance(locale);
} catch (IllegalArgumentException e) {
// use default values below for compatibility
}
}
+
if (currency != null) {
+ // get resource bundle data
+ LocaleProviderAdapter adapter =
+ LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+ // Avoid potential recursions
+ if (!(adapter instanceof ResourceBundleBasedAdapter)) {
+ adapter = LocaleProviderAdapter.getResourceBundleBased();
+ }
+ Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();
intlCurrencySymbol = currency.getCurrencyCode();
if (data[1] != null && data[1] == intlCurrencySymbol) {
currencySymbol = (String) data[2];
@@ -658,10 +697,8 @@
}
currencySymbol = "\u00A4";
}
- // Currently the monetary decimal separator is the same as the
- // standard decimal separator for all locales that we support.
- // If that changes, add a new entry to NumberElements.
- monetarySeparator = decimalSeparator;
+
+ currencyInitialized = true;
}
/**
@@ -679,7 +716,7 @@
* default serialization will work properly if this object is streamed out again.
* Initializes the currency from the intlCurrencySymbol field.
*
- * @since JDK 1.1.6
+ * @since 1.1.6
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
@@ -705,6 +742,7 @@
currency = Currency.getInstance(intlCurrencySymbol);
} catch (IllegalArgumentException e) {
}
+ currencyInitialized = true;
}
}
@@ -802,7 +840,7 @@
/**
* The decimal separator used when formatting currency values.
* @serial
- * @since JDK 1.1.6
+ * @since 1.1.6
* @see #getMonetaryDecimalSeparator
*/
private char monetarySeparator; // Field new in JDK 1.1.6
@@ -816,20 +854,20 @@
* The intent is that this will be added to the API in the future.
*
* @serial
- * @since JDK 1.1.6
+ * @since 1.1.6
*/
private char exponential; // Field new in JDK 1.1.6
- /**
- * The string used to separate the mantissa from the exponent.
- * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
- * <p>
- * If both <code>exponential</code> and <code>exponentialSeparator</code>
- * exist, this <code>exponentialSeparator</code> has the precedence.
- *
- * @serial
- * @since 1.6
- */
+ /**
+ * The string used to separate the mantissa from the exponent.
+ * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
+ * <p>
+ * If both <code>exponential</code> and <code>exponentialSeparator</code>
+ * exist, this <code>exponentialSeparator</code> has the precedence.
+ *
+ * @serial
+ * @since 1.6
+ */
private String exponentialSeparator; // Field new in JDK 1.6
/**
@@ -842,6 +880,7 @@
// currency; only the ISO code is serialized.
private transient Currency currency;
+ private transient volatile boolean currencyInitialized;
// Proclaim JDK 1.1 FCS compatibility
static final long serialVersionUID = 5772796243397350300L;
@@ -872,7 +911,7 @@
* is always written.
*
* @serial
- * @since JDK 1.1.6
+ * @since 1.1.6
*/
private int serialVersionOnStream = currentSerialVersion;
}
diff --git a/ojluni/src/main/java/java/text/MessageFormat.java b/ojluni/src/main/java/java/text/MessageFormat.java
index 2497a49..e54033c 100644
--- a/ojluni/src/main/java/java/text/MessageFormat.java
+++ b/ojluni/src/main/java/java/text/MessageFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -68,7 +68,7 @@
* behavior is defined by the pattern that you provide as well as the
* subformats used for inserted arguments.
*
- * <h3><a name="patterns">Patterns and Their Interpretation</a></h3>
+ * <h3><a id="patterns">Patterns and Their Interpretation</a></h3>
*
* <code>MessageFormat</code> uses patterns of the following form:
* <blockquote><pre>
@@ -146,73 +146,78 @@
* shown in the table are illegal. A <i>SubformatPattern</i> must
* be a valid pattern string for the {@code Format} subclass used.
*
- * <table border=1 summary="Shows how FormatType and FormatStyle values map to Format instances">
+ * <table class="plain">
+ * <caption style="display:none">Shows how FormatType and FormatStyle values map to Format instances</caption>
+ * <thead>
* <tr>
- * <th id="ft" class="TableHeadingColor">FormatType
- * <th id="fs" class="TableHeadingColor">FormatStyle
- * <th id="sc" class="TableHeadingColor">Subformat Created
+ * <th scope="col" class="TableHeadingColor">FormatType
+ * <th scope="col" class="TableHeadingColor">FormatStyle
+ * <th scope="col" class="TableHeadingColor">Subformat Created
+ * </thead>
+ * <tbody>
* <tr>
- * <td headers="ft"><i>(none)</i>
- * <td headers="fs"><i>(none)</i>
- * <td headers="sc"><code>null</code>
+ * <th scope="row" style="text-weight: normal"><i>(none)</i>
+ * <th scope="row" style="text-weight: normal"><i>(none)</i>
+ * <td>{@code null}
* <tr>
- * <td headers="ft" rowspan=5><code>number</code>
- * <td headers="fs"><i>(none)</i>
- * <td headers="sc">{@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())}
+ * <th scope="row" style="text-weight: normal" rowspan=5>{@code number}
+ * <th scope="row" style="text-weight: normal"><i>(none)</i>
+ * <td>{@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())}
* <tr>
- * <td headers="fs"><code>integer</code>
- * <td headers="sc">{@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code integer}
+ * <td>{@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())}
* <tr>
- * <td headers="fs"><code>currency</code>
- * <td headers="sc">{@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code currency}
+ * <td>{@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())}
* <tr>
- * <td headers="fs"><code>percent</code>
- * <td headers="sc">{@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code percent}
+ * <td>{@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())}
* <tr>
- * <td headers="fs"><i>SubformatPattern</i>
- * <td headers="sc">{@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))}
+ * <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ * <td>{@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))}
* <tr>
- * <td headers="ft" rowspan=6><code>date</code>
- * <td headers="fs"><i>(none)</i>
- * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal" rowspan=6>{@code date}
+ * <th scope="row" style="text-weight: normal"><i>(none)</i>
+ * <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>short</code>
- * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code short}
+ * <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>medium</code>
- * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code medium}
+ * <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>long</code>
- * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code long}
+ * <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>full</code>
- * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code full}
+ * <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
* <tr>
- * <td headers="fs"><i>SubformatPattern</i>
- * <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
+ * <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ * <td>{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
* <tr>
- * <td headers="ft" rowspan=6><code>time</code>
- * <td headers="fs"><i>(none)</i>
- * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal" rowspan=6>{@code time}
+ * <th scope="row" style="text-weight: normal"><i>(none)</i>
+ * <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>short</code>
- * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code short}
+ * <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>medium</code>
- * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code medium}
+ * <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>long</code>
- * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code long}
+ * <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
* <tr>
- * <td headers="fs"><code>full</code>
- * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
+ * <th scope="row" style="text-weight: normal">{@code full}
+ * <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
* <tr>
- * <td headers="fs"><i>SubformatPattern</i>
- * <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
+ * <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ * <td>{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
* <tr>
- * <td headers="ft"><code>choice</code>
- * <td headers="fs"><i>SubformatPattern</i>
- * <td headers="sc">{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)}
+ * <th scope="row" style="text-weight: normal">{@code choice}
+ * <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ * <td>{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)}
+ * </tbody>
* </table>
*
* <h4>Usage Information</h4>
@@ -321,7 +326,7 @@
* // result now equals {new String("z")}
* </pre></blockquote>
*
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
*
* <p>
* Message formats are not synchronized.
@@ -339,6 +344,7 @@
* @see SimpleDateFormat
*
* @author Mark Davis
+ * @since 1.1
*/
public class MessageFormat extends Format {
@@ -356,6 +362,8 @@
*
* @param pattern the pattern for this message format
* @exception IllegalArgumentException if the pattern is invalid
+ * @exception NullPointerException if {@code pattern} is
+ * {@code null}
*/
public MessageFormat(String pattern) {
this.locale = Locale.getDefault(Locale.Category.FORMAT);
@@ -373,6 +381,8 @@
* @param pattern the pattern for this message format
* @param locale the locale for this message format
* @exception IllegalArgumentException if the pattern is invalid
+ * @exception NullPointerException if {@code pattern} is
+ * {@code null}
* @since 1.4
*/
public MessageFormat(String pattern, Locale locale) {
@@ -420,6 +430,8 @@
*
* @param pattern the pattern for this message format
* @exception IllegalArgumentException if the pattern is invalid
+ * @exception NullPointerException if {@code pattern} is
+ * {@code null}
*/
@SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
public void applyPattern(String pattern) {
@@ -689,6 +701,10 @@
* larger than the number of format elements in the pattern string
*/
public void setFormat(int formatElementIndex, Format newFormat) {
+
+ if (formatElementIndex > maxOffset) {
+ throw new ArrayIndexOutOfBoundsException(formatElementIndex);
+ }
formats[formatElementIndex] = newFormat;
}
@@ -760,45 +776,46 @@
* argument is <i>unavailable</i> if <code>arguments</code> is
* <code>null</code> or has fewer than argumentIndex+1 elements.
*
- * <table border=1 summary="Examples of subformat,argument,and formatted text">
+ * <table class="plain">
+ * <caption style="display:none">Examples of subformat,argument,and formatted text</caption>
+ * <thead>
* <tr>
- * <th>Subformat
- * <th>Argument
- * <th>Formatted Text
+ * <th scope="col">Subformat
+ * <th scope="col">Argument
+ * <th scope="col">Formatted Text
+ * </thead>
+ * <tbody>
* <tr>
- * <td><i>any</i>
- * <td><i>unavailable</i>
+ * <th scope="row" style="text-weight-normal" rowspan=2><i>any</i>
+ * <th scope="row" style="text-weight-normal"><i>unavailable</i>
* <td><code>"{" + argumentIndex + "}"</code>
* <tr>
- * <td><i>any</i>
- * <td><code>null</code>
+ * <th scope="row" style="text-weight-normal"><code>null</code>
* <td><code>"null"</code>
* <tr>
- * <td><code>instanceof ChoiceFormat</code>
- * <td><i>any</i>
+ * <th scope="row" style="text-weight-normal"><code>instanceof ChoiceFormat</code>
+ * <th scope="row" style="text-weight-normal"><i>any</i>
* <td><code>subformat.format(argument).indexOf('{') >= 0 ?<br>
* (new MessageFormat(subformat.format(argument), getLocale())).format(argument) :
* subformat.format(argument)</code>
* <tr>
- * <td><code>!= null</code>
- * <td><i>any</i>
+ * <th scope="row" style="text-weight-normal"><code>!= null</code>
+ * <th scope="row" style="text-weight-normal"><i>any</i>
* <td><code>subformat.format(argument)</code>
* <tr>
- * <td><code>null</code>
- * <td><code>instanceof Number</code>
+ * <th scope="row" style="text-weight-normal" rowspan=4><code>null</code>
+ * <th scope="row" style="text-weight-normal"><code>instanceof Number</code>
* <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
* <tr>
- * <td><code>null</code>
- * <td><code>instanceof Date</code>
+ * <th scope="row" style="text-weight-normal"><code>instanceof Date</code>
* <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()).format(argument)</code>
* <tr>
- * <td><code>null</code>
- * <td><code>instanceof String</code>
+ * <th scope="row" style="text-weight-normal"><code>instanceof String</code>
* <td><code>argument</code>
* <tr>
- * <td><code>null</code>
- * <td><i>any</i>
+ * <th scope="row" style="text-weight-normal"><i>any</i>
* <td><code>argument.toString()</code>
+ * </tbody>
* </table>
* <p>
* If <code>pos</code> is non-null, and refers to
@@ -807,13 +824,14 @@
*
* @param arguments an array of objects to be formatted and substituted.
* @param result where text is appended.
- * @param pos On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param pos keeps track on the position of the first replaced argument
+ in the output string.
* @return the string buffer passed in as {@code result}, with formatted
* text appended
* @exception IllegalArgumentException if an argument in the
* <code>arguments</code> array is not of the type
* expected by the format element(s) that use it.
+ * @exception NullPointerException if {@code result} is {@code null}
*/
public final StringBuffer format(Object[] arguments, StringBuffer result,
FieldPosition pos)
@@ -835,6 +853,7 @@
* or if an argument in the <code>arguments</code> array
* is not of the type expected by the format element(s)
* that use it.
+ * @exception NullPointerException if {@code pattern} is {@code null}
*/
public static String format(String pattern, Object ... arguments) {
MessageFormat temp = new MessageFormat(pattern);
@@ -853,11 +872,12 @@
*
* @param arguments an array of objects to be formatted and substituted.
* @param result where text is appended.
- * @param pos On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param pos keeps track on the position of the first replaced argument
+ * in the output string.
* @exception IllegalArgumentException if an argument in the
* <code>arguments</code> array is not of the type
* expected by the format element(s) that use it.
+ * @exception NullPointerException if {@code result} is {@code null}
*/
public final StringBuffer format(Object arguments, StringBuffer result,
FieldPosition pos)
@@ -947,6 +967,8 @@
* @param source the string to parse
* @param pos the parse position
* @return an array of parsed objects
+ * @exception NullPointerException if {@code pos} is {@code null}
+ * for a non-null {@code source} string.
*/
public Object[] parse(String source, ParsePosition pos) {
if (source == null) {
@@ -1068,7 +1090,7 @@
* index information as described above.
* @return An <code>Object</code> array parsed from the string. In case of
* error, returns null.
- * @exception NullPointerException if <code>pos</code> is null.
+ * @throws NullPointerException if {@code pos} is null.
*/
public Object parseObject(String source, ParsePosition pos) {
return parse(source, pos);
@@ -1168,7 +1190,7 @@
* indicating the index in the <code>arguments</code> array of the
* argument from which the text was generated.
*/
- public final static Field ARGUMENT =
+ public static final Field ARGUMENT =
new Field("message argument field");
}
@@ -1221,11 +1243,11 @@
private int maxOffset = -1;
/**
- * Internal routine used by format. If <code>characterIterators</code> is
- * non-null, AttributedCharacterIterator will be created from the
- * subformats as necessary. If <code>characterIterators</code> is null
- * and <code>fp</code> is non-null and identifies
- * <code>Field.MESSAGE_ARGUMENT</code>, the location of
+ * Internal routine used by format. If {@code characterIterators} is
+ * {@code non-null}, AttributedCharacterIterator will be created from the
+ * subformats as necessary. If {@code characterIterators} is {@code null}
+ * and {@code fp} is {@code non-null} and identifies
+ * {@code Field.ARGUMENT} as the field attribute, the location of
* the first replaced argument will be set in it.
*
* @exception IllegalArgumentException if an argument in the
@@ -1239,7 +1261,7 @@
int lastOffset = 0;
int last = result.length();
for (int i = 0; i <= maxOffset; ++i) {
- result.append(pattern.substring(lastOffset, offsets[i]));
+ result.append(pattern, lastOffset, offsets[i]);
lastOffset = offsets[i];
int argumentNumber = argumentNumbers[i];
if (arguments == null || argumentNumber >= arguments.length) {
@@ -1308,7 +1330,7 @@
}
arg = null;
}
- if (arg != null && arg.length() > 0) {
+ if (arg != null && !arg.isEmpty()) {
result.append(arg);
characterIterators.add(
createAttributedCharacterIterator(
@@ -1332,7 +1354,7 @@
}
}
}
- result.append(pattern.substring(lastOffset, pattern.length()));
+ result.append(pattern, lastOffset, pattern.length());
if (characterIterators != null && last != result.length()) {
characterIterators.add(createAttributedCharacterIterator(
result.substring(last)));
@@ -1454,7 +1476,7 @@
// now get the format
Format newFormat = null;
- if (segments[SEG_TYPE].length() != 0) {
+ if (!segments[SEG_TYPE].isEmpty()) {
int type = findKeyword(segments[SEG_TYPE], TYPE_KEYWORDS);
switch (type) {
case TYPE_NULL:
diff --git a/ojluni/src/main/java/java/text/NumberFormat.java b/ojluni/src/main/java/java/text/NumberFormat.java
index 2fdcad6..a1de3fe 100644
--- a/ojluni/src/main/java/java/text/NumberFormat.java
+++ b/ojluni/src/main/java/java/text/NumberFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -96,7 +96,14 @@
* NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
* }</pre>
* </blockquote>
- * You can also use a <code>NumberFormat</code> to parse numbers:
+ *
+ * <p>If the locale contains "nu" (numbers) and/or "rg" (region override)
+ * <a href="../util/Locale.html#def_locale_extension">Unicode extensions</a>,
+ * the decimal digits, and/or the country used for formatting are overridden.
+ * If both "nu" and "rg" are specified, the decimal digits from the "nu"
+ * extension supersedes the implicit one from the "rg" extension.
+ *
+ * <p>You can also use a {@code NumberFormat} to parse numbers:
* <blockquote>
* <pre>{@code
* myNumber = nf.parse(myString);
@@ -166,7 +173,7 @@
* numbers: "(12)" for -12.
* </ol>
*
- * <h3><a name="synchronization">Synchronization</a></h3>
+ * <h3><a id="synchronization">Synchronization</a></h3>
*
* <p>
* Number formats are generally not synchronized.
@@ -174,10 +181,29 @@
* If multiple threads access a format concurrently, it must be synchronized
* externally.
*
+ * @implSpec The {@link #format(double, StringBuffer, FieldPosition)},
+ * {@link #format(long, StringBuffer, FieldPosition)} and
+ * {@link #parse(String, ParsePosition)} methods may throw
+ * {@code NullPointerException}, if any of their parameter is {@code null}.
+ * The subclass may provide its own implementation and specification about
+ * {@code NullPointerException}.
+ *
+ * <p>
+ * The default implementation provides rounding modes defined
+ * in {@link java.math.RoundingMode} for formatting numbers. It
+ * uses the {@linkplain java.math.RoundingMode#HALF_EVEN
+ * round half-even algorithm}. To change the rounding mode use
+ * {@link #setRoundingMode(java.math.RoundingMode) setRoundingMode}.
+ * The {@code NumberFormat} returned by the static factory methods is
+ * configured to round floating point numbers using half-even
+ * rounding (see {@link java.math.RoundingMode#HALF_EVEN
+ * RoundingMode.HALF_EVEN}) for formatting.
+ *
* @see DecimalFormat
* @see ChoiceFormat
* @author Mark Davis
* @author Helena Shih
+ * @since 1.1
*/
public abstract class NumberFormat extends Format {
@@ -221,8 +247,14 @@
* @param number the number to format
* @param toAppendTo the <code>StringBuffer</code> to which the formatted
* text is to be appended
- * @param pos On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param pos keeps track on the position of the field within the
+ * returned string. For example, for formatting a number
+ * {@code 1234567.89} in {@code Locale.US} locale,
+ * if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 9, respectively for the output string
+ * {@code 1,234,567.89}.
* @return the value passed in as <code>toAppendTo</code>
* @exception IllegalArgumentException if <code>number</code> is
* null or not an instance of <code>Number</code>.
@@ -271,7 +303,7 @@
* index information as described above.
* @return A <code>Number</code> parsed from the string. In case of
* error, returns null.
- * @exception NullPointerException if <code>pos</code> is null.
+ * @throws NullPointerException if {@code source} or {@code pos} is null.
*/
@Override
public final Object parseObject(String source, ParsePosition pos) {
@@ -323,7 +355,14 @@
* @param number the double number to format
* @param toAppendTo the StringBuffer to which the formatted text is to be
* appended
- * @param pos the field position
+ * @param pos keeps track on the position of the field within the
+ * returned string. For example, for formatting a number
+ * {@code 1234567.89} in {@code Locale.US} locale,
+ * if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 9, respectively for the output string
+ * {@code 1,234,567.89}.
* @return the formatted StringBuffer
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
@@ -339,7 +378,14 @@
* @param number the long number to format
* @param toAppendTo the StringBuffer to which the formatted text is to be
* appended
- * @param pos the field position
+ * @param pos keeps track on the position of the field within the
+ * returned string. For example, for formatting a number
+ * {@code 123456789} in {@code Locale.US} locale,
+ * if the given {@code fieldPosition} is
+ * {@link NumberFormat#INTEGER_FIELD}, the begin index
+ * and end index of {@code fieldPosition} will be set
+ * to 0 and 11, respectively for the output string
+ * {@code 123,456,789}.
* @return the formatted StringBuffer
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
@@ -393,7 +439,7 @@
* For example in the English locale, with ParseIntegerOnly true, the
* string "1234." would be parsed as the integer value 1234 and parsing
* would stop at the "." character. Of course, the exact format accepted
- * by the parse operation is locale dependant and determined by sub-classes
+ * by the parse operation is locale dependent and determined by sub-classes
* of NumberFormat.
*
* @return {@code true} if numbers should be parsed as integers only;
@@ -425,7 +471,7 @@
* @return the {@code NumberFormat} instance for general-purpose number
* formatting
*/
- public final static NumberFormat getInstance() {
+ public static final NumberFormat getInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
}
@@ -454,7 +500,7 @@
* @see java.util.Locale#getDefault(java.util.Locale.Category)
* @see java.util.Locale.Category#FORMAT
*/
- public final static NumberFormat getNumberInstance() {
+ public static final NumberFormat getNumberInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
}
@@ -487,7 +533,7 @@
* @return a number format for integer values
* @since 1.4
*/
- public final static NumberFormat getIntegerInstance() {
+ public static final NumberFormat getIntegerInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), INTEGERSTYLE);
}
@@ -519,7 +565,7 @@
* @see java.util.Locale#getDefault(java.util.Locale.Category)
* @see java.util.Locale.Category#FORMAT
*/
- public final static NumberFormat getCurrencyInstance() {
+ public static final NumberFormat getCurrencyInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE);
}
@@ -544,7 +590,7 @@
* @see java.util.Locale#getDefault(java.util.Locale.Category)
* @see java.util.Locale.Category#FORMAT
*/
- public final static NumberFormat getPercentInstance() {
+ public static final NumberFormat getPercentInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
}
@@ -638,7 +684,7 @@
* Returns true if grouping is used in this format. For example, in the
* English locale, with grouping on, the number 1234567 might be formatted
* as "1,234,567". The grouping separator as well as the size of each group
- * is locale dependant and is determined by sub-classes of NumberFormat.
+ * is locale dependent and is determined by sub-classes of NumberFormat.
*
* @return {@code true} if grouping is used;
* {@code false} otherwise
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index a5663a4..4c41a82 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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
@@ -55,6 +55,7 @@
import sun.util.calendar.CalendarUtils;
import sun.util.calendar.ZoneInfoFile;
import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.TimeZoneNameUtility;
/**
* <code>SimpleDateFormat</code> is a concrete class for formatting and
@@ -92,144 +93,149 @@
* <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to
* <code>'z'</code> are reserved):
* <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Chart shows pattern letters, date/time component, presentation, and examples.">
- * <tr style="background-color: rgb(204, 204, 255);">
- * <th align=left>Letter
- * <th align=left>Date or Time Component
- * <th align=left>Presentation
- * <th align=left>Examples
+ * <table class="striped">
+ * <caption style="display:none">Chart shows pattern letters, date/time component, presentation, and examples.</caption>
+ * <thead>
* <tr>
- * <td><code>G</code>
+ * <th scope="col" style="text-align:left">Letter
+ * <th scope="col" style="text-align:left">Date or Time Component
+ * <th scope="col" style="text-align:left">Presentation
+ * <th scope="col" style="text-align:left">Examples
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <th scope="row"><code>G</code>
* <td>Era designator
* <td><a href="#text">Text</a>
* <td><code>AD</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>y</code>
+ * <tr>
+ * <th scope="row"><code>y</code>
* <td>Year
* <td><a href="#year">Year</a>
* <td><code>1996</code>; <code>96</code>
* <tr>
- * <td><code>Y</code>
+ * <th scope="row"><code>Y</code>
* <td>Week year
* <td><a href="#year">Year</a>
* <td><code>2009</code>; <code>09</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>M</code>
+ * <tr>
+ * <th scope="row"><code>M</code>
* <td>Month in year (context sensitive)
* <td><a href="#month">Month</a>
* <td><code>July</code>; <code>Jul</code>; <code>07</code>
* <tr>
- * <td><code>L</code>
+ * <th scope="row"><code>L</code>
* <td>Month in year (standalone form)
* <td><a href="#month">Month</a>
* <td><code>July</code>; <code>Jul</code>; <code>07</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>w</code>
+ * <tr>
+ * <th scope="row"><code>w</code>
* <td>Week in year
* <td><a href="#number">Number</a>
* <td><code>27</code>
* <tr>
- * <td><code>W</code>
+ * <th scope="row"><code>W</code>
* <td>Week in month
* <td><a href="#number">Number</a>
* <td><code>2</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>D</code>
+ * <tr>
+ * <th scope="row"><code>D</code>
* <td>Day in year
* <td><a href="#number">Number</a>
* <td><code>189</code>
* <tr>
- * <td><code>d</code>
+ * <th scope="row"><code>d</code>
* <td>Day in month
* <td><a href="#number">Number</a>
* <td><code>10</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>F</code>
+ * <tr>
+ * <th scope="row"><code>F</code>
* <td>Day of week in month
* <td><a href="#number">Number</a>
* <td><code>2</code>
* <tr>
- * <td><code>E</code>
+ * <th scope="row"><code>E</code>
* <td>Day name in week
* <td><a href="#text">Text</a>
* <td><code>Tuesday</code>; <code>Tue</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>u</code>
+ * <tr>
+ * <th scope="row"><code>u</code>
* <td>Day number of week (1 = Monday, ..., 7 = Sunday)
* <td><a href="#number">Number</a>
* <td><code>1</code>
* <tr>
- * <td><code>a</code>
+ * <th scope="row"><code>a</code>
* <td>Am/pm marker
* <td><a href="#text">Text</a>
* <td><code>PM</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>H</code>
+ * <tr>
+ * <th scope="row"><code>H</code>
* <td>Hour in day (0-23)
* <td><a href="#number">Number</a>
* <td><code>0</code>
* <tr>
- * <td><code>k</code>
+ * <th scope="row"><code>k</code>
* <td>Hour in day (1-24)
* <td><a href="#number">Number</a>
* <td><code>24</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>K</code>
+ * <tr>
+ * <th scope="row"><code>K</code>
* <td>Hour in am/pm (0-11)
* <td><a href="#number">Number</a>
* <td><code>0</code>
* <tr>
- * <td><code>h</code>
+ * <th scope="row"><code>h</code>
* <td>Hour in am/pm (1-12)
* <td><a href="#number">Number</a>
* <td><code>12</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>m</code>
+ * <tr>
+ * <th scope="row"><code>m</code>
* <td>Minute in hour
* <td><a href="#number">Number</a>
* <td><code>30</code>
* <tr>
- * <td><code>s</code>
+ * <th scope="row"><code>s</code>
* <td>Second in minute
* <td><a href="#number">Number</a>
* <td><code>55</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>S</code>
+ * <tr>
+ * <th scope="row"><code>S</code>
* <td>Millisecond
* <td><a href="#number">Number</a>
* <td><code>978</code>
* <tr>
- * <td><code>z</code>
+ * <th scope="row"><code>z</code>
* <td>Time zone
* <td><a href="#timezone">General time zone</a>
* <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>Z</code>
+ * <tr>
+ * <th scope="row"><code>Z</code>
* <td>Time zone
* <td><a href="#rfc822timezone">RFC 822 time zone</a>
* <td><code>-0800</code>
* <tr>
- * <td><code>X</code>
+ * <th scope="row"><code>X</code>
* <td>Time zone
* <td><a href="#iso8601timezone">ISO 8601 time zone</a>
* <td><code>-08</code>; <code>-0800</code>; <code>-08:00</code>
+ * </tbody>
* </table>
* </blockquote>
* Pattern letters are usually repeated, as their number determines the
* exact presentation:
* <ul>
- * <li><strong><a name="text">Text:</a></strong>
+ * <li><strong><a id="text">Text:</a></strong>
* For formatting, if the number of pattern letters is 4 or more,
* the full form is used; otherwise a short or abbreviated form
* is used if available.
* For parsing, both forms are accepted, independent of the number
* of pattern letters.<br><br></li>
- * <li><strong><a name="number">Number:</a></strong>
+ * <li><strong><a id="number">Number:</a></strong>
* For formatting, the number of pattern letters is the minimum
* number of digits, and shorter numbers are zero-padded to this amount.
* For parsing, the number of pattern letters is ignored unless
* it's needed to separate two adjacent fields.<br><br></li>
- * <li><strong><a name="year">Year:</a></strong>
+ * <li><strong><a id="year">Year:</a></strong>
* If the formatter's {@link #getCalendar() Calendar} is the Gregorian
* calendar, the following rules are applied.<br>
* <ul>
@@ -270,26 +276,33 @@
* DateFormat#getCalendar() getCalendar()}.{@link
* java.util.Calendar#isWeekDateSupported()
* isWeekDateSupported()}.<br><br></li>
- * <li><strong><a name="month">Month:</a></strong>
+ * <li><strong><a id="month">Month:</a></strong>
* If the number of pattern letters is 3 or more, the month is
* interpreted as <a href="#text">text</a>; otherwise,
* it is interpreted as a <a href="#number">number</a>.<br>
* <ul>
* <li>Letter <em>M</em> produces context-sensitive month names, such as the
- * embedded form of names. If a {@code DateFormatSymbols} has been set
- * explicitly with constructor {@link #SimpleDateFormat(String,
- * DateFormatSymbols)} or method {@link
+ * embedded form of names. Letter <em>M</em> is context-sensitive in the
+ * sense that when it is used in the standalone pattern, for example,
+ * "MMMM", it gives the standalone form of a month name and when it is
+ * used in the pattern containing other field(s), for example, "d MMMM",
+ * it gives the format form of a month name. For example, January in the
+ * Catalan language is "de gener" in the format form while it is "gener"
+ * in the standalone form. In this case, "MMMM" will produce "gener" and
+ * the month part of the "d MMMM" will produce "de gener". If a
+ * {@code DateFormatSymbols} has been set explicitly with constructor
+ * {@link #SimpleDateFormat(String,DateFormatSymbols)} or method {@link
* #setDateFormatSymbols(DateFormatSymbols)}, the month names given by
* the {@code DateFormatSymbols} are used.</li>
* <li>Letter <em>L</em> produces the standalone form of month names.</li>
* </ul>
* <br></li>
- * <li><strong><a name="timezone">General time zone:</a></strong>
+ * <li><strong><a id="timezone">General time zone:</a></strong>
* Time zones are interpreted as <a href="#text">text</a> if they have
* names. For time zones representing a GMT offset value, the
* following syntax is used:
* <pre>
- * <a name="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a>
+ * <a id="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a>
* <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i>
* <i>Sign:</i> one of
* <code>+ -</code>
@@ -305,7 +318,7 @@
* from the Basic Latin block of the Unicode standard.
* <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also
* accepted.<br><br></li>
- * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
+ * <li><strong><a id="rfc822timezone">RFC 822 time zone:</a></strong>
* For formatting, the RFC 822 4-digit time zone format is used:
*
* <pre>
@@ -318,7 +331,7 @@
*
* <p>For parsing, <a href="#timezone">general time zones</a> are also
* accepted.
- * <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
+ * <li><strong><a id="iso8601timezone">ISO 8601 Time zone:</a></strong>
* The number of pattern letters designates the format for both formatting
* and parsing as follows:
* <pre>
@@ -363,47 +376,52 @@
* the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time
* in the U.S. Pacific Time time zone.
* <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Examples of date and time patterns interpreted in the U.S. locale">
- * <tr style="background-color: rgb(204, 204, 255);">
- * <th align=left>Date and Time Pattern
- * <th align=left>Result
+ * <table class="striped">
+ * <caption style="display:none">Examples of date and time patterns interpreted in the U.S. locale</caption>
+ * <thead>
* <tr>
- * <td><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
+ * <th scope="col" style="text-align:left">Date and Time Pattern
+ * <th scope="col" style="text-align:left">Result
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <th scope="row"><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
* <td><code>2001.07.04 AD at 12:08:56 PDT</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>"EEE, MMM d, ''yy"</code>
+ * <tr>
+ * <th scope="row"><code>"EEE, MMM d, ''yy"</code>
* <td><code>Wed, Jul 4, '01</code>
* <tr>
- * <td><code>"h:mm a"</code>
+ * <th scope="row"><code>"h:mm a"</code>
* <td><code>12:08 PM</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>"hh 'o''clock' a, zzzz"</code>
+ * <tr>
+ * <th scope="row"><code>"hh 'o''clock' a, zzzz"</code>
* <td><code>12 o'clock PM, Pacific Daylight Time</code>
* <tr>
- * <td><code>"K:mm a, z"</code>
+ * <th scope="row"><code>"K:mm a, z"</code>
* <td><code>0:08 PM, PDT</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code>
+ * <tr>
+ * <th scope="row"><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code>
* <td><code>02001.July.04 AD 12:08 PM</code>
* <tr>
- * <td><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
+ * <th scope="row"><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
* <td><code>Wed, 4 Jul 2001 12:08:56 -0700</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>"yyMMddHHmmssZ"</code>
+ * <tr>
+ * <th scope="row"><code>"yyMMddHHmmssZ"</code>
* <td><code>010704120856-0700</code>
* <tr>
- * <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
+ * <th scope="row"><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
* <td><code>2001-07-04T12:08:56.235-0700</code>
- * <tr style="background-color: rgb(238, 238, 255);">
- * <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
+ * <tr>
+ * <th scope="row"><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
* <td><code>2001-07-04T12:08:56.235-07:00</code>
* <tr>
- * <td><code>"YYYY-'W'ww-u"</code>
+ * <th scope="row"><code>"YYYY-'W'ww-u"</code>
* <td><code>2001-W27-3</code>
+ * </tbody>
* </table>
* </blockquote>
*
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
*
* <p>
* Date formats are not synchronized.
@@ -411,12 +429,13 @@
* If multiple threads access a format concurrently, it must be synchronized
* externally.
*
- * @see <a href="https://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a>
+ * @see <a href="http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a>
* @see java.util.Calendar
* @see java.util.TimeZone
* @see DateFormat
* @see DateFormatSymbols
* @author Mark Davis, Chen-Lieh Huang, Alan Liu
+ * @since 1.1
*/
public class SimpleDateFormat extends DateFormat {
@@ -441,7 +460,7 @@
* and the highest allowable <code>serialVersionOnStream</code>
* is written.
* @serial
- * @since JDK1.1.4
+ * @since 1.1.4
*/
private int serialVersionOnStream = currentSerialVersion;
@@ -456,42 +475,42 @@
* Saved numberFormat and pattern.
* @see SimpleDateFormat#checkNegativeNumberExpression
*/
- transient private NumberFormat originalNumberFormat;
- transient private String originalNumberPattern;
+ private transient NumberFormat originalNumberFormat;
+ private transient String originalNumberPattern;
/**
* The minus sign to be used with format and parse.
*/
- transient private char minusSign = '-';
+ private transient char minusSign = '-';
/**
* True when a negative sign follows a number.
* (True as default in Arabic.)
*/
- transient private boolean hasFollowingMinusSign = false;
+ private transient boolean hasFollowingMinusSign = false;
/**
* True if standalone form needs to be used.
*/
- transient private boolean forceStandaloneForm = false;
+ private transient boolean forceStandaloneForm = false;
/**
* The compiled pattern.
*/
- transient private char[] compiledPattern;
+ private transient char[] compiledPattern;
/**
* Tags for the compiled pattern.
*/
- private final static int TAG_QUOTE_ASCII_CHAR = 100;
- private final static int TAG_QUOTE_CHARS = 101;
+ private static final int TAG_QUOTE_ASCII_CHAR = 100;
+ private static final int TAG_QUOTE_CHARS = 101;
/**
* Locale dependent digit zero.
* @see #zeroPaddingNumber
* @see java.text.DecimalFormatSymbols#getZeroDigit
*/
- transient private char zeroDigit;
+ private transient char zeroDigit;
/**
* The symbols used by this formatter for week names, month names,
@@ -506,11 +525,11 @@
* <code>defaultCenturyStart</code>, which may be any date. May
* not be null.
* @serial
- * @since JDK1.1.4
+ * @since 1.1.4
*/
private Date defaultCenturyStart;
- transient private int defaultCenturyStartYear;
+ private transient int defaultCenturyStartYear;
private static final int MILLIS_PER_MINUTE = 60 * 1000;
@@ -654,7 +673,7 @@
// However, the calendar should use the current default TimeZone.
// If this is not contained in the locale zone strings, then the zone
// will be formatted using generic GMT+/-H:MM nomenclature.
- calendar = Calendar.getInstance(TimeZone.getDefault(), loc);
+ calendar = Calendar.getInstance(loc);
}
}
@@ -898,6 +917,7 @@
* @param startDate During parsing, two digit years will be placed in the range
* <code>startDate</code> to <code>startDate + 100 years</code>.
* @see #get2DigitYearStart
+ * @throws NullPointerException if {@code startDate} is {@code null}.
* @since 1.2
*/
public void set2DigitYearStart(Date startDate) {
@@ -923,10 +943,21 @@
*
* @param date the date-time value to be formatted into a date-time string.
* @param toAppendTo where the new date-time text is to be appended.
- * @param pos the formatting position. On input: an alignment field,
- * if desired. On output: the offsets of the alignment field.
+ * @param pos keeps track on the position of the field within
+ * the returned string. For example, given a date-time text
+ * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
+ * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
+ * {@code fieldPosition} will be set to 0 and 4, respectively.
+ * Notice that if the same date-time field appears more than once in a
+ * pattern, the {@code fieldPosition} will be set for the first occurrence
+ * of that date-time field. For instance, formatting a {@code Date} to the
+ * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
+ * pattern {@code "h a z (zzzz)"} and the alignment field
+ * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
+ * {@code fieldPosition} will be set to 5 and 8, respectively, for the
+ * first occurrence of the timezone pattern character {@code 'z'}.
* @return the formatted date-time string.
- * @exception NullPointerException if the given {@code date} is {@code null}.
+ * @exception NullPointerException if any of the parameters is {@code null}.
*/
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo,
@@ -1491,22 +1522,18 @@
if (i < compiledPattern.length) {
int nextTag = compiledPattern[i] >>> 8;
- if (!(nextTag == TAG_QUOTE_ASCII_CHAR ||
- nextTag == TAG_QUOTE_CHARS)) {
- obeyCount = true;
- }
+ int nextCount = compiledPattern[i] & 0xff;
+ obeyCount = shouldObeyCount(nextTag, nextCount);
if (hasFollowingMinusSign &&
(nextTag == TAG_QUOTE_ASCII_CHAR ||
nextTag == TAG_QUOTE_CHARS)) {
- int c;
- if (nextTag == TAG_QUOTE_ASCII_CHAR) {
- c = compiledPattern[i] & 0xff;
- } else {
- c = compiledPattern[i+1];
+
+ if (nextTag != TAG_QUOTE_ASCII_CHAR) {
+ nextCount = compiledPattern[i+1];
}
- if (c == minusSign) {
+ if (nextCount == minusSign) {
useFollowingMinusSignAsDelimiter = true;
}
}
@@ -1549,6 +1576,36 @@
return parsedDate;
}
+ /* If the next tag/pattern is a <Numeric_Field> then the parser
+ * should consider the count of digits while parsing the contigous digits
+ * for the current tag/pattern
+ */
+ private boolean shouldObeyCount(int tag, int count) {
+ switch (tag) {
+ case PATTERN_MONTH:
+ case PATTERN_MONTH_STANDALONE:
+ return count <= 2;
+ case PATTERN_YEAR:
+ case PATTERN_DAY_OF_MONTH:
+ case PATTERN_HOUR_OF_DAY1:
+ case PATTERN_HOUR_OF_DAY0:
+ case PATTERN_MINUTE:
+ case PATTERN_SECOND:
+ case PATTERN_MILLISECOND:
+ case PATTERN_DAY_OF_YEAR:
+ case PATTERN_DAY_OF_WEEK_IN_MONTH:
+ case PATTERN_WEEK_OF_YEAR:
+ case PATTERN_WEEK_OF_MONTH:
+ case PATTERN_HOUR1:
+ case PATTERN_HOUR0:
+ case PATTERN_WEEK_YEAR:
+ case PATTERN_ISO_DAY_OF_WEEK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/**
* Private code-size reduction function used by subParse.
* @param text the time text being parsed.
@@ -1635,6 +1692,12 @@
// Checking long and short zones [1 & 2],
// and long and short daylight [3 & 4].
String zoneName = zoneNames[i];
+ if (zoneName.isEmpty()) {
+ // fill in by retrieving single name
+ zoneName = TimeZoneNameUtility.retrieveDisplayName(
+ zoneNames[0], i >= 3, i % 2, locale);
+ zoneNames[i] = zoneName;
+ }
if (text.regionMatches(true, start,
zoneName, 0, zoneName.length())) {
return i;
@@ -1856,6 +1919,7 @@
if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
patternCharIndex == PATTERN_HOUR1 ||
(patternCharIndex == PATTERN_MONTH && count <= 2) ||
+ (patternCharIndex == PATTERN_MONTH_STANDALONE && count <= 2) ||
patternCharIndex == PATTERN_YEAR ||
patternCharIndex == PATTERN_WEEK_YEAR) {
// It would be good to unify this with the obeyCount logic below,
@@ -1976,6 +2040,20 @@
}
break parsing;
+ case PATTERN_MONTH_STANDALONE: // 'L'
+ if (count <= 2) {
+ // Don't want to parse the month if it is a string
+ // while pattern uses numeric style: L or LL
+ //[we computed 'value' above.]
+ calb.set(Calendar.MONTH, value - 1);
+ return pos.index;
+ }
+ Map<String, Integer> maps = getDisplayNamesMap(field, locale);
+ if ((index = matchString(text, start, field, maps, calb)) > 0) {
+ return index;
+ }
+ break parsing;
+
case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59
if (!isLenient()) {
// Validate the hour value in non-lenient
@@ -2374,7 +2452,7 @@
/**
* After reading an object from the input stream, the format
* pattern in the object is verified.
- * <p>
+ *
* @exception InvalidObjectException if the pattern is invalid
*/
private void readObject(ObjectInputStream stream)