Copilot commented on code in PR #1815:
URL: https://github.com/apache/commons-lang/pull/1815#discussion_r4264631887
##########
src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java:
##########
@@ -210,6 +214,36 @@ void testEraNonGregorianCalendar() {
}
}
+ /**
+ * Tests that a month-only pattern uses the standalone month names, like
SimpleDateFormat. In some languages, like the Slavic and Baltic ones, they are a
+ * different grammatical form from the names used next to a day: "MMMM"
alone prints Russian February as nominative "февраль" where "d MMMM" prints
+ * genitive "февраля".
+ */
+ @Test
+ void testStandaloneMonthForMonthOnlyPattern() throws ParseException {
+ // SimpleDateFormat forces the standalone form for a month-only
pattern only since Java 9 (JDK-8114833); Java 8 has no such rule.
+ assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9));
+ final Locale[] locales = { Locale.US, Locale.GERMANY, new
Locale("ru"), new Locale("cs"), new Locale("pl"), new Locale("fi") };
+ // Month-only patterns, with or without literals, use the standalone
form; patterns with another field keep the format form.
+ final String[] patterns = { "MMM", "MMMM", "'m:'MMMM", "MMMM''", "d
MMMM", "MMMM yyyy", "MMM MMM" };
+ for (final Locale locale : locales) {
+ for (final String pattern : patterns) {
+ for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER;
month++) {
+ final Calendar cal = Calendar.getInstance(TimeZones.GMT,
locale);
+ cal.clear();
+ cal.set(2024, month, 10);
+ final Date date = cal.getTime();
+ final SimpleDateFormat sdf = new SimpleDateFormat(pattern,
locale);
+ sdf.setTimeZone(TimeZones.GMT);
+ final FastDateFormat fdf =
FastDateFormat.getInstance(pattern, TimeZones.GMT, locale);
+ assertEquals(sdf.format(date), fdf.format(date), () ->
locale + " " + pattern);
+ // FastDateParser accepts all name styles, so the
printer's output parses back.
+ assertEquals(month,
DateUtils.toCalendar(fdf.parse(fdf.format(date))).get(Calendar.MONTH), () ->
locale + " " + pattern);
Review Comment:
`DateUtils.toCalendar(Date)` uses the system default time zone, but
`fdf.parse(...)` is run in `TimeZones.GMT`. This can make the assertion
timezone-dependent (and potentially flaky near month boundaries, since parsing
month-only patterns commonly defaults the day-of-month). Prefer constructing
the `Calendar` in GMT (e.g., `DateUtils.toCalendar(parsedDate, TimeZones.GMT)`
or `Calendar.getInstance(TimeZones.GMT, locale)` + `setTime(...)`) before
reading `Calendar.MONTH`.
##########
src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java:
##########
@@ -1462,6 +1467,7 @@ protected List<Rule> parsePattern() {
final int length = pattern.length();
final int[] indexRef = new int[1];
+ final boolean monthOnly = STANDALONE_MONTH_PATTERN &&
isMonthOnlyPattern();
Review Comment:
When `monthOnly` is true, `CalendarUtils.getInstance(locale)` is invoked
separately for the long and short month lookups. Even though `parsePattern()`
is typically called only during formatter construction, this is easy to
streamline by retrieving the `CalendarUtils` instance once (and optionally the
standalone arrays) into locals before the loop/case, reducing repeated lookups
and keeping the rule construction simpler.
##########
src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java:
##########
@@ -1493,9 +1499,9 @@ protected List<Rule> parsePattern() {
break;
case 'M': // month in year (text and number)
if (tokenLen >= 4) {
- rule = new TextField(Calendar.MONTH, months);
+ rule = new TextField(Calendar.MONTH, monthOnly ?
CalendarUtils.getInstance(locale).getStandaloneLongMonthNames() : months);
} else if (tokenLen == 3) {
- rule = new TextField(Calendar.MONTH, shortMonths);
+ rule = new TextField(Calendar.MONTH, monthOnly ?
CalendarUtils.getInstance(locale).getStandaloneShortMonthNames() : shortMonths);
Review Comment:
When `monthOnly` is true, `CalendarUtils.getInstance(locale)` is invoked
separately for the long and short month lookups. Even though `parsePattern()`
is typically called only during formatter construction, this is easy to
streamline by retrieving the `CalendarUtils` instance once (and optionally the
standalone arrays) into locals before the loop/case, reducing repeated lookups
and keeping the rule construction simpler.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]