Skip to content

LWG-3536 Should chrono::from_stream assign zero to duration for failure? #1740

@StephanTLavavej

Description

@StephanTLavavej

Noticed by @MattStephanson and investigated by @mnatsuhara.

WG21-N4878 [time.duration.io]/3:

template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>>
  basic_istream<charT, traits>&
    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
                duration<Rep, Period>& d,
                basic_string<charT, traits, Alloc>* abbrev = nullptr,
                minutes* offset = nullptr);

Effects: Attempts to parse the input stream is into the duration d using the format flags given in the NTCTS fmt as specified in [time.parse]. If the parse parses everything specified by the parsing format flags without error, and yet none of the flags impacts a duration, d will be assigned a zero value. If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null. If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.

[time.parse]/11:

If the type being parsed cannot represent the information that the format flag refers to, is.setstate(ios_base::failbit) is called.
[Example 1: A duration cannot represent a weekday. -- end example]
However, if a flag refers to a "time of day" (e.g. %H, %I, %p, etc.), then a specialization of duration is parsed as the time of day elapsed since midnight.

[time.parse]/12:

If the from_stream overload fails to parse everything specified by the format string, or if insufficient information is parsed to specify a complete duration, time point, or calendrical data structure, setstate(ios_base::failbit) is called on the basic_istream.

What happens for the duration overload of from_stream()? My interpretation of the Standardese:

Format Stream Result Rationale
"%j" "10" Success, days{10}
"%j" "meow" failbit, unknown
"%a" "Saturday" failbit, duration::zero() [time.parse]/11 "cannot represent", [time.duration.io]/3 "none of the flags impacts a duration"
"%a" "Caturday" failbit, unknown
"literal" "literal" failbit, duration::zero() [time.parse]/12 "insufficient information", [time.duration.io]/3 "none of the flags impacts a duration"
"literal" "meow" failbit, unknown

When the parse simply fails, should the duration be set to zero, or should it be unchanged? Nothing seems to address this specific case.

On one hand, it seems that there's no Standardese telling us to assign zero, so we shouldn't. On the other hand, it seems very strange for "%a" parsing "Saturday" to set failbit and assign zero, while "%a" parsing "Caturday" sets failbit and leaves the duration unchanged.

The other from_stream() overloads all clearly address this, e.g. [time.cal.wd.nonmembers]/7 "If the parse fails to decode a valid weekday, is.setstate(ios_base::failbit) is called and wd is not modified."

Metadata

Metadata

Assignees

No one assigned

    Labels

    LWGLibrary Working Group issuechronoC++20 chronofixedSomething works now, yay!

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions