-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8176706: Additional Date-Time Formats #7340
Conversation
…ly thrown on format()
👋 Welcome back naoto! A progress list of the required criteria for merging this PR into |
Webrevs
|
@@ -5015,10 +5148,16 @@ public int parse(DateTimeParseContext context, CharSequence text, int position) | |||
* @throws IllegalArgumentException if the formatter cannot be found | |||
*/ | |||
private DateTimeFormatter formatter(Locale locale, Chronology chrono) { | |||
String key = chrono.getId() + '|' + locale.toString() + '|' + dateStyle + timeStyle; | |||
var dtStyle = dateStyle !=null || timeStyle != null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch to using requestedTemplate == null or != null as the discriminator.
validateTemplate(); | ||
} | ||
|
||
private LocalizedPrinterParser(FormatStyle dateStyle, FormatStyle timeStyle, String requestedTemplate) { | ||
this.dateStyle = dateStyle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop this constructor; it opens up the possibility of ambiguity between the modes.
Keep only the two constructors with disjoint checking and initialization.
String pattern = (dtStyle ? | ||
getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale) : | ||
getLocalizedDateTimePattern(requestedTemplate, chrono, locale)); | ||
|
||
formatter = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale); | ||
DateTimeFormatter old = FORMATTER_CACHE.putIfAbsent(key, formatter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.computeIfAbsent(key, () -> {....}) might be a bit cleaner/clearer here and avoid the race a few lines of code below. (a slight improvement in old code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Changed to computeIfAbsent()
.
// validity check | ||
var matcher = VALID_SKELETON_PATTERN.matcher(skeleton); | ||
if (!matcher.matches()) { | ||
throw new IllegalArgumentException("Requested template is invalid: " + requestedTemplate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The substitutions are not going to be visible in the exception message.
That might make it harder to identify and fix the cause of the exception. Perhaps the message can make it clear that the matching was done after substitutions and show the 'skeleton'.
*/ | ||
public static String getLocalizedDateTimePattern(String requestedTemplate, | ||
Chronology chrono, Locale locale) { | ||
Objects.requireNonNull(locale, "requestedTemplate"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, "locale" should have been requestedTemplate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
public String getJavaTimeDateTimePattern(String requestedTemplate, String calType, Locale locale) { | ||
LocaleProviderAdapter lpa = LocaleProviderAdapter.getResourceBundleBased(); | ||
// CLDR's 'u'/'U' are not supported in the JDK. Replace them with 'y' instead | ||
final var modifiedSkeleton = requestedTemplate.replaceAll("[uU]", "y"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to me requestedTemplate needs to be validated when it gets passed to getLocalizedDateTimePattern, similar as to appendLocalized
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a left over which should be removed. In fact, CLDR specific pattern symbols should not be accepted as the requested template. Removed the substitutions. As to the validation, it will be performed in the following LocaleResources.getLocalizedPattern()
method.
@@ -104,6 +108,10 @@ | |||
"narrow.Eras" | |||
}; | |||
|
|||
// DateFormatItem prefix | |||
final static String DATEFORMATITEM_KEY_PREFIX = "DateFormatItem."; | |||
final static String DATEFORMATITEM_INPUT_REGIONS_PREFIX = "DateFormatItemInputRegions."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The canonical order of modifiers is "static final".
* } | ||
* All pattern symbols are optional, and each pattern symbol represents the field it is in, | ||
* e.g., '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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would reword as:
* 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
* {@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 will use the {@link Locale#getDefault() default FORMAT locale}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Editorial suggestion:
- this method uses the {https://github.com/link Locale#getDefault() default FORMAT locale}.
@@ -227,6 +227,41 @@ public static String getLocalizedDateTimePattern(FormatStyle dateStyle, FormatSt | |||
CalendarDataUtility.findRegionOverride(locale)); | |||
} | |||
|
|||
/** | |||
* Gets the formatting pattern for the requested template for a locale and chronology. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Returns" is more conventional (than "Gets; though it is consistent within the file)
* @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} is invalid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The meaning "Invalid" should be clearly defined; repeating or refering to the template regex.
* <ul> | ||
* <li>the {@code requestedTemplate} specified to this method | ||
* <li>the {@code Locale} of the {@code DateTimeFormatter} | ||
* <li>the {@code Chronology}, selecting the best available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps "best available" should be well defined, or just drop "best".
or ...
"of the {@code DateTimeFormatter} unless overridden"
* "[vz]{0,4}" // Zone | ||
* } | ||
* All pattern symbols are optional, and each pattern symbol represents the field it is in, | ||
* e.g., 'M' represents the Month field. The number of the pattern symbol letters follows the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto above:
* All pattern symbols are optional, and each pattern symbol represents the field,
* for example, 'M' represents the Month field. The number of the pattern symbol letters follows the
return formatter; | ||
var useRequestedTemplate = requestedTemplate != null; | ||
String key = chrono.getId() + '|' + locale.toString() + '|' + | ||
(useRequestedTemplate ? requestedTemplate : Objects.toString(dateStyle) + timeStyle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The boolean useRequestedTemplate
isn't necessary, replace with requestedTemplate != null
.
@@ -58,4 +59,23 @@ protected JavaTimeDateTimePatternProvider() { | |||
* @since 9 | |||
*/ | |||
public abstract String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale); | |||
|
|||
/** | |||
* Gets the formatting pattern for the requested template, calendarType, and locale. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Returns" is more conventional.
@@ -63,10 +66,22 @@ public boolean isSupportedLocale(Locale locale) { | |||
@Override | |||
public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) { | |||
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale); | |||
String pattern = lr.getJavaTimeDateTimePattern( | |||
return lr.getJavaTimeDateTimePattern( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fold the parameters onto a single line.
*/ | ||
private String resolveInputSkeleton(String type) { | ||
var regionToSkeletonMap = inputSkeletons.get(type); | ||
return regionToSkeletonMap.getOrDefault(locale.getLanguage() + "-" + locale.getCountry(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This structure computes all the defaults even if the value isn't needed (because the value has to be passed to the getOrDefault
method. Perhaps performance isn't an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, yes. I thought this was simple enough, and as you said, not performance-critical.
/label -build |
@magicus |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
@@ -4986,9 +5101,22 @@ private String getChronologyName(Chronology chrono, Locale locale) { | |||
* @param timeStyle the time style to use, may be null | |||
*/ | |||
LocalizedPrinterParser(FormatStyle dateStyle, FormatStyle timeStyle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the constructors be private
.
The combination of package protected and the style of caller doing the validation makes me a bit nervous.
There should not be any callers outside of DateTimeFormatterBuilder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to private
so that it can only be instantiated within DateTimeFormatterBuilder
. Same modifications are applied to other DateTimePrinterParser
implementations.
/** | ||
* Returns the formatting pattern for the requested template, calendarType, and locale. | ||
* Concrete implementation of this method will retrieve | ||
* a java.time specific pattern from selected Locale Provider. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
editorial: "from the selected Locale"...
*/ | ||
public String getJavaTimeDateTimePattern(String requestedTemplate, String calType, Locale locale) { | ||
// default implementation throws exception | ||
throw new DateTimeException("Formatter is not available for the requested template: " + requestedTemplate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Formatting pattern is not available"...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modified, as well as other minor corrections in the javadoc.
@naotoj This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 123 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
/integrate |
Going to push as commit 9b74c3f.
Your commit was automatically rebased without conflicts. |
Following the prior discussion [1], here is the PR for the subject enhancement. CSR has also been updated according to the suggestion.
[1] https://mail.openjdk.java.net/pipermail/core-libs-dev/2022-January/085175.html
Progress
Issues
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/7340/head:pull/7340
$ git checkout pull/7340
Update a local copy of the PR:
$ git checkout pull/7340
$ git pull https://git.openjdk.java.net/jdk pull/7340/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 7340
View PR using the GUI difftool:
$ git pr show -t 7340
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/7340.diff