Skip to content

date: support GNU-compatible out-of-range years and formatting parity#10931

Closed
abhishekpradhan wants to merge 10 commits intouutils:mainfrom
abhishekpradhan:codex/large-year-date-parity
Closed

date: support GNU-compatible out-of-range years and formatting parity#10931
abhishekpradhan wants to merge 10 commits intouutils:mainfrom
abhishekpradhan:codex/large-year-date-parity

Conversation

@abhishekpradhan
Copy link
Copy Markdown

@abhishekpradhan abhishekpradhan commented Feb 14, 2026

Summary

This addresses #9774: date -d rejects GNU-valid out-of-range years (for example 18978-01-01) because the normal parser/runtime path stops at the in-range datetime boundary.

  • accept parse_datetime::ParsedDateTime::{InRange, Extended} in the date -d flow
  • add an extended-year formatting path for out-of-range years with GNU-compatible output behavior
  • preserve timezone conversion for extended dates, including -u, local TZ output, explicit input offsets, and far-future IANA rule lookups
  • support timezone abbreviations on extended dates, including preserved non--u output and -u conversion for both fixed-offset and mapped IANA cases
  • support additional format specifiers on extended dates, including %Q, %q, %r, %c, %U, %W, %V, %G, and %g
  • for format behavior that already differs from GNU in current uutils date (notably %Q and E/O modifiers), preserve current uutils behavior rather than expanding scope in this PR
  • handle extended parse results in touch -d without panic
  • add regression tests for large-year output, DST-aware IANA rules, formatter parity, timezone abbreviations, and touch -d

Dependency

  • temporarily pin parse_datetime to the upstream 0.15.0 git tag
  • update deny.toml and fuzz/Cargo.lock to keep CI green with the temporary git dependency
  • this should switch back to the crates.io release once parse_datetime 0.15.0 is published there

Related issues

Reviewer guide

  • src/uu/date/src/date.rs: parse branching, extended formatting, timezone/output conversion
  • src/uu/touch/src/touch.rs: extended touch -d path
  • tests/by-util/test_date.rs and tests/by-util/test_touch.rs: regression coverage

Testing

  • cargo fmt --all -- --check
  • cargo check -p uu_date -p uu_touch
  • cargo test -p uu_date --lib -q
  • cargo test -p uu_touch --lib -q
  • cargo clippy -p uu_date --all-features --all-targets -- -D warnings
  • cd fuzz && cargo fetch --locked
  • cargo test -q --test tests test_date::test_large_year_with_explicit_offset_converts_to_output_timezone -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_supports_r_and_c_formats -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_iana_timezone_rule_uses_dst_in_far_future -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_week_format_specifiers -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_supports_existing_q_format_in_local_timezone -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_preserves_existing_eo_literal_behavior -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_timezone_abbreviations -- --nocapture
  • cargo test -q --test tests test_date::test_large_year_timezone_abbreviations_match_in_range_behavior -- --nocapture
  • cargo test -q --test tests test_touch::test_touch_large_year_date_does_not_panic -- --nocapture

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 14, 2026

Merging this PR will not alter performance

✅ 305 untouched benchmarks
⏩ 46 skipped benchmarks1


Comparing abhishekpradhan:codex/large-year-date-parity (435d316) with main (e510449)

Open in CodSpeed

Footnotes

  1. 46 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@sylvestre
Copy link
Copy Markdown
Contributor

some conflicts

@abhishekpradhan abhishekpradhan force-pushed the codex/large-year-date-parity branch from 4d2eee6 to f33e4bb Compare March 31, 2026 17:39
@abhishekpradhan abhishekpradhan marked this pull request as ready for review March 31, 2026 17:40
@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/printf/printf-surprise is now being skipped but was previously passing.

@abhishekpradhan
Copy link
Copy Markdown
Author

abhishekpradhan commented Mar 31, 2026

This branch is now rebased onto current main, and the parse_datetime dependency now points to the large-year support from uutils/parse_datetime#263.

I also fixed the remaining extended-format regressions for large years:

  • support for %Q, matching current uutils date behavior
  • preserve E/O-modified format sequences literally, instead of reinterpreting them
  • locale-aware month/day names
  • timezone abbreviations on large years, including preserved non--u output and -u conversion

Local fmt, check, clippy, uu_date, and uu_touch tests are clean. This is still pinned to the parse_datetime 0.15.0 git tag for now, since that version has been tagged upstream but has not been published on crates.io yet.

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cut/cut-huge-range is now passing!
Congrats! The gnu test tests/unexpand/bounded-memory is now passing!

@abhishekpradhan
Copy link
Copy Markdown
Author

This is now pinned to the upstream 0.15.0 git tag rather than the previous commit SHA. I’ll switch it over to the crates.io release once parse_datetime 0.15.0 is published there.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

GNU testsuite comparison:

Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/tty/tty-eof (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/cut/bounded-memory is now being skipped but was previously passing.
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

GNU testsuite comparison:

Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@sylvestre
Copy link
Copy Markdown
Contributor

This is too large to be reviewed
please split it into several PR:

  • bump parse_datetime
  • one to support large date in date
  • formatting parity
  • touch work
    etc

Having a quick look here, it isn't ready - too much duplication (Extended vs ExtendedInZone branches), some various issues, etc

Given it seems that you use codex, you should prompt it to do better work in term of modification sizes, code duplication, etc

thanks

@sylvestre sylvestre closed this Apr 2, 2026
@abhishekpradhan
Copy link
Copy Markdown
Author

Of course, thanks for the feedback here. I’ll split into several PR’s and work on the quality here.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/tail/symlink (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/tail/retry is no longer failing!

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.

2 participants