Skip to content

Accept a space separator in NaiveDateTime::from_str - #1815

Closed
hdimer wants to merge 1 commit into
chronotope:mainfrom
hdimer:naivedatetime-display-roundtrip
Closed

Accept a space separator in NaiveDateTime::from_str#1815
hdimer wants to merge 1 commit into
chronotope:mainfrom
hdimer:naivedatetime-display-roundtrip

Conversation

@hdimer

@hdimer hdimer commented Aug 22, 2026

Copy link
Copy Markdown

Thanks for contributing to chrono!

Targeting main: this only widens the set of accepted inputs, so it is semver-compatible.


Fixes #1792.

NaiveDateTime's Display writes a space between the date and the time, but FromStr hard-coded Item::Literal("T"), so nothing round-trips:

let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(0, 0, 0).unwrap();
dt.to_string();                              // "2016-07-08 00:00:00"
dt.to_string().parse::<NaiveDateTime>();     // Err(ParseError(Invalid))

#378 fixed exactly this for DateTime<FixedOffset> back in 0.4.11 ("Support a space or T in FromStr for DateTime<Tz>, meaning that e.g. dt.to_string().parse::<DateTime<Utc>>() now correctly works on round-trip"). NaiveDateTime kept the old items array, XXX comment and all, so it was left behind.

This splits the items at the separator and accepts whitespace there as well as a T, following the structure NaiveTime::from_str already uses. Adds test_to_string_round_trip, mirroring the one in src/datetime/tests.rs.

Three things worth flagging, since they are judgement calls rather than mechanical consequences:

  • Two existing assertions flip. "2012-12-12 12:12:12" moves from the invalid list to the valid list in test_datetime_from_str, and the matching is_err() in the serde tests becomes a positive assertion. I added "2012-12-1212:12:12" (no separator at all) to the invalid list to keep that case covered, since Numeric(Day) is width-2 and would otherwise happily split 1212:12:12.
  • This reaches serde. Deserialize goes through FromStr, so NaiveDateTime now accepts the space form from JSON. That is what DateTime<Utc> and DateTime<FixedOffset> already do today as a consequence of support round tripping display <-> datetime #378, so it makes the naive type consistent rather than novel, but it is a wire-format change and you may feel differently about it.
  • It is whitespace, not just a space. trim_start() means a tab or newline works too, so "2016-07-08\n09:10:48" now parses. Every other slot in this same format already trims Unicode whitespace via Item::Space(""), so this is that existing policy applied to one more position, but it is looser than parse_rfc3339_relaxed, which matches a single byte. Happy to tighten it to an ASCII space if you would rather keep the two parsers aligned.

I deliberately did not make the T case-insensitive, so "2012-12-12t12:12:12" is still rejected here while DateTime<FixedOffset> accepts it. That is outside what #1792 asks for and the existing test pins it, so it seemed like your call to make. I left the // XXX shouldn't this be case-insensitive? comment in place.

cargo test (full CI feature set, plus the --no-default-features variants), cargo clippy --all-targets -D warnings and cargo fmt --check are all clean.

I used AI tooling while working on this, and I have reviewed and tested the change myself.


Used AI assistance on this; I reviewed and tested the change myself.

`NaiveDateTime`'s `Display` writes a space between the date and the time,
but `FromStr` hard-coded `Item::Literal("T")`, so no `NaiveDateTime` could
round-trip through `to_string()`/`parse()`.

Split the format items at the separator and accept whitespace as well as a
`T`, the same fix chronotope#378 made for `DateTime<FixedOffset>`.

Fixes chronotope#1792
@hdimer
hdimer marked this pull request as ready for review August 22, 2026 19:57
@djc

djc commented Aug 28, 2026

Copy link
Copy Markdown
Member

chrono is soft-deprecated and will not be accepting most kinds of changes:

@djc djc closed this Aug 28, 2026
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.

Roundtrip to_string and from_str fails for NaiveDateTime

2 participants