mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8176841: Additional Unicode Language-Tag Extensions
8189134: New system properties for the default Locale extensions 8190918: Retrieve the region specific data regardless of language in locale 8191349: Add a new method in j.t.f.DateTimeFormatter to reflect Unicode extensions Reviewed-by: scolebourne, lancea, rriggs, rgoel, nishjain
This commit is contained in:
parent
3246c46f41
commit
f065141ddc
55 changed files with 3631 additions and 890 deletions
|
@ -97,6 +97,13 @@ import sun.util.locale.provider.LocaleServiceProviderPool;
|
|||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2016, 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
|
||||
|
@ -49,6 +49,7 @@ import java.util.Objects;
|
|||
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 @@ import sun.util.locale.provider.TimeZoneNameUtility;
|
|||
* </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
|
||||
|
@ -716,15 +721,18 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
}
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
@ -44,6 +44,7 @@ import java.io.Serializable;
|
|||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.util.Currency;
|
||||
import java.util.Locale;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
|
@ -56,6 +57,10 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
|||
* 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
|
||||
|
@ -609,13 +614,18 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
|||
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);
|
||||
|
|
|
@ -96,7 +96,14 @@ import sun.util.locale.provider.LocaleServiceProviderPool;
|
|||
* 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);
|
||||
|
|
|
@ -672,7 +672,7 @@ public class SimpleDateFormat extends DateFormat {
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import sun.util.locale.provider.TimeZoneNameUtility;
|
||||
|
||||
/**
|
||||
* Formatter for printing and parsing date-time objects.
|
||||
|
@ -548,7 +549,7 @@ public final class DateTimeFormatter {
|
|||
* For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
|
||||
* <p>
|
||||
* The formatter will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
|
||||
* This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
|
||||
* This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter.
|
||||
* Alternatively use the {@link #ofPattern(String, Locale)} variant of this method.
|
||||
* <p>
|
||||
* The returned formatter has no override chronology or zone.
|
||||
|
@ -572,7 +573,7 @@ public final class DateTimeFormatter {
|
|||
* For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
|
||||
* <p>
|
||||
* The formatter will use the specified locale.
|
||||
* This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
|
||||
* This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter.
|
||||
* <p>
|
||||
* The returned formatter has no override chronology or zone.
|
||||
* It uses {@link ResolverStyle#SMART SMART} resolver style.
|
||||
|
@ -1443,10 +1444,17 @@ public final class DateTimeFormatter {
|
|||
* This is used to lookup any part of the formatter needing specific
|
||||
* localization, such as the text or localized pattern.
|
||||
* <p>
|
||||
* The locale is stored as passed in, without further processing.
|
||||
* If the locale has <a href="../../util/Locale.html#def_locale_extension">
|
||||
* Unicode extensions</a>, they may be used later in text
|
||||
* processing. To set the chronology, time-zone and decimal style from
|
||||
* unicode extensions, see {@link #localizedBy localizedBy()}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param locale the new locale, not null
|
||||
* @return a formatter based on this formatter with the requested locale, not null
|
||||
* @see #localizedBy(Locale)
|
||||
*/
|
||||
public DateTimeFormatter withLocale(Locale locale) {
|
||||
if (this.locale.equals(locale)) {
|
||||
|
@ -1455,6 +1463,52 @@ public final class DateTimeFormatter {
|
|||
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this formatter with localized values of the locale,
|
||||
* calendar, region, decimal style and/or timezone, that supercede values in
|
||||
* this formatter.
|
||||
* <p>
|
||||
* This is used to lookup any part of the formatter needing specific
|
||||
* localization, such as the text or localized pattern. If the locale contains the
|
||||
* "ca" (calendar), "nu" (numbering system), "rg" (region override), and/or
|
||||
* "tz" (timezone)
|
||||
* <a href="../../util/Locale.html#def_locale_extension">Unicode extensions</a>,
|
||||
* the chronology, numbering system and/or the zone are overridden. If both "ca"
|
||||
* and "rg" are specified, the chronology from the "ca" extension supersedes the
|
||||
* implicit one from the "rg" extension. Same is true for the "nu" extension.
|
||||
* <p>
|
||||
* Unlike the {@link #withLocale withLocale} method, the call to this method may
|
||||
* produce a different formatter depending on the order of method chaining with
|
||||
* other withXXXX() methods.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param locale the locale, not null
|
||||
* @return a formatter based on this formatter with localized values of
|
||||
* the calendar, decimal style and/or timezone, that supercede values in this
|
||||
* formatter.
|
||||
* @see #withLocale(Locale)
|
||||
* @since 10
|
||||
*/
|
||||
public DateTimeFormatter localizedBy(Locale locale) {
|
||||
if (this.locale.equals(locale)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Check for decimalStyle/chronology/timezone in locale object
|
||||
Chronology c = locale.getUnicodeLocaleType("ca") != null ?
|
||||
Chronology.ofLocale(locale) : chrono;
|
||||
DecimalStyle ds = locale.getUnicodeLocaleType("nu") != null ?
|
||||
DecimalStyle.of(locale) : decimalStyle;
|
||||
String tzType = locale.getUnicodeLocaleType("tz");
|
||||
ZoneId z = tzType != null ?
|
||||
TimeZoneNameUtility.convertLDMLShortID(tzType)
|
||||
.map(ZoneId::of)
|
||||
.orElse(zone) :
|
||||
zone;
|
||||
return new DateTimeFormatter(printerParser, locale, ds, resolverStyle, resolverFields, c, z);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the DecimalStyle to be used during formatting.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -120,6 +120,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import sun.text.spi.JavaTimeDateTimePatternProvider;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
import sun.util.locale.provider.TimeZoneNameUtility;
|
||||
|
@ -198,6 +199,10 @@ public final class DateTimeFormatterBuilder {
|
|||
* Gets the formatting pattern for date and time styles for a locale and chronology.
|
||||
* The locale and chronology are used to lookup the locale specific format
|
||||
* for the requested dateStyle and/or timeStyle.
|
||||
* <p>
|
||||
* If the locale contains the "rg" (region override)
|
||||
* <a href="../../util/Locale.html#def_locale_extension">Unicode extensions</a>,
|
||||
* the formatting pattern is overridden with the one appropriate for the region.
|
||||
*
|
||||
* @param dateStyle the FormatStyle for the date, null for time-only pattern
|
||||
* @param timeStyle the FormatStyle for the time, null for date-only pattern
|
||||
|
@ -216,7 +221,8 @@ public final class DateTimeFormatterBuilder {
|
|||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, locale);
|
||||
JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider();
|
||||
String pattern = provider.getJavaTimeDateTimePattern(convertStyle(timeStyle),
|
||||
convertStyle(dateStyle), chrono.getCalendarType(), locale);
|
||||
convertStyle(dateStyle), chrono.getCalendarType(),
|
||||
CalendarDataUtility.findRegionOverride(locale));
|
||||
return pattern;
|
||||
}
|
||||
|
||||
|
|
|
@ -510,7 +510,8 @@ class DateTimeTextProvider {
|
|||
@SuppressWarnings("unchecked")
|
||||
static <T> T getLocalizedResource(String key, Locale locale) {
|
||||
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
|
||||
.getLocaleResources(locale);
|
||||
.getLocaleResources(
|
||||
CalendarDataUtility.findRegionOverride(locale));
|
||||
ResourceBundle rb = lr.getJavaTimeFormatData();
|
||||
return rb.containsKey(key) ? (T) rb.getObject(key) : null;
|
||||
}
|
||||
|
|
|
@ -147,6 +147,11 @@ public final class DecimalStyle {
|
|||
* Obtains the DecimalStyle for the specified locale.
|
||||
* <p>
|
||||
* This method provides access to locale sensitive decimal style symbols.
|
||||
* If the locale contains "nu" (Numbering System) and/or "rg"
|
||||
* (Region Override) <a href="../../util/Locale.html#def_locale_extension">
|
||||
* Unicode extensions</a>, returned instance will reflect the values specified with
|
||||
* those extensions. If both "nu" and "rg" are specified, the value from
|
||||
* the "nu" extension supersedes the implicit one from the "rg" extension.
|
||||
*
|
||||
* @param locale the locale, not null
|
||||
* @return the decimal style, not null
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -79,6 +79,7 @@ import java.time.chrono.Chronology;
|
|||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
|
||||
|
@ -632,7 +633,9 @@ public enum ChronoField implements TemporalField {
|
|||
}
|
||||
|
||||
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
|
||||
.getLocaleResources(locale);
|
||||
.getLocaleResources(
|
||||
CalendarDataUtility
|
||||
.findRegionOverride(locale));
|
||||
ResourceBundle rb = lr.getJavaTimeFormatData();
|
||||
String key = "field." + displayNameKey;
|
||||
return rb.containsKey(key) ? rb.getString(key) : name;
|
||||
|
|
|
@ -81,6 +81,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
|
||||
|
@ -430,7 +431,9 @@ public final class IsoFields {
|
|||
public String getDisplayName(Locale locale) {
|
||||
Objects.requireNonNull(locale, "locale");
|
||||
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
|
||||
.getLocaleResources(locale);
|
||||
.getLocaleResources(
|
||||
CalendarDataUtility
|
||||
.findRegionOverride(locale));
|
||||
ResourceBundle rb = lr.getJavaTimeFormatData();
|
||||
return rb.containsKey("field.week") ? rb.getString("field.week") : toString();
|
||||
}
|
||||
|
|
|
@ -286,13 +286,17 @@ public final class WeekFields implements Serializable {
|
|||
* Obtains an instance of {@code WeekFields} appropriate for a locale.
|
||||
* <p>
|
||||
* This will look up appropriate values from the provider of localization data.
|
||||
* If the locale contains "fw" (First day of week) and/or "rg"
|
||||
* (Region Override) <a href="../../util/Locale.html#def_locale_extension">
|
||||
* Unicode extensions</a>, returned instance will reflect the values specified with
|
||||
* those extensions. If both "fw" and "rg" are specified, the value from
|
||||
* the "fw" extension supersedes the implicit one from the "rg" extension.
|
||||
*
|
||||
* @param locale the locale to use, not null
|
||||
* @return the week-definition, not null
|
||||
*/
|
||||
public static WeekFields of(Locale locale) {
|
||||
Objects.requireNonNull(locale, "locale");
|
||||
locale = new Locale(locale.getLanguage(), locale.getCountry()); // elminate variants
|
||||
|
||||
int calDow = CalendarDataUtility.retrieveFirstDayOfWeek(locale);
|
||||
DayOfWeek dow = DayOfWeek.SUNDAY.plus(calDow - 1);
|
||||
|
@ -1041,7 +1045,8 @@ public final class WeekFields implements Serializable {
|
|||
Objects.requireNonNull(locale, "locale");
|
||||
if (rangeUnit == YEARS) { // only have values for week-of-year
|
||||
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
|
||||
.getLocaleResources(locale);
|
||||
.getLocaleResources(
|
||||
CalendarDataUtility.findRegionOverride(locale));
|
||||
ResourceBundle rb = lr.getJavaTimeFormatData();
|
||||
return rb.containsKey("field.week") ? rb.getString("field.week") : name;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ import sun.util.BuddhistCalendar;
|
|||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.TimeZoneNameUtility;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
|
@ -128,9 +129,14 @@ import sun.util.spi.CalendarProvider;
|
|||
*
|
||||
* <code>Calendar</code> defines a locale-specific seven day week using two
|
||||
* parameters: the first day of the week and the minimal days in first week
|
||||
* (from 1 to 7). These numbers are taken from the locale resource data when a
|
||||
* <code>Calendar</code> is constructed. They may also be specified explicitly
|
||||
* through the methods for setting their values.
|
||||
* (from 1 to 7). These numbers are taken from the locale resource data or the
|
||||
* locale itself when a {@code Calendar} is constructed. If the designated
|
||||
* locale contains "fw" and/or "rg" <a href="./Locale.html#def_locale_extension">
|
||||
* Unicode extensions</a>, the first day of the week will be obtained according to
|
||||
* those extensions. If both "fw" and "rg" are specified, the value from the "fw"
|
||||
* extension supersedes the implicit one from the "rg" extension.
|
||||
* They may also be specified explicitly through the methods for setting their
|
||||
* values.
|
||||
*
|
||||
* <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
|
||||
* <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
|
||||
|
@ -1444,6 +1450,11 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
|||
*
|
||||
* <p>The default values are used for locale and time zone if these
|
||||
* parameters haven't been given explicitly.
|
||||
* <p>
|
||||
* If the locale contains the time zone with "tz"
|
||||
* <a href="Locale.html#def_locale_extension">Unicode extension</a>,
|
||||
* and time zone hasn't been given explicitly, time zone in the locale
|
||||
* is used.
|
||||
*
|
||||
* <p>Any out of range field values are either normalized in lenient
|
||||
* mode or detected as an invalid value in non-lenient mode.
|
||||
|
@ -1463,7 +1474,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
|||
locale = Locale.getDefault();
|
||||
}
|
||||
if (zone == null) {
|
||||
zone = TimeZone.getDefault();
|
||||
zone = defaultTimeZone(locale);
|
||||
}
|
||||
Calendar cal;
|
||||
if (type == null) {
|
||||
|
@ -1605,12 +1616,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
|||
* <code>Calendar</code> returned is based on the current time
|
||||
* in the default time zone with the default
|
||||
* {@link Locale.Category#FORMAT FORMAT} locale.
|
||||
* <p>
|
||||
* If the locale contains the time zone with "tz"
|
||||
* <a href="Locale.html#def_locale_extension">Unicode extension</a>,
|
||||
* that time zone is used instead.
|
||||
*
|
||||
* @return a Calendar.
|
||||
*/
|
||||
public static Calendar getInstance()
|
||||
{
|
||||
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
|
||||
Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);
|
||||
return createCalendar(defaultTimeZone(aLocale), aLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1631,13 +1647,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
|||
* Gets a calendar using the default time zone and specified locale.
|
||||
* The <code>Calendar</code> returned is based on the current time
|
||||
* in the default time zone with the given locale.
|
||||
* <p>
|
||||
* If the locale contains the time zone with "tz"
|
||||
* <a href="Locale.html#def_locale_extension">Unicode extension</a>,
|
||||
* that time zone is used instead.
|
||||
*
|
||||
* @param aLocale the locale for the week data
|
||||
* @return a Calendar.
|
||||
*/
|
||||
public static Calendar getInstance(Locale aLocale)
|
||||
{
|
||||
return createCalendar(TimeZone.getDefault(), aLocale);
|
||||
return createCalendar(defaultTimeZone(aLocale), aLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1655,6 +1675,16 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
|||
return createCalendar(zone, aLocale);
|
||||
}
|
||||
|
||||
private static TimeZone defaultTimeZone(Locale l) {
|
||||
TimeZone defaultTZ = TimeZone.getDefault();
|
||||
String shortTZID = l.getUnicodeLocaleType("tz");
|
||||
return shortTZID != null ?
|
||||
TimeZoneNameUtility.convertLDMLShortID(shortTZID)
|
||||
.map(TimeZone::getTimeZone)
|
||||
.orElse(defaultTZ) :
|
||||
defaultTZ;
|
||||
}
|
||||
|
||||
private static Calendar createCalendar(TimeZone zone,
|
||||
Locale aLocale)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
|
@ -28,7 +28,6 @@ package java.util;
|
|||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -42,6 +41,7 @@ import java.util.concurrent.ConcurrentMap;
|
|||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
|
@ -348,6 +348,13 @@ public final class Currency implements Serializable {
|
|||
* until December 31, 2001, and the Euro from January 1, 2002, local time
|
||||
* of the respective countries.
|
||||
* <p>
|
||||
* If the specified {@code locale} contains "cu" and/or "rg"
|
||||
* <a href="./Locale.html#def_locale_extension">Unicode extensions</a>,
|
||||
* the instance returned from this method reflects
|
||||
* the values specified with those extensions. If both "cu" and "rg" are
|
||||
* specified, the currency from the "cu" extension supersedes the implicit one
|
||||
* from the "rg" extension.
|
||||
* <p>
|
||||
* The method returns <code>null</code> for territories that don't
|
||||
* have a currency, such as Antarctica.
|
||||
*
|
||||
|
@ -361,12 +368,19 @@ public final class Currency implements Serializable {
|
|||
* is not a supported ISO 3166 country code.
|
||||
*/
|
||||
public static Currency getInstance(Locale locale) {
|
||||
String country = locale.getCountry();
|
||||
if (country == null) {
|
||||
throw new NullPointerException();
|
||||
// check for locale overrides
|
||||
String override = locale.getUnicodeLocaleType("cu");
|
||||
if (override != null) {
|
||||
try {
|
||||
return getInstance(override.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// override currency is invalid. Fall through.
|
||||
}
|
||||
}
|
||||
|
||||
if (country.length() != 2) {
|
||||
String country = CalendarDataUtility.findRegionOverride(locale).getCountry();
|
||||
|
||||
if (country == null || !country.matches("^[a-zA-Z]{2}$")) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
|
@ -482,6 +496,12 @@ public final class Currency implements Serializable {
|
|||
* locale is the US, while for other locales it may be "US$". If no
|
||||
* symbol can be determined, the ISO 4217 currency code is returned.
|
||||
* <p>
|
||||
* If the default {@link Locale.Category#DISPLAY DISPLAY} locale
|
||||
* contains "rg" (region override)
|
||||
* <a href="./Locale.html#def_locale_extension">Unicode extension</a>,
|
||||
* the symbol returned from this method reflects
|
||||
* the value specified with that extension.
|
||||
* <p>
|
||||
* This is equivalent to calling
|
||||
* {@link #getSymbol(Locale)
|
||||
* getSymbol(Locale.getDefault(Locale.Category.DISPLAY))}.
|
||||
|
@ -498,6 +518,11 @@ public final class Currency implements Serializable {
|
|||
* For example, for the US Dollar, the symbol is "$" if the specified
|
||||
* locale is the US, while for other locales it may be "US$". If no
|
||||
* symbol can be determined, the ISO 4217 currency code is returned.
|
||||
* <p>
|
||||
* If the specified {@code locale} contains "rg" (region override)
|
||||
* <a href="./Locale.html#def_locale_extension">Unicode extension</a>,
|
||||
* the symbol returned from this method reflects
|
||||
* the value specified with that extension.
|
||||
*
|
||||
* @param locale the locale for which a display name for this currency is
|
||||
* needed
|
||||
|
@ -507,6 +532,7 @@ public final class Currency implements Serializable {
|
|||
public String getSymbol(Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CurrencyNameProvider.class);
|
||||
locale = CalendarDataUtility.findRegionOverride(locale);
|
||||
String symbol = pool.getLocalizedObject(
|
||||
CurrencyNameGetter.INSTANCE,
|
||||
locale, currencyCode, SYMBOL);
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.io.Serializable;
|
|||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.util.locale.BaseLocale;
|
||||
|
@ -62,6 +63,7 @@ import sun.util.locale.ParseStatus;
|
|||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.locale.provider.TimeZoneNameUtility;
|
||||
|
||||
/**
|
||||
* A <code>Locale</code> object represents a specific geographical, political,
|
||||
|
@ -665,10 +667,12 @@ public final class Locale implements Cloneable, Serializable {
|
|||
/**
|
||||
* Display types for retrieving localized names from the name providers.
|
||||
*/
|
||||
private static final int DISPLAY_LANGUAGE = 0;
|
||||
private static final int DISPLAY_COUNTRY = 1;
|
||||
private static final int DISPLAY_VARIANT = 2;
|
||||
private static final int DISPLAY_SCRIPT = 3;
|
||||
private static final int DISPLAY_LANGUAGE = 0;
|
||||
private static final int DISPLAY_COUNTRY = 1;
|
||||
private static final int DISPLAY_VARIANT = 2;
|
||||
private static final int DISPLAY_SCRIPT = 3;
|
||||
private static final int DISPLAY_UEXT_KEY = 4;
|
||||
private static final int DISPLAY_UEXT_TYPE = 5;
|
||||
|
||||
/**
|
||||
* Private constructor used by getInstance method
|
||||
|
@ -942,11 +946,14 @@ public final class Locale implements Cloneable, Serializable {
|
|||
variant = props.getProperty("user.variant", "");
|
||||
}
|
||||
|
||||
return getInstance(language, script, country, variant, null);
|
||||
return getInstance(language, script, country, variant,
|
||||
getDefaultExtensions(props.getProperty("user.extensions", ""))
|
||||
.orElse(null));
|
||||
}
|
||||
|
||||
private static Locale initDefault(Locale.Category category) {
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
|
||||
return getInstance(
|
||||
props.getProperty(category.languageKey,
|
||||
defaultLocale.getLanguage()),
|
||||
|
@ -956,7 +963,22 @@ public final class Locale implements Cloneable, Serializable {
|
|||
defaultLocale.getCountry()),
|
||||
props.getProperty(category.variantKey,
|
||||
defaultLocale.getVariant()),
|
||||
null);
|
||||
getDefaultExtensions(props.getProperty(category.extensionsKey, ""))
|
||||
.orElse(defaultLocale.getLocaleExtensions()));
|
||||
}
|
||||
|
||||
private static Optional<LocaleExtensions> getDefaultExtensions(String extensionsProp) {
|
||||
LocaleExtensions exts = null;
|
||||
|
||||
try {
|
||||
exts = new InternalLocaleBuilder()
|
||||
.setExtensions(extensionsProp)
|
||||
.getLocaleExtensions();
|
||||
} catch (LocaleSyntaxException e) {
|
||||
// just ignore this incorrect property
|
||||
}
|
||||
|
||||
return Optional.ofNullable(exts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1771,7 +1793,7 @@ public final class Locale implements Cloneable, Serializable {
|
|||
* @exception NullPointerException if <code>inLocale</code> is <code>null</code>
|
||||
*/
|
||||
public String getDisplayLanguage(Locale inLocale) {
|
||||
return getDisplayString(baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
|
||||
return getDisplayString(baseLocale.getLanguage(), null, inLocale, DISPLAY_LANGUAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1801,7 +1823,7 @@ public final class Locale implements Cloneable, Serializable {
|
|||
* @since 1.7
|
||||
*/
|
||||
public String getDisplayScript(Locale inLocale) {
|
||||
return getDisplayString(baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
|
||||
return getDisplayString(baseLocale.getScript(), null, inLocale, DISPLAY_SCRIPT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1844,29 +1866,24 @@ public final class Locale implements Cloneable, Serializable {
|
|||
* @exception NullPointerException if <code>inLocale</code> is <code>null</code>
|
||||
*/
|
||||
public String getDisplayCountry(Locale inLocale) {
|
||||
return getDisplayString(baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
|
||||
return getDisplayString(baseLocale.getRegion(), null, inLocale, DISPLAY_COUNTRY);
|
||||
}
|
||||
|
||||
private String getDisplayString(String code, Locale inLocale, int type) {
|
||||
if (code.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
private String getDisplayString(String code, String cat, Locale inLocale, int type) {
|
||||
Objects.requireNonNull(inLocale);
|
||||
Objects.requireNonNull(code);
|
||||
|
||||
if (inLocale == null) {
|
||||
throw new NullPointerException();
|
||||
if (code.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
|
||||
String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
|
||||
String rbKey = (type == DISPLAY_VARIANT ? "%%"+code : code);
|
||||
String result = pool.getLocalizedObject(
|
||||
LocaleNameGetter.INSTANCE,
|
||||
inLocale, key, type, code);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return code;
|
||||
inLocale, rbKey, type, code, cat);
|
||||
return result != null ? result : code;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1894,29 +1911,31 @@ public final class Locale implements Cloneable, Serializable {
|
|||
if (baseLocale.getVariant().length() == 0)
|
||||
return "";
|
||||
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);
|
||||
LocaleResources lr = LocaleProviderAdapter
|
||||
.getResourceBundleBased()
|
||||
.getLocaleResources(inLocale);
|
||||
|
||||
String names[] = getDisplayVariantArray(inLocale);
|
||||
|
||||
// Get the localized patterns for formatting a list, and use
|
||||
// them to format the list.
|
||||
return formatList(names,
|
||||
lr.getLocaleName("ListPattern"),
|
||||
lr.getLocaleName("ListCompositionPattern"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name for the locale that is appropriate for display to the
|
||||
* user. This will be the values returned by getDisplayLanguage(),
|
||||
* getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled
|
||||
* into a single string. The non-empty values are used in order,
|
||||
* with the second and subsequent names in parentheses. For example:
|
||||
* getDisplayScript(), getDisplayCountry(), getDisplayVariant() and
|
||||
* optional <a href="./Locale.html#def_locale_extension">Unicode extensions</a>
|
||||
* assembled into a single string. The non-empty values are used in order, with
|
||||
* the second and subsequent names in parentheses. For example:
|
||||
* <blockquote>
|
||||
* language (script, country, variant)<br>
|
||||
* language (country)<br>
|
||||
* language (variant)<br>
|
||||
* script (country)<br>
|
||||
* country<br>
|
||||
* language (script, country, variant(, extension)*)<br>
|
||||
* language (country(, extension)*)<br>
|
||||
* language (variant(, extension)*)<br>
|
||||
* script (country(, extension)*)<br>
|
||||
* country (extension)*<br>
|
||||
* </blockquote>
|
||||
* depending on which fields are specified in the locale. If the
|
||||
* language, script, country, and variant fields are all empty,
|
||||
|
@ -1931,16 +1950,17 @@ public final class Locale implements Cloneable, Serializable {
|
|||
/**
|
||||
* Returns a name for the locale that is appropriate for display
|
||||
* to the user. This will be the values returned by
|
||||
* getDisplayLanguage(), getDisplayScript(),getDisplayCountry(),
|
||||
* and getDisplayVariant() assembled into a single string.
|
||||
* The non-empty values are used in order,
|
||||
* with the second and subsequent names in parentheses. For example:
|
||||
* getDisplayLanguage(), getDisplayScript(),getDisplayCountry()
|
||||
* getDisplayVariant(), and optional <a href="./Locale.html#def_locale_extension">
|
||||
* Unicode extensions</a> assembled into a single string. The non-empty
|
||||
* values are used in order, with the second and subsequent names in
|
||||
* parentheses. For example:
|
||||
* <blockquote>
|
||||
* language (script, country, variant)<br>
|
||||
* language (country)<br>
|
||||
* language (variant)<br>
|
||||
* script (country)<br>
|
||||
* country<br>
|
||||
* language (script, country, variant(, extension)*)<br>
|
||||
* language (country(, extension)*)<br>
|
||||
* language (variant(, extension)*)<br>
|
||||
* script (country(, extension)*)<br>
|
||||
* country (extension)*<br>
|
||||
* </blockquote>
|
||||
* depending on which fields are specified in the locale. If the
|
||||
* language, script, country, and variant fields are all empty,
|
||||
|
@ -1951,7 +1971,9 @@ public final class Locale implements Cloneable, Serializable {
|
|||
* @throws NullPointerException if <code>inLocale</code> is <code>null</code>
|
||||
*/
|
||||
public String getDisplayName(Locale inLocale) {
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);
|
||||
LocaleResources lr = LocaleProviderAdapter
|
||||
.getResourceBundleBased()
|
||||
.getLocaleResources(inLocale);
|
||||
|
||||
String languageName = getDisplayLanguage(inLocale);
|
||||
String scriptName = getDisplayScript(inLocale);
|
||||
|
@ -1960,7 +1982,6 @@ public final class Locale implements Cloneable, Serializable {
|
|||
|
||||
// Get the localized patterns for formatting a display name.
|
||||
String displayNamePattern = lr.getLocaleName("DisplayNamePattern");
|
||||
String listPattern = lr.getLocaleName("ListPattern");
|
||||
String listCompositionPattern = lr.getLocaleName("ListCompositionPattern");
|
||||
|
||||
// The display name consists of a main name, followed by qualifiers.
|
||||
|
@ -1977,7 +1998,7 @@ public final class Locale implements Cloneable, Serializable {
|
|||
if (variantNames.length == 0) {
|
||||
return "";
|
||||
} else {
|
||||
return formatList(variantNames, listPattern, listCompositionPattern);
|
||||
return formatList(variantNames, listCompositionPattern);
|
||||
}
|
||||
}
|
||||
ArrayList<String> names = new ArrayList<>(4);
|
||||
|
@ -1994,6 +2015,16 @@ public final class Locale implements Cloneable, Serializable {
|
|||
names.addAll(Arrays.asList(variantNames));
|
||||
}
|
||||
|
||||
// add Unicode extensions
|
||||
if (localeExtensions != null) {
|
||||
localeExtensions.getUnicodeLocaleAttributes().stream()
|
||||
.map(key -> getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY))
|
||||
.forEach(names::add);
|
||||
localeExtensions.getUnicodeLocaleKeys().stream()
|
||||
.map(key -> getDisplayKeyTypeExtensionString(key, lr, inLocale))
|
||||
.forEach(names::add);
|
||||
}
|
||||
|
||||
// The first one in the main name
|
||||
mainName = names.get(0);
|
||||
|
||||
|
@ -2014,7 +2045,7 @@ public final class Locale implements Cloneable, Serializable {
|
|||
// list case, but this is more efficient, and we want it to be
|
||||
// efficient since all the language-only locales will not have any
|
||||
// qualifiers.
|
||||
qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null
|
||||
qualifierNames.length != 0 ? formatList(qualifierNames, listCompositionPattern) : null
|
||||
};
|
||||
|
||||
if (displayNamePattern != null) {
|
||||
|
@ -2121,74 +2152,78 @@ public final class Locale implements Cloneable, Serializable {
|
|||
// For each variant token, lookup the display name. If
|
||||
// not found, use the variant name itself.
|
||||
for (int i=0; i<names.length; ++i) {
|
||||
names[i] = getDisplayString(tokenizer.nextToken(),
|
||||
names[i] = getDisplayString(tokenizer.nextToken(), null,
|
||||
inLocale, DISPLAY_VARIANT);
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
private String getDisplayKeyTypeExtensionString(String key, LocaleResources lr, Locale inLocale) {
|
||||
String type = localeExtensions.getUnicodeLocaleType(key);
|
||||
String ret = getDisplayString(type, key, inLocale, DISPLAY_UEXT_TYPE);
|
||||
|
||||
if (ret == null || ret.equals(type)) {
|
||||
// no localization for this type. try combining key/type separately
|
||||
String displayType = type;
|
||||
switch (key) {
|
||||
case "cu":
|
||||
displayType = lr.getCurrencyName(type.toLowerCase(Locale.ROOT));
|
||||
break;
|
||||
case "rg":
|
||||
if (type != null &&
|
||||
// UN M.49 code should not be allowed here
|
||||
type.matches("^[a-zA-Z]{2}[zZ]{4}$")) {
|
||||
displayType = lr.getLocaleName(type.substring(0, 2).toUpperCase(Locale.ROOT));
|
||||
}
|
||||
break;
|
||||
case "tz":
|
||||
displayType = TimeZoneNameUtility.retrieveGenericDisplayName(
|
||||
TimeZoneNameUtility.convertLDMLShortID(type).orElse(type),
|
||||
TimeZone.LONG, inLocale);
|
||||
break;
|
||||
}
|
||||
ret = MessageFormat.format(lr.getLocaleName("ListKeyTypePattern"),
|
||||
getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY),
|
||||
Optional.ofNullable(displayType).orElse(type));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a list using given pattern strings.
|
||||
* If either of the patterns is null, then a the list is
|
||||
* formatted by concatenation with the delimiter ','.
|
||||
* @param stringList the list of strings to be formatted.
|
||||
* @param listPattern should create a MessageFormat taking 0-3 arguments
|
||||
* and formatting them into a list.
|
||||
* @param listCompositionPattern should take 2 arguments
|
||||
* and is used by composeList.
|
||||
* @param pattern should take 2 arguments for reduction
|
||||
* @return a string representing the list.
|
||||
*/
|
||||
private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
|
||||
private static String formatList(String[] stringList, String pattern) {
|
||||
// If we have no list patterns, compose the list in a simple,
|
||||
// non-localized way.
|
||||
if (listPattern == null || listCompositionPattern == null) {
|
||||
StringJoiner sj = new StringJoiner(",");
|
||||
for (int i = 0; i < stringList.length; ++i) {
|
||||
sj.add(stringList[i]);
|
||||
}
|
||||
return sj.toString();
|
||||
if (pattern == null) {
|
||||
return Arrays.stream(stringList).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
// Compose the list down to three elements if necessary
|
||||
if (stringList.length > 3) {
|
||||
MessageFormat format = new MessageFormat(listCompositionPattern);
|
||||
stringList = composeList(format, stringList);
|
||||
switch (stringList.length) {
|
||||
case 0:
|
||||
return "";
|
||||
case 1:
|
||||
return stringList[0];
|
||||
default:
|
||||
return Arrays.stream(stringList).reduce("",
|
||||
(s1, s2) -> {
|
||||
if (s1.equals("")) {
|
||||
return s2;
|
||||
}
|
||||
if (s2.equals("")) {
|
||||
return s1;
|
||||
}
|
||||
return MessageFormat.format(pattern, s1, s2);
|
||||
});
|
||||
}
|
||||
|
||||
// Rebuild the argument list with the list length as the first element
|
||||
Object[] args = new Object[stringList.length + 1];
|
||||
System.arraycopy(stringList, 0, args, 1, stringList.length);
|
||||
args[0] = stringList.length;
|
||||
|
||||
// Format it using the pattern in the resource
|
||||
MessageFormat format = new MessageFormat(listPattern);
|
||||
return format.format(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of strings, return a list shortened to three elements.
|
||||
* Shorten it by applying the given format to the first two elements
|
||||
* recursively.
|
||||
* @param format a format which takes two arguments
|
||||
* @param list a list of strings
|
||||
* @return if the list is three elements or shorter, the same list;
|
||||
* otherwise, a new list of three elements.
|
||||
*/
|
||||
private static String[] composeList(MessageFormat format, String[] list) {
|
||||
if (list.length <= 3) return list;
|
||||
|
||||
// Use the given format to compose the first two elements into one
|
||||
String[] listItems = { list[0], list[1] };
|
||||
String newItem = format.format(listItems);
|
||||
|
||||
// Form a new list one element shorter
|
||||
String[] newList = new String[list.length-1];
|
||||
System.arraycopy(list, 2, newList, 1, newList.length-1);
|
||||
newList[0] = newItem;
|
||||
|
||||
// Recurse
|
||||
return composeList(format, newList);
|
||||
}
|
||||
|
||||
// Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
|
||||
|
@ -2345,9 +2380,10 @@ public final class Locale implements Cloneable, Serializable {
|
|||
Locale locale,
|
||||
String key,
|
||||
Object... params) {
|
||||
assert params.length == 2;
|
||||
assert params.length == 3;
|
||||
int type = (Integer)params[0];
|
||||
String code = (String)params[1];
|
||||
String cat = (String)params[2];
|
||||
|
||||
switch(type) {
|
||||
case DISPLAY_LANGUAGE:
|
||||
|
@ -2358,6 +2394,10 @@ public final class Locale implements Cloneable, Serializable {
|
|||
return localeNameProvider.getDisplayVariant(code, locale);
|
||||
case DISPLAY_SCRIPT:
|
||||
return localeNameProvider.getDisplayScript(code, locale);
|
||||
case DISPLAY_UEXT_KEY:
|
||||
return localeNameProvider.getDisplayUnicodeExtensionKey(code, locale);
|
||||
case DISPLAY_UEXT_TYPE:
|
||||
return localeNameProvider.getDisplayUnicodeExtensionType(code, cat, locale);
|
||||
default:
|
||||
assert false; // shouldn't happen
|
||||
}
|
||||
|
@ -2384,7 +2424,8 @@ public final class Locale implements Cloneable, Serializable {
|
|||
DISPLAY("user.language.display",
|
||||
"user.script.display",
|
||||
"user.country.display",
|
||||
"user.variant.display"),
|
||||
"user.variant.display",
|
||||
"user.extensions.display"),
|
||||
|
||||
/**
|
||||
* Category used to represent the default locale for
|
||||
|
@ -2393,19 +2434,23 @@ public final class Locale implements Cloneable, Serializable {
|
|||
FORMAT("user.language.format",
|
||||
"user.script.format",
|
||||
"user.country.format",
|
||||
"user.variant.format");
|
||||
"user.variant.format",
|
||||
"user.extensions.format");
|
||||
|
||||
Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
|
||||
Category(String languageKey, String scriptKey, String countryKey,
|
||||
String variantKey, String extensionsKey) {
|
||||
this.languageKey = languageKey;
|
||||
this.scriptKey = scriptKey;
|
||||
this.countryKey = countryKey;
|
||||
this.variantKey = variantKey;
|
||||
this.extensionsKey = extensionsKey;
|
||||
}
|
||||
|
||||
final String languageKey;
|
||||
final String scriptKey;
|
||||
final String countryKey;
|
||||
final String variantKey;
|
||||
final String extensionsKey;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
package java.util.spi;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An abstract class for service providers that
|
||||
|
@ -141,4 +142,54 @@ public abstract class LocaleNameProvider extends LocaleServiceProvider {
|
|||
* @see java.util.Locale#getDisplayVariant(java.util.Locale)
|
||||
*/
|
||||
public abstract String getDisplayVariant(String variant, Locale locale);
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given
|
||||
* <a href="../Locale.html#def_locale_extension">Unicode extension</a> key,
|
||||
* and the given locale that is appropriate for display to the user.
|
||||
* If the name returned cannot be localized according to {@code locale},
|
||||
* this method returns null.
|
||||
* @implSpec the default implementation returns {@code null}.
|
||||
* @param key the Unicode Extension key, not null.
|
||||
* @param locale the desired locale, not null.
|
||||
* @return the name of the given key string for the specified locale,
|
||||
* or null if it's not available.
|
||||
* @exception NullPointerException if {@code key} or {@code locale} is null
|
||||
* @exception IllegalArgumentException if {@code locale} isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @since 10
|
||||
*/
|
||||
public String getDisplayUnicodeExtensionKey(String key, Locale locale) {
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(locale);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given
|
||||
* <a href="../Locale.html#def_locale_extension">Unicode extension</a> type,
|
||||
* and the given locale that is appropriate for display to the user.
|
||||
* If the name returned cannot be localized according to {@code locale},
|
||||
* this method returns null.
|
||||
* @implSpec the default implementation returns {@code null}.
|
||||
* @param type the Unicode Extension type, not null.
|
||||
* @param key the Unicode Extension key for this {@code type}, not null.
|
||||
* @param locale the desired locale, not null.
|
||||
* @return the name of the given type string for the specified locale,
|
||||
* or null if it's not available.
|
||||
* @exception NullPointerException if {@code key}, {@code type} or {@code locale} is null
|
||||
* @exception IllegalArgumentException if {@code locale} isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @since 10
|
||||
*/
|
||||
public String getDisplayUnicodeExtensionType(String type, String key, Locale locale) {
|
||||
Objects.requireNonNull(type);
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(locale);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ public final class LauncherHelper {
|
|||
Locale locale = Locale.getDefault();
|
||||
ostream.println(LOCALE_SETTINGS);
|
||||
ostream.println(INDENT + "default locale = " +
|
||||
locale.getDisplayLanguage());
|
||||
locale.getDisplayName());
|
||||
ostream.println(INDENT + "default display locale = " +
|
||||
Locale.getDefault(Category.DISPLAY).getDisplayName());
|
||||
ostream.println(INDENT + "default format locale = " +
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.cldr;
|
||||
|
||||
import static sun.util.locale.provider.LocaleProviderAdapter.Type;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
import sun.util.locale.provider.CalendarDataProviderImpl;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the
|
||||
* {@link java.util.spi.CalendarDataProvider CalendarDataProvider} class
|
||||
* for the CLDR LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class CLDRCalendarDataProviderImpl extends CalendarDataProviderImpl {
|
||||
|
||||
private static Map<String, Integer> firstDay = new ConcurrentHashMap<>();
|
||||
private static Map<String, Integer> minDays = new ConcurrentHashMap<>();
|
||||
|
||||
public CLDRCalendarDataProviderImpl(Type type, Set<String> langtags) {
|
||||
super(type, langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
return findValue(CalendarDataUtility.FIRST_DAY_OF_WEEK, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
return findValue(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the requested integer value for the locale.
|
||||
* Each resource consists of the following:
|
||||
*
|
||||
* (n: cc1 cc2 ... ccx;)*
|
||||
*
|
||||
* where 'n' is the integer for the following region codes, terminated by
|
||||
* a ';'.
|
||||
*
|
||||
*/
|
||||
private static int findValue(String key, Locale locale) {
|
||||
Map<String, Integer> map = CalendarDataUtility.FIRST_DAY_OF_WEEK.equals(key) ?
|
||||
firstDay : minDays;
|
||||
String region = locale.getCountry();
|
||||
|
||||
if (region.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Integer val = map.get(region);
|
||||
if (val == null) {
|
||||
String valStr =
|
||||
LocaleProviderAdapter.forType(Type.CLDR).getLocaleResources(Locale.ROOT)
|
||||
.getCalendarData(key);
|
||||
val = retrieveInteger(valStr, region)
|
||||
.orElse(retrieveInteger(valStr, "001").orElse(0));
|
||||
map.putIfAbsent(region, val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
private static Optional<Integer> retrieveInteger(String src, String region) {
|
||||
return Arrays.stream(src.split(";"))
|
||||
.filter(entry -> entry.contains(region))
|
||||
.map(entry -> entry.substring(0, entry.indexOf(":")))
|
||||
.findAny()
|
||||
.map(Integer::parseInt);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ package sun.util.cldr;
|
|||
|
||||
import java.security.AccessController;
|
||||
import java.security.AccessControlException;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
|
@ -37,15 +38,16 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import sun.util.locale.provider.JRELocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleDataMetaInfo;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter implementation for the CLDR locale data.
|
||||
|
@ -105,6 +107,24 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarDataProvider getCalendarDataProvider() {
|
||||
if (calendarDataProvider == null) {
|
||||
CalendarDataProvider provider = AccessController.doPrivileged(
|
||||
(PrivilegedAction<CalendarDataProvider>) () ->
|
||||
new CLDRCalendarDataProviderImpl(
|
||||
getAdapterType(),
|
||||
getLanguageTagSet("CalendarData")));
|
||||
|
||||
synchronized (this) {
|
||||
if (calendarDataProvider == null) {
|
||||
calendarDataProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return calendarDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollatorProvider getCollatorProvider() {
|
||||
return null;
|
||||
|
@ -123,6 +143,10 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
|
|||
|
||||
@Override
|
||||
protected Set<String> createLanguageTagSet(String category) {
|
||||
// Assume all categories support the same set as AvailableLocales
|
||||
// in CLDR adapter.
|
||||
category = "AvailableLocales";
|
||||
|
||||
// Directly call Base tags, as we know it's in the base module.
|
||||
String supportedLocaleString = baseMetaInfo.availableLanguageTags(category);
|
||||
String nonBaseTags = null;
|
||||
|
@ -220,4 +244,11 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
|
|||
|| langtags.contains(locale.stripExtensions().toLanguageTag())
|
||||
|| langtags.contains(getEquivalentLoc(locale).toLanguageTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time zone ID from an LDML's short ID
|
||||
*/
|
||||
public Optional<String> getTimeZoneID(String shortID) {
|
||||
return Optional.ofNullable(baseMetaInfo.tzShortIDs().get(shortID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -46,14 +46,16 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av
|
|||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
String fw = LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
.getCalendarData(CalendarDataUtility.FIRST_DAY_OF_WEEK);
|
||||
return convertToCalendarData(fw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
String md = LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
.getCalendarData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK);
|
||||
return convertToCalendarData(md);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,4 +67,9 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av
|
|||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
|
||||
private int convertToCalendarData(String src) {
|
||||
int val = Integer.parseInt(src);
|
||||
return (src.isEmpty() || val <= 0 || val > 7) ? 0 : val;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -47,10 +47,34 @@ public class CalendarDataUtility {
|
|||
}
|
||||
|
||||
public static int retrieveFirstDayOfWeek(Locale locale) {
|
||||
// Look for the Unicode Extension in the locale parameter
|
||||
if (locale.hasExtensions()) {
|
||||
String fw = locale.getUnicodeLocaleType("fw");
|
||||
if (fw != null) {
|
||||
switch (fw.toLowerCase(Locale.ROOT)) {
|
||||
case "mon":
|
||||
return MONDAY;
|
||||
case "tue":
|
||||
return TUESDAY;
|
||||
case "wed":
|
||||
return WEDNESDAY;
|
||||
case "thu":
|
||||
return THURSDAY;
|
||||
case "fri":
|
||||
return FRIDAY;
|
||||
case "sat":
|
||||
return SATURDAY;
|
||||
case "sun":
|
||||
return SUNDAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
|
||||
Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
|
||||
locale, true, FIRST_DAY_OF_WEEK);
|
||||
findRegionOverride(locale),
|
||||
true, FIRST_DAY_OF_WEEK);
|
||||
return (value != null && (value >= SUNDAY && value <= SATURDAY)) ? value : SUNDAY;
|
||||
}
|
||||
|
||||
|
@ -58,7 +82,8 @@ public class CalendarDataUtility {
|
|||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
|
||||
Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
|
||||
locale, true, MINIMAL_DAYS_IN_FIRST_WEEK);
|
||||
findRegionOverride(locale),
|
||||
true, MINIMAL_DAYS_IN_FIRST_WEEK);
|
||||
return (value != null && (value >= 1 && value <= 7)) ? value : 1;
|
||||
}
|
||||
|
||||
|
@ -102,6 +127,32 @@ public class CalendarDataUtility {
|
|||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to look for a region override extension.
|
||||
* If no region override is found, returns the original locale.
|
||||
*/
|
||||
public static Locale findRegionOverride(Locale l) {
|
||||
String rg = l.getUnicodeLocaleType("rg");
|
||||
Locale override = l;
|
||||
|
||||
if (rg != null && rg.length() == 6) {
|
||||
// UN M.49 code should not be allowed here
|
||||
// cannot use regex here, as it could be a recursive call
|
||||
rg = rg.toUpperCase(Locale.ROOT);
|
||||
if (rg.charAt(0) >= 0x0041 &&
|
||||
rg.charAt(0) <= 0x005A &&
|
||||
rg.charAt(1) >= 0x0041 &&
|
||||
rg.charAt(1) <= 0x005A &&
|
||||
rg.substring(2).equals("ZZZZ")) {
|
||||
override = new Locale.Builder().setLocale(l)
|
||||
.setRegion(rg.substring(0, 2))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
return override;
|
||||
}
|
||||
|
||||
static String normalizeCalendarType(String requestID) {
|
||||
String type;
|
||||
if (requestID.equals("gregorian") || requestID.equals("iso8601")) {
|
||||
|
@ -179,7 +230,7 @@ public class CalendarDataUtility {
|
|||
}
|
||||
}
|
||||
|
||||
private static class CalendarWeekParameterGetter
|
||||
private static class CalendarWeekParameterGetter
|
||||
implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarDataProvider,
|
||||
Integer> {
|
||||
private static final CalendarWeekParameterGetter INSTANCE =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
|
@ -32,6 +32,7 @@ import java.util.Calendar;
|
|||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.DateFormatProvider
|
||||
|
@ -147,11 +148,14 @@ public class DateFormatProviderImpl extends DateFormatProvider implements Availa
|
|||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("", locale);
|
||||
// Check for region override
|
||||
Locale rg = CalendarDataUtility.findRegionOverride(locale);
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("", rg);
|
||||
Calendar cal = sdf.getCalendar();
|
||||
try {
|
||||
String pattern = LocaleProviderAdapter.forType(type)
|
||||
.getLocaleResources(locale).getDateTimePattern(timeStyle, dateStyle,
|
||||
.getLocaleResources(rg).getDateTimePattern(timeStyle, dateStyle,
|
||||
cal);
|
||||
sdf.applyPattern(pattern);
|
||||
} catch (MissingResourceException mre) {
|
||||
|
@ -159,6 +163,15 @@ public class DateFormatProviderImpl extends DateFormatProvider implements Availa
|
|||
sdf.applyPattern("M/d/yy h:mm a");
|
||||
}
|
||||
|
||||
// Check for timezone override
|
||||
String tz = locale.getUnicodeLocaleType("tz");
|
||||
if (tz != null) {
|
||||
sdf.setTimeZone(
|
||||
TimeZoneNameUtility.convertLDMLShortID(tz)
|
||||
.map(TimeZone::getTimeZone)
|
||||
.orElseGet(sdf::getTimeZone));
|
||||
}
|
||||
|
||||
return sdf;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -130,7 +130,7 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
|
|||
private volatile CurrencyNameProvider currencyNameProvider;
|
||||
private volatile LocaleNameProvider localeNameProvider;
|
||||
private volatile TimeZoneNameProvider timeZoneNameProvider;
|
||||
private volatile CalendarDataProvider calendarDataProvider;
|
||||
protected volatile CalendarDataProvider calendarDataProvider;
|
||||
private volatile CalendarNameProvider calendarNameProvider;
|
||||
|
||||
private volatile CalendarProvider calendarProvider;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* LocaleData meta info SPI
|
||||
*
|
||||
|
@ -46,4 +48,13 @@ public interface LocaleDataMetaInfo {
|
|||
* @return concatenated language tags, separated by a space.
|
||||
*/
|
||||
public String availableLanguageTags(String category);
|
||||
|
||||
/**
|
||||
* Returns a map for short time zone ids in BCP47 Unicode extension and
|
||||
* the long time zone ids.
|
||||
* @return map of short id to long ids, separated by a space.
|
||||
*/
|
||||
default public Map<String, String> tzShortIDs() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -168,6 +168,28 @@ public class LocaleNameProviderImpl extends LocaleNameProvider implements Availa
|
|||
return getDisplayString("%%"+vrnt, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayUnicodeExtensionKey(String key, Locale locale) {
|
||||
super.getDisplayUnicodeExtensionKey(key, locale); // null check
|
||||
String rbKey = "key." + key;
|
||||
String name = getDisplayString(rbKey, locale);
|
||||
return rbKey.equals(name) ? key : name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayUnicodeExtensionType(String extType, String key, Locale locale) {
|
||||
super.getDisplayUnicodeExtensionType(extType, key, locale); // null check
|
||||
String rbKey = "type." + key + "." + extType;
|
||||
String name = getDisplayString(rbKey, locale);
|
||||
return rbKey.equals(name) ? extType : name;
|
||||
}
|
||||
|
||||
private String getDisplayString(String key, Locale locale) {
|
||||
if (key == null || locale == null) {
|
||||
throw new NullPointerException();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -122,23 +122,21 @@ public class LocaleResources {
|
|||
return (byte[]) localeData.getBreakIteratorResources(locale).getObject(key);
|
||||
}
|
||||
|
||||
int getCalendarData(String key) {
|
||||
Integer caldata;
|
||||
public String getCalendarData(String key) {
|
||||
String caldata = "";
|
||||
String cacheKey = CALENDAR_DATA + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
if (data == null || ((caldata = (Integer) data.get()) == null)) {
|
||||
if (data == null || ((caldata = (String) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getCalendarData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
caldata = Integer.parseInt(rb.getString(key));
|
||||
} else {
|
||||
caldata = 0;
|
||||
caldata = rb.getString(key);
|
||||
}
|
||||
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) caldata, referenceQueue));
|
||||
new ResourceReference(cacheKey, caldata, referenceQueue));
|
||||
}
|
||||
|
||||
return caldata;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
|
@ -173,9 +173,14 @@ public class NumberFormatProviderImpl extends NumberFormatProvider implements Av
|
|||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// Check for region override
|
||||
Locale override = locale.getUnicodeLocaleType("nu") == null ?
|
||||
CalendarDataUtility.findRegionOverride(locale) :
|
||||
locale;
|
||||
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
|
||||
String[] numberPatterns = adapter.getLocaleResources(locale).getNumberPatterns();
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
String[] numberPatterns = adapter.getLocaleResources(override).getNumberPatterns();
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(override);
|
||||
int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
|
||||
DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
|
@ -160,28 +160,24 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public BreakIterator getWordInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getWordInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getLineInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getLineInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getCharacterInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getCharacterInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getSentenceInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getSentenceInstance(locale);
|
||||
}
|
||||
|
||||
|
@ -215,7 +211,6 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public Collator getInstance(Locale locale) {
|
||||
CollatorProvider cp = getImpl(locale);
|
||||
assert cp != null;
|
||||
return cp.getInstance(locale);
|
||||
}
|
||||
}
|
||||
|
@ -249,21 +244,18 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public DateFormat getTimeInstance(int style, Locale locale) {
|
||||
DateFormatProvider dfp = getImpl(locale);
|
||||
assert dfp != null;
|
||||
return dfp.getTimeInstance(style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateInstance(int style, Locale locale) {
|
||||
DateFormatProvider dfp = getImpl(locale);
|
||||
assert dfp != null;
|
||||
return dfp.getDateInstance(style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) {
|
||||
DateFormatProvider dfp = getImpl(locale);
|
||||
assert dfp != null;
|
||||
return dfp.getDateTimeInstance(dateStyle, timeStyle, locale);
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +289,6 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public DateFormatSymbols getInstance(Locale locale) {
|
||||
DateFormatSymbolsProvider dfsp = getImpl(locale);
|
||||
assert dfsp != null;
|
||||
return dfsp.getInstance(locale);
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +322,6 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public DecimalFormatSymbols getInstance(Locale locale) {
|
||||
DecimalFormatSymbolsProvider dfsp = getImpl(locale);
|
||||
assert dfsp != null;
|
||||
return dfsp.getInstance(locale);
|
||||
}
|
||||
}
|
||||
|
@ -365,28 +355,24 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public NumberFormat getCurrencyInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getCurrencyInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getIntegerInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getIntegerInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getNumberInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getNumberInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getPercentInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getPercentInstance(locale);
|
||||
}
|
||||
}
|
||||
|
@ -420,14 +406,12 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
CalendarDataProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getFirstDayOfWeek(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
CalendarDataProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getMinimalDaysInFirstWeek(locale);
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +447,6 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
int field, int value,
|
||||
int style, Locale locale) {
|
||||
CalendarNameProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getDisplayName(calendarType, field, value, style, locale);
|
||||
}
|
||||
|
||||
|
@ -472,7 +455,6 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
int field, int style,
|
||||
Locale locale) {
|
||||
CalendarNameProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getDisplayNames(calendarType, field, style, locale);
|
||||
}
|
||||
}
|
||||
|
@ -506,14 +488,12 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public String getSymbol(String currencyCode, Locale locale) {
|
||||
CurrencyNameProvider cnp = getImpl(locale);
|
||||
assert cnp != null;
|
||||
return cnp.getSymbol(currencyCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String currencyCode, Locale locale) {
|
||||
CurrencyNameProvider cnp = getImpl(locale);
|
||||
assert cnp != null;
|
||||
return cnp.getDisplayName(currencyCode, locale);
|
||||
}
|
||||
}
|
||||
|
@ -547,30 +527,38 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public String getDisplayLanguage(String languageCode, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayLanguage(languageCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayScript(String scriptCode, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayScript(scriptCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCountry(String countryCode, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayCountry(countryCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVariant(String variant, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayVariant(variant, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayUnicodeExtensionKey(String key, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
return lnp.getDisplayUnicodeExtensionKey(key, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayUnicodeExtensionType(String extType, String key, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
return lnp.getDisplayUnicodeExtensionType(extType, key, locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class TimeZoneNameProviderDelegate extends TimeZoneNameProvider
|
||||
|
@ -602,14 +590,12 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
|||
@Override
|
||||
public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
|
||||
TimeZoneNameProvider tznp = getImpl(locale);
|
||||
assert tznp != null;
|
||||
return tznp.getDisplayName(ID, daylight, style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGenericDisplayName(String ID, int style, Locale locale) {
|
||||
TimeZoneNameProvider tznp = getImpl(locale);
|
||||
assert tznp != null;
|
||||
return tznp.getGenericDisplayName(ID, style, locale);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
|
@ -31,10 +31,13 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.cldr.CLDRLocaleProviderAdapter;
|
||||
import static sun.util.locale.provider.LocaleProviderAdapter.Type;
|
||||
|
||||
/**
|
||||
* Utility class that deals with the localized time zone names
|
||||
|
@ -152,6 +155,18 @@ public final class TimeZoneNameUtility {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the time zone id from LDML's 5-letter id to tzdb's id
|
||||
*
|
||||
* @param shortID time zone short ID defined in LDML
|
||||
* @return the tzdb's time zone ID
|
||||
*/
|
||||
public static Optional<String> convertLDMLShortID(String shortID) {
|
||||
return ((CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR))
|
||||
.getTimeZoneID(shortID)
|
||||
.map(id -> id.replaceAll("\\s.*", ""));
|
||||
}
|
||||
|
||||
private static String[] retrieveDisplayNamesImpl(String id, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2005, 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
|
||||
|
@ -1164,8 +1164,7 @@ ZW=Zimbabwe
|
|||
|
||||
|
||||
# locale name patterns
|
||||
# rarely localized
|
||||
|
||||
DisplayNamePattern={0,choice,0#|1#{1}|2#{1} ({2})}
|
||||
ListPattern={0,choice,0#|1#{1}|2#{1},{2}|3#{1},{2},{3}}
|
||||
ListKeyTypePattern={0}:{1}
|
||||
ListCompositionPattern={0},{1}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue