forked from HowardHinnant/date
Move chrono_io.h functionality into date.h.
This commit is contained in:
302
chrono_io.html
302
chrono_io.html
@@ -26,311 +26,15 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br/>
|
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br/>
|
||||||
2016-07-30<br/>
|
2017-04-13<br/>
|
||||||
</address>
|
</address>
|
||||||
<hr/>
|
<hr/>
|
||||||
<h1 align=center><code>chrono_io</code></h1>
|
<h1 align=center><code>chrono_io</code></h1>
|
||||||
|
|
||||||
<h2>Contents</h2>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/HowardHinnant/date">github link</a></li>
|
|
||||||
<li><a href="#Introduction">Introduction</a></li>
|
|
||||||
<li><a href="#Examples">Examples</a></li>
|
|
||||||
<li><a href="#Implementation">Implementation Details</a></li>
|
|
||||||
<li><a href="#Reference">Reference</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a name="Introduction"></a><h2>Introduction</h2>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This is a small library which does nothing but add non-configurable, non-localizable
|
This library has been moved to
|
||||||
streaming to <code>std::chrono::duration</code>. The streaming operator lives in
|
<a href="date.html#duration_io"><code>"date.h"</code></a>.
|
||||||
<code>namespace date</code> for convenience purposes, and does not live in
|
|
||||||
<code>namespace std::chrono</code> as that would violate the standard.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
|
||||||
The entire API of this library is:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
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
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Just one signature for an entire library? Are you serious?!
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<p>
|
|
||||||
Very serious.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
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 <code>std::chrono::duration</code> just by parsing arithmetic types
|
|
||||||
and strings.
|
|
||||||
</p>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
No formatting options?!
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<p>
|
|
||||||
No.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
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 <code>chrono::duration</code>s without hassle.
|
|
||||||
Streaming <code>chrono::duration</code>s is the biggest use of
|
|
||||||
<code>.count()</code> (a dangerous type cast), and that use should be handled by
|
|
||||||
a library such as this.
|
|
||||||
</p>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<a name="Examples"></a><h2>Examples</h2>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
#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';
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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
|
|
||||||
<code>steady_clock</code> and print out the value <i>and</i> units for that duration,
|
|
||||||
for example:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
682580ns
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Change <code>steady_clock</code> to <code>system_clock</code> (and if that clock has
|
|
||||||
different units on your platform), and the output automatically changes units for you:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
auto t0 = system_clock::now();
|
|
||||||
f();
|
|
||||||
auto t1 = system_clock::now();
|
|
||||||
std::cout << t1 - t0 << '\n';
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
682µs
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
And yes, it really does print out the Greek letter <code>µ</code> and not
|
|
||||||
<code>u</code>. When streaming to <code>char</code>-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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In general, if the duration tick period is the same type as one of the non-optional
|
|
||||||
<code>std::ratio</code> SI convenience typedefs (<code>atto</code> thru <code>exa</code>),
|
|
||||||
then the unit will use the internationally accepted symbol for the
|
|
||||||
<a href="https://en.wikipedia.org/wiki/Metric_prefix">metric prefix</a> followed
|
|
||||||
by <code>'s'</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In addition, if the duration tick period is <code>ratio<60></code>, then the
|
|
||||||
printed unit is <code>min</code>. And if the duration tick period is
|
|
||||||
<code>ratio<3600></code>, then the unit is <code>h</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
std::cout << 1s << '\n';
|
|
||||||
std::cout << 2min << '\n';
|
|
||||||
std::cout << 3h << '\n';
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Outputs:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
1s
|
|
||||||
2min
|
|
||||||
3h
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Sometimes odd durations pop up which have no widely recognized names. For example
|
|
||||||
consider this code:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
using frames = duration<int, ratio<1, 60>>;
|
|
||||||
std::cout << 45ms + frames{5} << '\n';
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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 <code>'s'</code>:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
385[1/3000]s
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If the durations tick period is a whole number of seconds (<code>period::den == 1</code>),
|
|
||||||
then the <code>/1</code> is dropped inside of the square brackets. The following example
|
|
||||||
uses <code>months</code> from <a href="https://github.com/HowardHinnant/date">date.h</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
std::cout << months{6} << '\n';
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
6[2629746]s
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<i>Trivia:</i> 2,629,746s is the exact length of the average Gregorian month, which is also exactly
|
|
||||||
30.436875 24h days.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<a name="Implementation"></a><h2>Implementation Details</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<i>Question:</i> Why are there separate implementations for C++11 and C++14?
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<i>Answer:</i> The units of a <code>duration</code> are <i>always</i> 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 <code>[num/den]s</code>. 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 <code>std::basic_string<CharT></code>,
|
|
||||||
and a compile-time solution that currently only gcc and clang with <code>-std=c++14</code>
|
|
||||||
can handle.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For example if you compile the following code with <code>-std=c++14</code> and clang:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
And then inspect the generated assembly, it contains this:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
movabsq $6714920027984703835, %rax ## imm = 0x5D303030332F315B
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Which is assembly-speak for "[1/3000]" all boiled down to one x86_64 instruction. The
|
|
||||||
<code>'s'</code> wouldn't quite fit within this one instruction and follows in a later
|
|
||||||
instruction. C++14 can do some <i>amazing</i> things at compile time! For C++11 I just
|
|
||||||
gave up and called <code>std::to_string</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<a name="Reference"></a><h2>Reference</h2>
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
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);
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<p>
|
|
||||||
<i>Effects:</i> Equivalent to:
|
|
||||||
</p>
|
|
||||||
<blockquote><pre>
|
|
||||||
os << d.count() << detail::get_units<CharT>(duration<Rep, typename Period::type>{});
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
Where <code>detail::get_units<CharT>()</code> returns a null-terminated string of
|
|
||||||
<code>CharT</code> which depends only on <code>Period::type</code> as follows (let
|
|
||||||
<code>period</code> be the type <code>Period::type</code>):
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>If <code>period</code> is type <code>std::atto</code>, <code>as</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::femto</code>, <code>fs</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::pico</code>, <code>ps</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::nano</code>, <code>ns</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::micro</code>, <code>µs</code> (U+00B5), else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::milli</code>, <code>ms</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::centi</code>, <code>cs</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::deci</code>, <code>ds</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::ratio<1></code>, <code>s</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::deca</code>, <code>das</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::hecto</code>, <code>hs</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::kilo</code>, <code>ks</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::mega</code>, <code>Ms</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::giga</code>, <code>Gs</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::tera</code>, <code>Ts</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::peta</code>, <code>Ps</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::exa</code>, <code>Es</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::ratio<60></code>, <code>min</code>, else</li>
|
|
||||||
<li>if <code>period</code> is type <code>std::ratio<3600></code>, <code>h</code>, else</li>
|
|
||||||
<li>if <code>period::den == 1</code>, <code>[num]s</code>, else</li>
|
|
||||||
<li><code>[num/den]s</code>.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In the list above the use of <code>num</code> and <code>den</code> refer to the
|
|
||||||
static data members of <code>period</code> which are converted to arrays of
|
|
||||||
<code>CharT</code> using a decimal conversion with no leading zeroes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
<i>Returns:</i> <code>os</code>.
|
|
||||||
</p>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
62
date.html
62
date.html
@@ -1485,6 +1485,7 @@ and predictable.
|
|||||||
<tr><td> </td><td><a href="#weeks"><code>weeks</code></a></td></tr>
|
<tr><td> </td><td><a href="#weeks"><code>weeks</code></a></td></tr>
|
||||||
<tr><td> </td><td><a href="#months"><code>months</code></a></td></tr>
|
<tr><td> </td><td><a href="#months"><code>months</code></a></td></tr>
|
||||||
<tr><td> </td><td><a href="#years"><code>years</code></a></td></tr>
|
<tr><td> </td><td><a href="#years"><code>years</code></a></td></tr>
|
||||||
|
<tr><td> </td><td><a href="#duration_io"><code>Formatting and parsing durations</code></a></td></tr>
|
||||||
|
|
||||||
<tr><td> </td><td> </td></tr>
|
<tr><td> </td><td> </td></tr>
|
||||||
<tr><td>time_points</td><td> </td></tr>
|
<tr><td>time_points</td><td> </td></tr>
|
||||||
@@ -1674,7 +1675,7 @@ using months = std::chrono::duration
|
|||||||
<int, std::ratio_divide<years::period, std::ratio<12>>>;
|
<int, std::ratio_divide<years::period, std::ratio<12>>>;
|
||||||
</pre></blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<h3>Formatting and parsing durations</h3>
|
<a name="duration_io"></a><h3>Formatting and parsing durations</h3>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
template <class CharT, class Traits, class Rep, class Period>
|
template <class CharT, class Traits, class Rep, class Period>
|
||||||
@@ -1721,6 +1722,65 @@ flags): <code>%H</code>, <code>%I</code>, <code>%M</code>, <code>%p</code>,
|
|||||||
</p>
|
</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
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);
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>
|
||||||
|
<i>Effects:</i> Equivalent to:
|
||||||
|
</p>
|
||||||
|
<blockquote><pre>
|
||||||
|
os << to_string<CharT, Traits>(d.count()) + detail::get_units<CharT>(duration<Rep, typename Period::type>{});
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Where <code>to_string</code> is pseudo code that returns a
|
||||||
|
<code>std::basic_string<CharT, Traits></code> representation of <code>d.count()</code>,
|
||||||
|
and <code>detail::get_units<CharT>()</code> returns a null-terminated string of
|
||||||
|
<code>CharT</code> which depends only on <code>Period::type</code> as follows (let
|
||||||
|
<code>period</code> be the type <code>Period::type</code>):
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>If <code>period</code> is type <code>std::atto</code>, <code>as</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::femto</code>, <code>fs</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::pico</code>, <code>ps</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::nano</code>, <code>ns</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::micro</code>, <code>µs</code> (U+00B5), else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::milli</code>, <code>ms</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::centi</code>, <code>cs</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::deci</code>, <code>ds</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::ratio<1></code>, <code>s</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::deca</code>, <code>das</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::hecto</code>, <code>hs</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::kilo</code>, <code>ks</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::mega</code>, <code>Ms</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::giga</code>, <code>Gs</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::tera</code>, <code>Ts</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::peta</code>, <code>Ps</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::exa</code>, <code>Es</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::ratio<60></code>, <code>min</code>, else</li>
|
||||||
|
<li>if <code>period</code> is type <code>std::ratio<3600></code>, <code>h</code>, else</li>
|
||||||
|
<li>if <code>period::den == 1</code>, <code>[num]s</code>, else</li>
|
||||||
|
<li><code>[num/den]s</code>.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In the list above the use of <code>num</code> and <code>den</code> refer to the
|
||||||
|
static data members of <code>period</code> which are converted to arrays of
|
||||||
|
<code>CharT</code> using a decimal conversion with no leading zeroes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
<p>
|
||||||
|
<i>Returns:</i> <code>os</code>.
|
||||||
|
</p>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
|
||||||
<a name="sys_time"></a><h3><code>sys_time</code></h3>
|
<a name="sys_time"></a><h3><code>sys_time</code></h3>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
Reference in New Issue
Block a user