diff --git a/chrono_io.html b/chrono_io.html index 5485352..ff3fd94 100644 --- a/chrono_io.html +++ b/chrono_io.html @@ -26,311 +26,15 @@

Howard E. Hinnant
-2016-07-30
+2017-04-13

chrono_io

-

Contents

- - - -

Introduction

-

-This is a small library which does nothing but add non-configurable, non-localizable -streaming to std::chrono::duration. The streaming operator lives in -namespace date for convenience purposes, and does not live in -namespace std::chrono as that would violate the standard. +This library has been moved to +"date.h".

-

-The entire API of this library is: -

- -
-namespace date
-{
-
-template <class CharT, class Traits, class Rep, class Period>
-std::basic_ostream<CharT, Traits>&
-operator<<(std::basic_ostream<CharT, Traits>& os,
-           const std::chrono::duration<Rep, Period>& d);
-
-}  // namespace date
-
- -

-Just one signature for an entire library? Are you serious?! -

- -
-

-Very serious. -

-

-Parsing is not included because there are a million ways to parse durations, and none -of them are universally agreed upon. And they are all easily implementable without -private access to std::chrono::duration just by parsing arithmetic types -and strings. -

-
- -

-No formatting options?! -

- -
-

-No. -

-

-The formatting provided here is based on an international SI standard. There is -no need for localization. If you need other formatting options for streaming -your durations that is easy enough for you to supply. What is needed here is -zero-effort streaming of chrono::durations without hassle. -Streaming chrono::durations is the biggest use of -.count() (a dangerous type cast), and that use should be handled by -a library such as this. -

-
- -

Examples

- -
-#include "chrono_io.h"
-#include <iostream>
-
-void f();
-
-int
-main()
-{
-    using namespace date;
-    using namespace std::chrono;
-    auto t0 = steady_clock::now();
-    f();
-    auto t1 = steady_clock::now();
-    std::cout << t1 - t0 << '\n';
-}
-
- -

-With this library, you don't have to specify the duration type (and cast to it) in timing -situations like this. This will create whatever duration is native to -steady_clock and print out the value and units for that duration, -for example: -

- -
-682580ns
-
- -

-Change steady_clock to system_clock (and if that clock has -different units on your platform), and the output automatically changes units for you: -

- -
-auto t0 = system_clock::now();
-f();
-auto t1 = system_clock::now();
-std::cout << t1 - t0 << '\n';
-
- -
-682µs
-
- -

-And yes, it really does print out the Greek letter µ and not -u. When streaming to char-based streams it uses UTF-8 encoding -to represent the Unicode character 'MICRO SIGN' (U+00B5). Otherwise it uses UTF-16 or -UTF-32 based on the size of character the stream is using. -

- -

-In general, if the duration tick period is the same type as one of the non-optional -std::ratio SI convenience typedefs (atto thru exa), -then the unit will use the internationally accepted symbol for the -metric prefix followed -by 's'. -

- -

-In addition, if the duration tick period is ratio<60>, then the -printed unit is min. And if the duration tick period is -ratio<3600>, then the unit is h. -

- -
-std::cout << 1s << '\n';
-std::cout << 2min << '\n';
-std::cout << 3h << '\n';
-
- -

-Outputs: -

- -
-1s
-2min
-3h
-
- -

-Sometimes odd durations pop up which have no widely recognized names. For example -consider this code: -

- -
-using frames = duration<int, ratio<1, 60>>;
-std::cout << 45ms + frames{5} << '\n';
-
- -

-This sum can't be exactly represented as either milliseconds or frames (1/60 of a second). -The compiler figures out the coarsest unit which can exactly represent the sum of -any millisecond and any frame and auto-generates that unit to hold the sum. For this -example that duration will have a tick period of 1/3000 of a second. This library -puts that ratio inside of square brackets, and then appends 's': -

- -
-385[1/3000]s
-
- -

-If the durations tick period is a whole number of seconds (period::den == 1), -then the /1 is dropped inside of the square brackets. The following example -uses months from date.h. -

- -
-std::cout << months{6} << '\n';
-
- -
-6[2629746]s
-
- -

-Trivia: 2,629,746s is the exact length of the average Gregorian month, which is also exactly -30.436875 24h days. -

- -

Implementation Details

- -

-Question: Why are there separate implementations for C++11 and C++14? -

- -

-Answer: The units of a duration are always known at compile -time. Thus the string representation of the units is always known at compile time. This -is true even when the unit is of the form [num/den]s. But only C++14 has -the gravitas to do the complete string conversion at compile time. And now that I've -claimed that, I'm sure someone will come up with a C++11 that VS-2015 won't compile anyway. -So I need a run-time solution (based on std::basic_string<CharT>, -and a compile-time solution that currently only gcc and clang with -std=c++14 -can handle. -

- -

-For example if you compile the following code with -std=c++14 and clang: -

- -
-using frames = std::chrono::duration<int, std::ratio<1, 60>>;
-
-void
-test(std::ostream& os, std::chrono::milliseconds x, frames y)
-{
-    using namespace date;
-    os << x + y;
-}
-
- -

-And then inspect the generated assembly, it contains this: -

- -
-movabsq	$6714920027984703835, %rax ## imm = 0x5D303030332F315B
-
- -

-Which is assembly-speak for "[1/3000]" all boiled down to one x86_64 instruction. The -'s' wouldn't quite fit within this one instruction and follows in a later -instruction. C++14 can do some amazing things at compile time! For C++11 I just -gave up and called std::to_string. -

- -

Reference

- -
-template <class CharT, class Traits, class Rep, class Period>
-std::basic_ostream<CharT, Traits>&
-operator<<(std::basic_ostream<CharT, Traits>& os,
-           const std::chrono::duration<Rep, Period>& d);
-
- -
-

-Effects: Equivalent to: -

-
-os << d.count() << detail::get_units<CharT>(duration<Rep, typename Period::type>{});
-
-

-Where detail::get_units<CharT>() returns a null-terminated string of -CharT which depends only on Period::type as follows (let -period be the type Period::type): -

- -
    -
  • If period is type std::atto, as, else
  • -
  • if period is type std::femto, fs, else
  • -
  • if period is type std::pico, ps, else
  • -
  • if period is type std::nano, ns, else
  • -
  • if period is type std::micro, µs (U+00B5), else
  • -
  • if period is type std::milli, ms, else
  • -
  • if period is type std::centi, cs, else
  • -
  • if period is type std::deci, ds, else
  • -
  • if period is type std::ratio<1>, s, else
  • -
  • if period is type std::deca, das, else
  • -
  • if period is type std::hecto, hs, else
  • -
  • if period is type std::kilo, ks, else
  • -
  • if period is type std::mega, Ms, else
  • -
  • if period is type std::giga, Gs, else
  • -
  • if period is type std::tera, Ts, else
  • -
  • if period is type std::peta, Ps, else
  • -
  • if period is type std::exa, Es, else
  • -
  • if period is type std::ratio<60>, min, else
  • -
  • if period is type std::ratio<3600>, h, else
  • -
  • if period::den == 1, [num]s, else
  • -
  • [num/den]s.
  • -
- -

-In the list above the use of num and den refer to the -static data members of period which are converted to arrays of -CharT using a decimal conversion with no leading zeroes. -

- -
-

-Returns: os. -

-
-
- diff --git a/date.html b/date.html index 4b7e0d6..88eeeb7 100644 --- a/date.html +++ b/date.html @@ -1485,6 +1485,7 @@ and predictable.  weeks  months  yearsFormatting and parsing durations    time_points  @@ -1674,7 +1675,7 @@ using months = std::chrono::duration <int, std::ratio_divide<years::period, std::ratio<12>>>; -

Formatting and parsing durations

+

Formatting and parsing durations

 template <class CharT, class Traits, class Rep, class Period>
@@ -1721,6 +1722,65 @@ flags): %H, %I, %M, %p,
 

+
+template <class CharT, class Traits, class Rep, class Period>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os,
+           const std::chrono::duration<Rep, Period>& d);
+
+ +
+

+Effects: Equivalent to: +

+
+os << to_string<CharT, Traits>(d.count()) + detail::get_units<CharT>(duration<Rep, typename Period::type>{});
+
+

+Where to_string is pseudo code that returns a +std::basic_string<CharT, Traits> representation of d.count(), +and detail::get_units<CharT>() returns a null-terminated string of +CharT which depends only on Period::type as follows (let +period be the type Period::type): +

+ +
    +
  • If period is type std::atto, as, else
  • +
  • if period is type std::femto, fs, else
  • +
  • if period is type std::pico, ps, else
  • +
  • if period is type std::nano, ns, else
  • +
  • if period is type std::micro, µs (U+00B5), else
  • +
  • if period is type std::milli, ms, else
  • +
  • if period is type std::centi, cs, else
  • +
  • if period is type std::deci, ds, else
  • +
  • if period is type std::ratio<1>, s, else
  • +
  • if period is type std::deca, das, else
  • +
  • if period is type std::hecto, hs, else
  • +
  • if period is type std::kilo, ks, else
  • +
  • if period is type std::mega, Ms, else
  • +
  • if period is type std::giga, Gs, else
  • +
  • if period is type std::tera, Ts, else
  • +
  • if period is type std::peta, Ps, else
  • +
  • if period is type std::exa, Es, else
  • +
  • if period is type std::ratio<60>, min, else
  • +
  • if period is type std::ratio<3600>, h, else
  • +
  • if period::den == 1, [num]s, else
  • +
  • [num/den]s.
  • +
+ +

+In the list above the use of num and den refer to the +static data members of period which are converted to arrays of +CharT using a decimal conversion with no leading zeroes. +

+ +
+

+Returns: os. +

+
+ +

sys_time