-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Formatting chrono durations and time_points #864
Comments
It doesn't, although we'd want the
Kind of.
No, it wouldn't.
The parser doesn't store the string itself, it just iterates over it and invokes parser actions as it goes.
That's inaccurate. The format string is guaranteed to exist throughout the parsing and formatting phases. |
From the description, and reading Howard's reference implementation, it seems like it would write an empty string. It's very much like
I was thinking specifically of the formatter for Line 113 in 802ff88
Okay, good. Thanks for the correction. Just to put my idea in concrete terms, this is what I think would be convenient: const std::chrono::nanoseconds ns(123456);
fmt::print("{}\n", ns);
// outputs
// 123456ns
// This is what happens if "we" do nothing, C++20 ships with the currently specified operator<<, and fmt/ostream.h is included.
fmt::print("{:n}\n", ns);
// outputs
// 123,456ns
const std::chrono::duration<double> floating_seconds(0.12345);
fmt::print("{:.3f}\n", floating_seconds);
// outputs
// 0.123s
const std::chrono::minutes mins(90);
fmt::print("{}\n", mins);
// outputs
// 90min
// again, this is what will "magically" happen
fmt::print("{:%H:%M}\n", mins);
// outputs
// 01:30
const std::chrono::minutes mins2 = std::chrono::hours(100) + std::chrono::minutes(16);
fmt::print("{:%H:%M}\n", mins2);
// I think this would output:
// 100:16
// but I haven't gotten that far in investigating to_stream's behavior in this instance.
// assuming C++20 ships, the following two lines would produce identical output.
std::cout << ns << '\n';
fmt::print("{}\n", ns);
What I presently have covers the first 4 examples as that was my immediate need, in addition to being a lot simpler to cover. The 5th seems convenient (and, indeed, I found one spot in my codebase that wants effectively this), but I didn't know if it was too odd to mix and match both styles, or if there should be a distinct type that would support the |
Yes, this is a horrible default. I think we should follow the Python's approach and pick something actually useful here because it's gonna be used often:
All your examples look very reasonable to me. PRs are welcome =). |
Sorry -- I thought I had something reasonable, but then realized I'm probably excluding too many platforms since I was relying on FMS_HAS_INCLUDE which isn't supported on all platforms that support chrono, but not every standard library that fmt supports has chrono. Minor thing, I just need to fix it up. And the implementation may not work with all output iterators. Also, for the tests, I cheated and based everything on https://github.com/HowardHinnant/date/blob/master/test/date_test/durations_output.pass.cpp. Is that okay to bring that copyright in, or should I work on a new set of tests? |
No worries, take your time. It's OK to bring tests from Howard's date repo, just make sure to keep their original license & copyright notice in the test source file(s). |
Sorry. Sorry. |
FWIW, I started experimenting with this (https://github.com/fmtlib/fmt/blob/master/include/fmt/time.h#L138) mostly to convince myself that chrono formatting is implementable using the current extension API for the forthcoming chrono-fmt ISO C++ paper. |
An experimental chrono duration formatter is now available at https://github.com/fmtlib/fmt/blob/master/include/fmt/chrono.h . It should be fully functional but not optimized. Improvements are welcome. |
I have a formatter for the
std::chrono::duration
template based on what's proposed for C++20's operator<<. The main differenceisoperator<<
is specified as usingstd::to_string
for the numeric part, right now I'm just using the default formatter for the representation type (for floating point types,to_string
behaves like %f, whilefmt
behaves like %g).However, I like much of what is available in to_stream. But there are some parts I'd probably not include, as I can't decide what an AM/PM designation or any of the other 12-hour clock-centric conversion specifiers mean for a duration. For instance, "my uptime is 01:03pm" seems nonsensical. I'd probably also want to add %f for subsecond values as suggested for time_points in #743.
operator<<
now constrain future changes?to_stream
. no: format as a number + unit suffix" is likely an adequate differentiator).to_stream
-like support limit compile time checks in the basic case?fmt::format(FMT_STRING("{:I have been running for %H hours and %M minutes}"), dur);
would be legal, so the formatter would need to support collecting an "unbounded" amount of characters inparse
, like thestd::tm
formatter, which seems limiting. Or canparse
merely store the locations of the beginning and ending of the format specifier instead? I have been assuming that the lifetime of the format string was possibly over by the timeformat
is called and that is why thetm
formatter collected the format string inparse
, but maybe that's inaccurate?The text was updated successfully, but these errors were encountered: