Printing facility for std::chrono::time_point Motivation:

It is known that std::time_point&lt;...&gt; cannot be streamed directly using operator&lt;&lt;(), which is pretty disappointing. Although Howard Hinnant created a good library, I'd like to have sole ownership of all of the code in my library, so I could do some benchmarks without including extra license and setup repositories faster.

Description:

Mainly it is only a streaming operator, which actually uses some C date-time library under the hood. The approach creates a huge chance for data race if std::chrono::time_point&lt;...&gt;s are streamed from multiple threads, even into multiple streams, because std::localtime() can return a static variable.

The formatting string is shared as well, which increases burden on users.

The streaming operator is templated only on the duration type, since casting between clocks which produced time point is not possible via std::chrono::time_point_cast&lt;&gt;().

Code:

#include &lt;iosfwd&gt;
#include &lt;chrono&gt;
#include &lt;iomanip&gt;
#include &lt;ctime&gt;
#include &lt;string&gt;

namespace shino
{
    namespace detail
    {
        std::string time_format{"%Y %b %d %H:%M:%S"};
    }

    std::string time_format()
    {
        return detail::time_format;
    }

    void set_time_format(const std::string&amp; format)
    {
        detail::time_format = format;
    }
}

template &lt;typename Duration&gt;
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os,
                         const std::chrono::time_point&lt;std::chrono::system_clock, Duration&gt;&amp; timep)
{
    using system_clock_duration = std::chrono::system_clock::duration;
    auto converted_timep = std::chrono::time_point_cast&lt;system_clock_duration&gt;(timep);
    auto seconds_since_epoch = std::chrono::system_clock::to_time_t(timep);
    os &lt;&lt; std::put_time(std::localtime(&amp;seconds_since_epoch), shino::time_format().c_str());
    return os;
}


Small demonstration:

#include &lt;iostream&gt;

int main()
{
    std::cout &lt;&lt; "current date and time: "
              &lt;&lt; std::chrono::system_clock::now() &lt;&lt; '\n';

    shino::set_time_format(shino::time_format() + " %a"); //add day of the week
    std::cout &lt;&lt; "current date and time with day of the week: "
              &lt;&lt; std::chrono::system_clock::now() &lt;&lt; '\n';

    return 0;
}


Result:



current date and time: 2017 Jun 17 16:01:27
current date and time with day of the week: 2017 Jun 17 16:01:27 Sat
Global singleton format looks a bit peculiar. Unfortunatelly, iostreams do not support user-defined stream properties like time format, but you can do something similar:

struct format
{
    std::string format;
    time_point time;
};

ostream &amp; operator &lt;&lt; (ostream &amp; os, format const &amp; f)
{
    // output f.time using f.format
    // ...
}


Which can be used like

std::cout &lt;&lt; format{"%Y %b %d %H:%M:%S %a", now()} &lt;&lt; std::endl;


Alongside with operator&lt;&lt;(ostream &amp;, time_point const &amp;) (which just uses some default predefined format) this can be used in a lot cleaner way.

(obviously, all this should be put to appropriate namespaces)