chrono icon indicating copy to clipboard operation
chrono copied to clipboard

Various fixes for formatting dates with a year outside of 0..=9999

Open pitdicker opened this issue 2 years ago • 3 comments
trafficstars

We have a couple of problems when formatting dates with a year outside of 0..=9999.

RFC 2822

Formatting in DateTime::to_rfc2822 panicked with "writing rfc2822 datetime to string should never fail".

  • The panic message is now "date outside of defined range for rfc2822".
  • I added a new method DateTime::try_to_rfc2822 that can return None when formatting fails.
  • DateTime::to_rfc2822 is deprecated with the notice: "Can panic on years outside of the range 0..=9999. Use try_to_rfc2822() instead."

Formatting with the RFC2822 formatting item could return a panic in the Display method of DelayedFormat.

  • The formatting item can be localized, making it already not fully correct according to RFC 2822. But it is convenient, and we have a dedicated method, so I kept it that way.
  • Formatting is extended to support years outside the range defined in RFC 2822 to prevent an error. It is now up to the calling function to ensure the date is in range.

RFC 3339 and ISO 8601

RFC 3339 is not defined for dates with a year outside of 0..=9999. ISO 8601 does support it.

DateTime::to_rfc3339 was a hybrid method, claiming to format a datetime as both valid RFC 3339 and ISO 8601. It would write invalid RFC 3339 strings if the year is out of range, which could not be parsed by DateTime::parse_from_rfc3339.

  • to_rfc3339 now panics on out-of-range dates with "date outside of defined range for rfc3339", just like to_rfc2822.
  • A new try_to_rfc3339 can return None when formatting fails.
  • A new method to_iso8601 functions exactly as to_rfc3339 did, because dates that are out of range for RFC 3339 are still valid ISO 8601.
  • to_rfc3339 is deprecated with the notice: "Can panic on years outside of the range 0..=9999. Use try_to_rfc3339() or to_iso8601 instead.". This way when users update chrono to a new version a panic is not silently introduced.

Other RFC 3339 formatting methods:

  • DateTime::to_rfc3339_opts is redefined to format to an ISO 8601 representation when the year is out of range.
  • The RFC3339 formatting item is also redefined to format to an ISO 8601 representation when the year is out of range (for the same reasons as the RFC2822 formatting item: to not panic inside the Display implementation of DelayedFormat).
  • This is the formatting item for "%+".

ISO 8601 and usually valid RFC 3339 is also the Debug output of DateTime.

We have no parser that can read these out-of-range dates, which is what https://github.com/chronotope/chrono/pull/1143 is for.

Year formatting items

I have updated the documentation of the formatting items YearDiv100, YearMod100, IsoYearDiv100 and IsoYearMod100. The implementation supports formatting dates outside the 0..=9999 range, which is now reflected in the documentation.

pitdicker avatar Jun 10 '23 11:06 pitdicker

I strongly recommend some tests to confirm the panic. It's an important behavior presumption to verify as it has a large affect on the important parts of chrono. e.g.

Thank you for even writing out some test cases.

pitdicker avatar Jul 24 '23 07:07 pitdicker

Codecov Report

Merging #1144 (4bc5075) into 0.4.x (604b92a) will increase coverage by 0.01%. The diff coverage is 97.00%.

@@            Coverage Diff             @@
##            0.4.x    #1144      +/-   ##
==========================================
+ Coverage   91.50%   91.52%   +0.01%     
==========================================
  Files          38       38              
  Lines       17314    17371      +57     
==========================================
+ Hits        15844    15898      +54     
- Misses       1470     1473       +3     
Files Coverage Δ
src/datetime/tests.rs 96.84% <100.00%> (+0.04%) :arrow_up:
src/format/mod.rs 85.04% <ø> (ø)
src/lib.rs 95.62% <100.00%> (+0.03%) :arrow_up:
src/offset/fixed.rs 82.35% <100.00%> (ø)
src/format/formatting.rs 92.43% <80.00%> (-0.04%) :arrow_down:
src/datetime/mod.rs 89.44% <95.23%> (+0.14%) :arrow_up:

:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more

codecov[bot] avatar Aug 12 '23 05:08 codecov[bot]

@jtmoon79 Sorry it took so long, thank you for the review!

pitdicker avatar Sep 02 '23 06:09 pitdicker