Skip to content

Fix negative week year formatting in FastDatePrinter - #1762

Merged
garydgregory merged 1 commit into
apache:masterfrom
alhudz:fastdateprinter-weekyear-sign
Jul 30, 2026
Merged

Fix negative week year formatting in FastDatePrinter#1762
garydgregory merged 1 commit into
apache:masterfrom
alhudz:fastdateprinter-weekyear-sign

Conversation

@alhudz

@alhudz alhudz commented Jul 30, 2026

Copy link
Copy Markdown
Contributor
  • Read the contribution guidelines for this project.
  • Read the ASF Generative Tooling Guidance if you use Artificial Intelligence (AI).
  • I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute?
  • Run a successful build using the default Maven goal with mvn; that's mvn on the command line by itself.
  • Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process.

Repro: FastDateFormat.getInstance("YYYY").format(cal) where cal is 15 July 42 BC, that is a GregorianCalendar with ERA set to GregorianCalendar.BC.
Expected: -0041, what SimpleDateFormat prints for the same date and pattern.
Actual: 000 followed by U+0007. YY gives ,/ against SimpleDateFormat's -41.

  1. GregorianCalendar.getWeekYear() is proleptic, so a BC date gives a negative week year (-41 here) and WeekYear hands it to the wrapped NumberRule unchanged.
  2. The digit rules build each character arithmetically ((char) (value + '0'), value / 10 + '0'), so a negative value walks below '0' and lands on control characters or unrelated code points rather than digits.

Fix: emit the sign in WeekYear and pass the magnitude down, the same handling TimeZoneNumberRule and Iso8601_Rule already apply to negative UTC offsets. Every other rule takes its value from Calendar.get, which never returns a negative, so getWeekYear is the only source of one; YYY and Y keep the four-digit padding the class Javadoc describes.

Checked YYYY against SimpleDateFormat over 46,667 dates spanning 249 BC to 4188 AD: 2,611 mismatches before this change, 337 of them carrying a control character, and 0 after.

GregorianCalendar.getWeekYear() is proleptic, so a BC date yields a negative week year that WeekYear passed straight to the digit rules. Those rules build characters arithmetically, so the value walked below '0' and emitted control characters instead of digits. Emit the sign in WeekYear and pass the magnitude down, matching TimeZoneNumberRule.
@garydgregory garydgregory changed the title fix negative week year formatting in FastDatePrinter Fix negative week year formatting in FastDatePrinter Jul 30, 2026
@garydgregory
garydgregory requested a review from Copilot July 30, 2026 10:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes incorrect formatting of negative week-based years in FastDatePrinter when using Y/YY/YYYY… patterns with BC dates (where GregorianCalendar.getWeekYear() can return a negative, proleptic value). The change brings FastDateFormat/FastDatePrinter output in line with SimpleDateFormat and prevents control-character output from the digit rules.

Changes:

  • Add sign handling to the WeekYear rule so negative week years are rendered with - and the magnitude is passed to the underlying NumberRule.
  • Add a regression test that compares multiple Y-width patterns against SimpleDateFormat for a BC date and asserts exact expected strings.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java WeekYear now emits - and formats the absolute value to avoid negative-digit rendering.
src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java Adds BC week-year regression coverage and parity assertions vs SimpleDateFormat.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@garydgregory
garydgregory merged commit 0add789 into apache:master Jul 30, 2026
23 of 24 checks passed
@garydgregory

Copy link
Copy Markdown
Member

Thank you @alhudz , merged 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants