Skip to content

<chrono>: format() should accept %X and %EX for duration and hh_mm_ss #4247

@StephanTLavavej

Description

@StephanTLavavej

Found by the upcoming libc++ test update. Accepted by libc++ and libstdc++: https://godbolt.org/z/oWGKosE3d

D:\GitHub\STL\out\x64>type meow.cpp
#include <cassert>
#include <chrono>
#include <format>
#include <string>
using namespace std;

int main() {
    // N4964 [time.format]/6: "However, if a flag refers to a "time of day" (e.g., `%H`, `%I`, `%p`, etc.),
    // then a specialization of `duration` is interpreted as the time of day elapsed since midnight."
    // [tab:time.format.spec]: "`%X` The locale's time representation.
    // The modified command `%EX` produces the locale's alternate time representation."

    // libcxx/test/std/time/time.syn/formatter.duration.pass.cpp
    assert(format("{:%X}", 0s) == "00:00:00");
    assert(format("{:%EX}", 0s) == "00:00:00");

    // libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp
    // libcxx/test/std/time/time.syn/formatter.hh_mm_ss.pass.cpp
    // libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp
    // libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp
    assert(format("{:%X}", chrono::hh_mm_ss{0s}) == "00:00:00");
    assert(format("{:%EX}", chrono::hh_mm_ss{0s}) == "00:00:00");
}
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /std:c++latest /MTd /Od meow.cpp && meow
meow.cpp
meow.cpp(14): error C7595: 'std::basic_format_string<char,std::chrono::duration<__int64,std::ratio<1,1>>>::basic_format_string': call to immediate function is not a constant expression
D:\GitHub\STL\out\x64\out\inc\chrono(5321): note: failure was caused by call of undefined function or one not declared 'constexpr'
D:\GitHub\STL\out\x64\out\inc\chrono(5321): note: see usage of 'std::_Throw_format_error'
[...]

D:\GitHub\STL\out\x64>clang-cl /EHsc /nologo /W4 /std:c++latest /MTd /Od meow.cpp && meow
meow.cpp(14,19): error: call to consteval function 'std::basic_format_string<char, std::chrono::duration<long
      long>>::basic_format_string<char[6]>' is not a constant expression
    assert(format("{:%X}", 0s) == "00:00:00");
                  ^
D:\GitHub\STL\out\x64\out\inc\chrono(5321,21): note: non-constexpr function '_Throw_format_error' cannot be used in a
      constant expression
                    _Throw_format_error("Invalid type.");
                    ^
[...]

For duration, we accept a superset of what hh_mm_ss<seconds> accepts:

STL/stl/inc/chrono

Lines 5378 to 5379 in 0403d19

if constexpr (_Is_specialization_v<_Ty, duration>) {
return _Type == 'j' || _Type == 'q' || _Type == 'Q' || _Is_valid_type<hh_mm_ss<seconds>>(_Type);

But hh_mm_ss doesn't accept 'X':

STL/stl/inc/chrono

Lines 5399 to 5401 in 0403d19

} else if constexpr (_Is_specialization_v<_Ty, hh_mm_ss>) {
return _Type == 'H' || _Type == 'I' || _Type == 'M' || _Type == 'S' || _Type == 'r' || _Type == 'R'
|| _Type == 'T' || _Type == 'p';

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingchronoC++20 chronofixedSomething works now, yay!formatC++20/23 format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions