Skip to content

fmt/strtime: some tweaks to %y and %s handling#432

Merged
BurntSushi merged 3 commits intomasterfrom
ag/strftime-tweaks
Oct 17, 2025
Merged

fmt/strtime: some tweaks to %y and %s handling#432
BurntSushi merged 3 commits intomasterfrom
ag/strftime-tweaks

Conversation

@BurntSushi
Copy link
Copy Markdown
Owner

This PR bundles together three related changes:

  • Formatting %y no longer errors when its year value is outside the
    range supported by parsing %y. This brings it more into line with
    GNU's strftime behavior and also removes the singular reason for
    Jiff's strftime formatting to fail based on the specific data values.
  • Lenient formatting is now more lenient: it won't return an error
    when the formatting string is invalid UTF-8. Instead, it will silently
    automatically lossily decode it. Lenient formatting will now only ever
    return an error when writing to the provided writer fails.
  • A BrokenDownTime's explicitly set timestamp field is now used in
    a way that is consistent with other data. It's a bit weird because it
    isn't in conflict with any one other field, but rather, to an aggregate
    of other fields (a civil datetime + offset/time zone). Previously, we
    would let %s and, say, %F %z override one another. Now they are
    separate and the higher level constructors (to_timestamp, to_zoned)
    now prefer an explicitly set timestamp when present.

Fixes #428

Previously, it was possible for lenient formatting to still error when
the formatting string contained invalid UTF-8. This commit alleviates
that error condition by writing a replacement character instead. This
required tweaking our UTF-8 decoding routines so that we could implement
the "substitution by maximal subparts" strategy for lossy decoding.

This now means that lenient formatting can only fail when writing to the
underlying writer fails.
Previously, these would fail if the year wasn't in the range
`1969-2068`. This was done because parsing fails for the same reason,
and it seemed like good sense to have parsing and formatting be
consistent with one another.

... however, this is the *only* formatting specifier that can yield an
error based on the specific values provided. In contrast, all other
errors are tied to either the validity of the formatting string or if
all relevant data is provided (i.e., you get an error if you use `%y`
and your `BrokenDownTime` doesn't have a way to get the year).

I don't think this aberration is worth it. I think it's better to be
able to say the two broad error categories and be able to stick to them.
This should also hopefully avoid accidental panics, since now the only
error conditions that result in, say, `Zoned::strftime` panicking are
limited to the format string itself.

Fixes #428
…re consistent

Specifically, all of the other higher level constructors on
`BrokenDownTime` already try their "hardest" to produce the
requested value. Notably, both `BrokenDownTime::to_date` and
`BrokenDownTime::to_time` go to some effort to achieve this.

However, `BrokenDownTime::to_timestamp` wasn't doing everything it
could. Namely, it was completely ignoring its internal `timestamp`
field. This is weird and inconsistent from how the rest of the
constructors worked.

I think this is overall more flexible as well. Because it means that
parsing `%s` is, at the level of the individual pieces of data inside a
`BrokenDownTime`, completely separate from everything else. So you don't
have any weird overwriting behavior at the lowest levels.

I started thinking about this in #428. While I don't think the
motivation in #428 is that compelling, it got me thinking more deeply
about how a `BrokenDownTime` deals with timestamps. I think we got to
this state because I bolted `%s` on to `fmt::strtime` and didn't think
deeply about it.

Fixes #428
@BurntSushi BurntSushi merged commit fdf6ab2 into master Oct 17, 2025
39 checks passed
@BurntSushi BurntSushi deleted the ag/strftime-tweaks branch October 17, 2025 18:54
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.

BrokenDownTime and Formatter arbitrary rules (%y, %D and %s have undocumented limitations)

1 participant