JDK-8243445 : Additional Date-Time Formats
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.time
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 19
  • Submitted: 2020-04-22
  • Updated: 2022-02-16
  • Resolved: 2022-02-16
Related Reports
CSR :  
Description
Summary
-------

Support additional custom locale date/time formats defined in CLDR.

Problem
-------

Currently `java.time.format.DateTimeFormatter` supports 4 pre-defined format styles, for example, `FormatStyle.FULL/LONG/MEDIUM/SHORT`. Users cannot use localized formats in a more flexible manner, such as a format that contains only year and month. For example, consider getting the title string for a typical month for a calendar user interface. Currently, the typical way is to assume an explicit pattern, such as `DateTimeFormatter.ofPattern("MMM y")` which is proven to be incorrect for some locales.

Solution
--------

Provide a method analogous to `java.time.format.DateTimeFormatter#ofPattern` that takes the template based on [Skeleton patterns defined in CLDR][1]. It returns the localized formatter based on passed skeletons. Also, add supporting methods in `java.time.format.DateTimeFormatterBuilder` class that are the basis for the method in `DateTimeFormatter`.

Specification
-------------

Add the following method to `java.time.format.DateTimeFormatter` class:


    /**
     * 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)

Add the following methods to `java.time.format.DateTimeFormatterBuilder` class:

    /**
     * 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)

    /**
     * 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)

  [1]: https://www.unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
Comments
Moving to Approved.
16-02-2022