mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8176706: Additional Date-Time Formats
Reviewed-by: joehw, rriggs
This commit is contained in:
parent
0f3d3ac32c
commit
9b74c3f2e7
12 changed files with 809 additions and 96 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, 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
|
||||
|
@ -81,7 +81,6 @@ import java.time.Period;
|
|||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.chrono.ChronoZonedDateTime;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser;
|
||||
|
@ -718,6 +717,57 @@ public final class DateTimeFormatter {
|
|||
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Creates a locale specific formatter derived from the requested template for
|
||||
* the ISO chronology. The requested template is a series of typical pattern
|
||||
* symbols in canonical order from the largest date or time unit to the smallest,
|
||||
* which can be expressed with the following regular expression:
|
||||
* {@snippet :
|
||||
* "G{0,5}" + // Era
|
||||
* "y*" + // Year
|
||||
* "Q{0,5}" + // Quarter
|
||||
* "M{0,5}" + // Month
|
||||
* "w*" + // Week of Week Based Year
|
||||
* "E{0,5}" + // Day of Week
|
||||
* "d{0,2}" + // Day of Month
|
||||
* "B{0,5}" + // Period/AmPm of Day
|
||||
* "[hHjC]{0,2}" + // Hour of Day/AmPm (refer to LDML for 'j' and 'C')
|
||||
* "m{0,2}" + // Minute of Hour
|
||||
* "s{0,2}" + // Second of Minute
|
||||
* "[vz]{0,4}" // Zone
|
||||
* }
|
||||
* All pattern symbols are optional, and each pattern symbol represents a field,
|
||||
* for example, 'M' represents the Month field. The number of the pattern symbol letters follows the
|
||||
* same presentation, such as "number" or "text" as in the <a href="#patterns">Patterns for
|
||||
* Formatting and Parsing</a> section. Other pattern symbols in the requested template are
|
||||
* invalid.
|
||||
* <p>
|
||||
* The mapping of the requested template to the closest of the available localized formats
|
||||
* is defined by the
|
||||
* <a href="https://www.unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems">
|
||||
* Unicode LDML specification</a>. For example, the formatter created from the requested template
|
||||
* {@code yMMM} will format the date '2020-06-16' to 'Jun 2020' in the {@link Locale#US US locale}.
|
||||
* <p>
|
||||
* The locale is determined from the formatter. The formatter returned directly by
|
||||
* this method uses the {@link Locale#getDefault() default FORMAT locale}.
|
||||
* The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
|
||||
* on the result of this method.
|
||||
* <p>
|
||||
* The returned formatter has no override zone.
|
||||
* It uses {@link ResolverStyle#SMART SMART} resolver style.
|
||||
*
|
||||
* @param requestedTemplate the requested template, not null
|
||||
* @return the formatter based on the {@code requestedTemplate} pattern, not null
|
||||
* @throws IllegalArgumentException if {@code requestedTemplate} is invalid
|
||||
* @see #ofPattern(String)
|
||||
* @since 19
|
||||
*/
|
||||
public static DateTimeFormatter ofLocalizedPattern(String requestedTemplate) {
|
||||
return new DateTimeFormatterBuilder().appendLocalized(requestedTemplate)
|
||||
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* The ISO date formatter that formats or parses a date without an
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, 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
|
||||
|
@ -227,6 +227,42 @@ public final class DateTimeFormatterBuilder {
|
|||
CalendarDataUtility.findRegionOverride(locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the formatting pattern for the requested template for a locale and chronology.
|
||||
* The locale and chronology are used to lookup the locale specific format
|
||||
* for the requested template.
|
||||
* <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.
|
||||
* <p>
|
||||
* Refer to {@link #appendLocalized(String)} for the detail of {@code requestedTemplate}
|
||||
* argument.
|
||||
*
|
||||
* @param requestedTemplate the requested template, not null
|
||||
* @param chrono the Chronology, non-null
|
||||
* @param locale the locale, non-null
|
||||
* @return the locale and Chronology specific formatting pattern
|
||||
* @throws IllegalArgumentException if {@code requestedTemplate} does not match
|
||||
* the regular expression syntax described in {@link #appendLocalized(String)}.
|
||||
* @throws DateTimeException if a match for the localized pattern for
|
||||
* {@code requestedTemplate} is not available
|
||||
* @see #appendLocalized(String)
|
||||
* @since 19
|
||||
*/
|
||||
public static String getLocalizedDateTimePattern(String requestedTemplate,
|
||||
Chronology chrono, Locale locale) {
|
||||
Objects.requireNonNull(requestedTemplate, "requestedTemplate");
|
||||
Objects.requireNonNull(chrono, "chrono");
|
||||
Objects.requireNonNull(locale, "locale");
|
||||
Locale override = CalendarDataUtility.findRegionOverride(locale);
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, override);
|
||||
JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider();
|
||||
return provider.getJavaTimeDateTimePattern(requestedTemplate,
|
||||
chrono.getCalendarType(),
|
||||
override);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given FormatStyle to the java.text.DateFormat style.
|
||||
*
|
||||
|
@ -1423,6 +1459,84 @@ public final class DateTimeFormatterBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// RegEx pattern for skeleton validity checking
|
||||
private static final Pattern VALID_TEMPLATE_PATTERN = Pattern.compile(
|
||||
"G{0,5}" + // Era
|
||||
"y*" + // Year
|
||||
"Q{0,5}" + // Quarter
|
||||
"M{0,5}" + // Month
|
||||
"w*" + // Week of Week Based Year
|
||||
"E{0,5}" + // Day of Week
|
||||
"d{0,2}" + // Day of Month
|
||||
"B{0,5}" + // Period/AmPm of Day
|
||||
"[hHjC]{0,2}" + // Hour of Day/AmPm
|
||||
"m{0,2}" + // Minute of Hour
|
||||
"s{0,2}" + // Second of Minute
|
||||
"[vz]{0,4}"); // Zone
|
||||
/**
|
||||
* Appends a localized pattern to the formatter using the requested template.
|
||||
* <p>
|
||||
* This appends a localized section to the builder, suitable for outputting
|
||||
* a date, time or date-time combination. The format of the localized
|
||||
* section is lazily looked up based on three items:
|
||||
* <ul>
|
||||
* <li>the {@code requestedTemplate} specified to this method
|
||||
* <li>the {@code Locale} of the {@code DateTimeFormatter}
|
||||
* <li>the {@code Chronology} of the {@code DateTimeFormatter} unless overridden
|
||||
* </ul>
|
||||
* During formatting, the chronology is obtained from the temporal object
|
||||
* being formatted, which may have been overridden by
|
||||
* {@link DateTimeFormatter#withChronology(Chronology)}.
|
||||
* <p>
|
||||
* During parsing, if a chronology has already been parsed, then it is used.
|
||||
* Otherwise the default from {@code DateTimeFormatter.withChronology(Chronology)}
|
||||
* is used, with {@code IsoChronology} as the fallback.
|
||||
* <p>
|
||||
* The requested template is a series of typical pattern
|
||||
* symbols in canonical order from the largest date or time unit to the smallest,
|
||||
* which can be expressed with the following regular expression:
|
||||
* {@snippet :
|
||||
* "G{0,5}" + // Era
|
||||
* "y*" + // Year
|
||||
* "Q{0,5}" + // Quarter
|
||||
* "M{0,5}" + // Month
|
||||
* "w*" + // Week of Week Based Year
|
||||
* "E{0,5}" + // Day of Week
|
||||
* "d{0,2}" + // Day of Month
|
||||
* "B{0,5}" + // Period/AmPm of Day
|
||||
* "[hHjC]{0,2}" + // Hour of Day/AmPm (refer to LDML for 'j' and 'C')
|
||||
* "m{0,2}" + // Minute of Hour
|
||||
* "s{0,2}" + // Second of Minute
|
||||
* "[vz]{0,4}" // Zone
|
||||
* }
|
||||
* All pattern symbols are optional, and each pattern symbol represents a field,
|
||||
* for example, 'M' represents the Month field. The number of the pattern symbol letters follows the
|
||||
* same presentation, such as "number" or "text" as in the
|
||||
* <a href="./DateTimeFormatter.html#patterns">Patterns for Formatting and Parsing</a> section.
|
||||
* Other pattern symbols in the requested template are invalid.
|
||||
* <p>
|
||||
* The mapping of the requested template to the closest of the available localized formats
|
||||
* is defined by the
|
||||
* <a href="https://www.unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems">
|
||||
* Unicode LDML specification</a>. For example, the formatter created from the requested template
|
||||
* {@code yMMM} will format the date '2020-06-16' to 'Jun 2020' in the {@link Locale#US US locale}.
|
||||
*
|
||||
* @param requestedTemplate the requested template to use, not null
|
||||
* @return this, for chaining, not null
|
||||
* @throws IllegalArgumentException if {@code requestedTemplate} is invalid
|
||||
* @see #appendPattern(String)
|
||||
* @since 19
|
||||
*/
|
||||
public DateTimeFormatterBuilder appendLocalized(String requestedTemplate) {
|
||||
Objects.requireNonNull(requestedTemplate, "requestedTemplate");
|
||||
if (!VALID_TEMPLATE_PATTERN.matcher(requestedTemplate).matches()) {
|
||||
throw new IllegalArgumentException("Requested template is invalid: " + requestedTemplate);
|
||||
}
|
||||
appendInternal(new LocalizedPrinterParser(requestedTemplate));
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Appends a character literal to the formatter.
|
||||
|
@ -2378,11 +2492,11 @@ public final class DateTimeFormatterBuilder {
|
|||
private final DateTimePrinterParser[] printerParsers;
|
||||
private final boolean optional;
|
||||
|
||||
CompositePrinterParser(List<DateTimePrinterParser> printerParsers, boolean optional) {
|
||||
private CompositePrinterParser(List<DateTimePrinterParser> printerParsers, boolean optional) {
|
||||
this(printerParsers.toArray(new DateTimePrinterParser[0]), optional);
|
||||
}
|
||||
|
||||
CompositePrinterParser(DateTimePrinterParser[] printerParsers, boolean optional) {
|
||||
private CompositePrinterParser(DateTimePrinterParser[] printerParsers, boolean optional) {
|
||||
this.printerParsers = printerParsers;
|
||||
this.optional = optional;
|
||||
}
|
||||
|
@ -2476,7 +2590,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param padWidth the width to pad to, 1 or greater
|
||||
* @param padChar the pad character
|
||||
*/
|
||||
PadPrinterParserDecorator(DateTimePrinterParser printerParser, int padWidth, char padChar) {
|
||||
private PadPrinterParserDecorator(DateTimePrinterParser printerParser, int padWidth, char padChar) {
|
||||
// input checked by DateTimeFormatterBuilder
|
||||
this.printerParser = printerParser;
|
||||
this.padWidth = padWidth;
|
||||
|
@ -2584,7 +2698,7 @@ public final class DateTimeFormatterBuilder {
|
|||
private final TemporalField field;
|
||||
private final long value;
|
||||
|
||||
DefaultValueParser(TemporalField field, long value) {
|
||||
private DefaultValueParser(TemporalField field, long value) {
|
||||
this.field = field;
|
||||
this.value = value;
|
||||
}
|
||||
|
@ -2608,7 +2722,7 @@ public final class DateTimeFormatterBuilder {
|
|||
static final class CharLiteralPrinterParser implements DateTimePrinterParser {
|
||||
private final char literal;
|
||||
|
||||
CharLiteralPrinterParser(char literal) {
|
||||
private CharLiteralPrinterParser(char literal) {
|
||||
this.literal = literal;
|
||||
}
|
||||
|
||||
|
@ -2651,7 +2765,7 @@ public final class DateTimeFormatterBuilder {
|
|||
static final class StringLiteralPrinterParser implements DateTimePrinterParser {
|
||||
private final String literal;
|
||||
|
||||
StringLiteralPrinterParser(String literal) {
|
||||
private StringLiteralPrinterParser(String literal) {
|
||||
this.literal = literal; // validated by caller
|
||||
}
|
||||
|
||||
|
@ -2717,7 +2831,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param maxWidth the maximum field width, from minWidth to 19
|
||||
* @param signStyle the positive/negative sign style, not null
|
||||
*/
|
||||
NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) {
|
||||
private NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) {
|
||||
// validated by caller
|
||||
this.field = field;
|
||||
this.minWidth = minWidth;
|
||||
|
@ -3008,7 +3122,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param baseValue the base value
|
||||
* @param baseDate the base date
|
||||
*/
|
||||
ReducedPrinterParser(TemporalField field, int minWidth, int maxWidth,
|
||||
private ReducedPrinterParser(TemporalField field, int minWidth, int maxWidth,
|
||||
int baseValue, ChronoLocalDate baseDate) {
|
||||
this(field, minWidth, maxWidth, baseValue, baseDate, 0);
|
||||
if (minWidth < 1 || minWidth > 10) {
|
||||
|
@ -3161,7 +3275,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param maxWidth the maximum width to output, from 0 to 9
|
||||
* @param decimalPoint whether to output the localized decimal point symbol
|
||||
*/
|
||||
NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint) {
|
||||
private NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint) {
|
||||
this(minWidth, maxWidth, decimalPoint, 0);
|
||||
if (minWidth < 0 || minWidth > 9) {
|
||||
throw new IllegalArgumentException("Minimum width must be from 0 to 9 inclusive but was " + minWidth);
|
||||
|
@ -3183,7 +3297,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param decimalPoint whether to output the localized decimal point symbol
|
||||
* @param subsequentWidth the subsequentWidth for this instance
|
||||
*/
|
||||
NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) {
|
||||
private NanosPrinterParser(int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) {
|
||||
super(NANO_OF_SECOND, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
|
||||
this.decimalPoint = decimalPoint;
|
||||
}
|
||||
|
@ -3366,7 +3480,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param maxWidth the maximum width to output, from 0 to 9
|
||||
* @param decimalPoint whether to output the localized decimal point symbol
|
||||
*/
|
||||
FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) {
|
||||
private FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) {
|
||||
this(field, minWidth, maxWidth, decimalPoint, 0);
|
||||
Objects.requireNonNull(field, "field");
|
||||
if (field.range().isFixed() == false) {
|
||||
|
@ -3393,7 +3507,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param decimalPoint whether to output the localized decimal point symbol
|
||||
* @param subsequentWidth the subsequentWidth for this instance
|
||||
*/
|
||||
FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) {
|
||||
private FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) {
|
||||
super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
|
||||
this.decimalPoint = decimalPoint;
|
||||
ValueRange range = field.range();
|
||||
|
@ -3583,7 +3697,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param textStyle the text style, not null
|
||||
* @param provider the text provider, not null
|
||||
*/
|
||||
TextPrinterParser(TemporalField field, TextStyle textStyle, DateTimeTextProvider provider) {
|
||||
private TextPrinterParser(TemporalField field, TextStyle textStyle, DateTimeTextProvider provider) {
|
||||
// validated by caller
|
||||
this.field = field;
|
||||
this.textStyle = textStyle;
|
||||
|
@ -3681,7 +3795,7 @@ public final class DateTimeFormatterBuilder {
|
|||
private static final long SECONDS_0000_TO_1970 = ((146097L * 5L) - (30L * 365L + 7L)) * 86400L;
|
||||
private final int fractionalDigits;
|
||||
|
||||
InstantPrinterParser(int fractionalDigits) {
|
||||
private InstantPrinterParser(int fractionalDigits) {
|
||||
this.fractionalDigits = fractionalDigits;
|
||||
}
|
||||
|
||||
|
@ -3830,7 +3944,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param pattern the pattern
|
||||
* @param noOffsetText the text to use for UTC, not null
|
||||
*/
|
||||
OffsetIdPrinterParser(String pattern, String noOffsetText) {
|
||||
private OffsetIdPrinterParser(String pattern, String noOffsetText) {
|
||||
Objects.requireNonNull(pattern, "pattern");
|
||||
Objects.requireNonNull(noOffsetText, "noOffsetText");
|
||||
this.type = checkPattern(pattern);
|
||||
|
@ -4312,7 +4426,7 @@ public final class DateTimeFormatterBuilder {
|
|||
|
||||
/** Display in generic time-zone format. True in case of pattern letter 'v' */
|
||||
private final boolean isGeneric;
|
||||
ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) {
|
||||
private ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) {
|
||||
super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")");
|
||||
this.textStyle = Objects.requireNonNull(textStyle, "textStyle");
|
||||
this.isGeneric = isGeneric;
|
||||
|
@ -4484,7 +4598,7 @@ public final class DateTimeFormatterBuilder {
|
|||
private final TemporalQuery<ZoneId> query;
|
||||
private final String description;
|
||||
|
||||
ZoneIdPrinterParser(TemporalQuery<ZoneId> query, String description) {
|
||||
private ZoneIdPrinterParser(TemporalQuery<ZoneId> query, String description) {
|
||||
this.query = query;
|
||||
this.description = description;
|
||||
}
|
||||
|
@ -4903,7 +5017,7 @@ public final class DateTimeFormatterBuilder {
|
|||
/** The text style to output, null means the ID. */
|
||||
private final TextStyle textStyle;
|
||||
|
||||
ChronoPrinterParser(TextStyle textStyle) {
|
||||
private ChronoPrinterParser(TextStyle textStyle) {
|
||||
// validated by caller
|
||||
this.textStyle = textStyle;
|
||||
}
|
||||
|
@ -4978,6 +5092,7 @@ public final class DateTimeFormatterBuilder {
|
|||
|
||||
private final FormatStyle dateStyle;
|
||||
private final FormatStyle timeStyle;
|
||||
private final String requestedTemplate;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -4985,10 +5100,23 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param dateStyle the date style to use, may be null
|
||||
* @param timeStyle the time style to use, may be null
|
||||
*/
|
||||
LocalizedPrinterParser(FormatStyle dateStyle, FormatStyle timeStyle) {
|
||||
// validated by caller
|
||||
private LocalizedPrinterParser(FormatStyle dateStyle, FormatStyle timeStyle) {
|
||||
// params validated by caller
|
||||
this.dateStyle = dateStyle;
|
||||
this.timeStyle = timeStyle;
|
||||
this.requestedTemplate = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param requestedTemplate the requested template to use, not null
|
||||
*/
|
||||
private LocalizedPrinterParser(String requestedTemplate) {
|
||||
// param validated by caller
|
||||
this.dateStyle = null;
|
||||
this.timeStyle = null;
|
||||
this.requestedTemplate = requestedTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5006,7 +5134,8 @@ public final class DateTimeFormatterBuilder {
|
|||
/**
|
||||
* Gets the formatter to use.
|
||||
* <p>
|
||||
* The formatter will be the most appropriate to use for the date and time style in the locale.
|
||||
* The formatter will be the most appropriate to use for the date and time style, or
|
||||
* the requested template for the locale.
|
||||
* For example, some locales will use the month name while others will use the number.
|
||||
*
|
||||
* @param locale the locale to use, not null
|
||||
|
@ -5015,23 +5144,22 @@ public final class DateTimeFormatterBuilder {
|
|||
* @throws IllegalArgumentException if the formatter cannot be found
|
||||
*/
|
||||
private DateTimeFormatter formatter(Locale locale, Chronology chrono) {
|
||||
String key = chrono.getId() + '|' + locale.toString() + '|' + dateStyle + timeStyle;
|
||||
DateTimeFormatter formatter = FORMATTER_CACHE.get(key);
|
||||
if (formatter == null) {
|
||||
String pattern = getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale);
|
||||
formatter = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale);
|
||||
DateTimeFormatter old = FORMATTER_CACHE.putIfAbsent(key, formatter);
|
||||
if (old != null) {
|
||||
formatter = old;
|
||||
}
|
||||
}
|
||||
return formatter;
|
||||
String key = chrono.getId() + '|' + locale.toString() + '|' +
|
||||
(requestedTemplate != null ? requestedTemplate : Objects.toString(dateStyle) + timeStyle);
|
||||
|
||||
return FORMATTER_CACHE.computeIfAbsent(key, k ->
|
||||
new DateTimeFormatterBuilder()
|
||||
.appendPattern(requestedTemplate != null ?
|
||||
getLocalizedDateTimePattern(requestedTemplate, chrono, locale) :
|
||||
getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale))
|
||||
.toFormatter(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Localized(" + (dateStyle != null ? dateStyle : "") + "," +
|
||||
(timeStyle != null ? timeStyle : "") + ")";
|
||||
return "Localized(" + (requestedTemplate != null ? requestedTemplate :
|
||||
(dateStyle != null ? dateStyle : "") + "," +
|
||||
(timeStyle != null ? timeStyle : "")) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5056,7 +5184,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param minWidth the minimum field width, from 1 to 19
|
||||
* @param maxWidth the maximum field width, from minWidth to 19
|
||||
*/
|
||||
WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) {
|
||||
private WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) {
|
||||
this(chr, count, minWidth, maxWidth, 0);
|
||||
}
|
||||
|
||||
|
@ -5070,7 +5198,7 @@ public final class DateTimeFormatterBuilder {
|
|||
* @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater,
|
||||
* -1 if fixed width due to active adjacent parsing
|
||||
*/
|
||||
WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth,
|
||||
private WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth,
|
||||
int subsequentWidth) {
|
||||
super(null, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
|
||||
this.chr = chr;
|
||||
|
@ -5201,7 +5329,7 @@ public final class DateTimeFormatterBuilder {
|
|||
*
|
||||
* @param textStyle the text style, not null
|
||||
*/
|
||||
DayPeriodPrinterParser(TextStyle textStyle) {
|
||||
private DayPeriodPrinterParser(TextStyle textStyle) {
|
||||
// validated by caller
|
||||
this.textStyle = textStyle;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue