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:
Naoto Sato 2017-12-12 10:21:58 -08:00
parent 3246c46f41
commit f065141ddc
55 changed files with 3631 additions and 890 deletions

View file

@ -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.

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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();
}

View file

@ -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;
}