diff --git a/chrono_io.html b/chrono_io.html new file mode 100644 index 0000000..3b398f4 --- /dev/null +++ b/chrono_io.html @@ -0,0 +1,332 @@ + + +
+chrono_io
+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.
+
+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::duration
s without hassle. +Streamingchrono::duration
s is the biggest use of +.count()
(a dangerous type cast), and that use should be handled by +a library such as this. +
+ ++#include "chrono_io.h" +#include <iostream> + +int +main() +{ + using namespace date; + using namespace std::chrono; + auto t0 = steady_clock::now(); + 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:
+
+ ++104ns +
+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(); +auto t1 = system_clock::now(); +std::cout << t1 - t0 << '\n'; +
+ ++0µ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. +
+ ++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
.
+
+ + ++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 onPeriod::type
as follows (let +period
be the typePeriod::type
): ++
+ +- If
+period
is typestd::atto
,as
, else- if
+period
is typestd::femto
,fs
, else- if
+period
is typestd::pico
,ps
, else- if
+period
is typestd::nano
,ns
, else- if
+period
is typestd::micro
,µs
(U+00B5), else- if
+period
is typestd::milli
,ms
, else- if
+period
is typestd::centi
,cs
, else- if
+period
is typestd::deci
,ds
, else- if
+period
is typestd::ratio<1>
,s
, else- if
+period
is typestd::deca
,das
, else- if
+period
is typestd::hecto
,hs
, else- if
+period
is typestd::kilo
,ks
, else- if
+period
is typestd::mega
,Ms
, else- if
+period
is typestd::giga
,Gs
, else- if
+period
is typestd::tera
,Ts
, else- if
+period
is typestd::peta
,Ps
, else- if
+period
is typestd::exa
,Es
, else- if
+period
is typestd::ratio<60>
,min
, else- if
+period
is typestd::ratio<3600>
,h
, else- if
+period::den == 1
,[num]s
, else- +
[num/den]s
.+In the list above the use of
+ +num
andden
refer to the +static data members ofperiod
which are converted to arrays of +CharT
using a decimal conversion with no leading zeroes. ++Returns:
+os
. +