How do you print a C++11 time_point?

Trevor Hickey picture Trevor Hickey · Apr 3, 2013 · Viewed 72.6k times · Source

I've created a time point, but I have been struggling to print it to the terminal.

#include <iostream>
#include <chrono>

int main(){

    //set time_point to current time
    std::chrono::time_point<std::chrono::system_clock,std::chrono::nanoseconds> time_point;
    time_point = std::chrono::system_clock::now();

    //print the time
    //...

    return 0;
}

The only documentation I can find that prints a time_point is found here: http://en.cppreference.com/w/cpp/chrono/time_point

however, I'm not even able to create a time_t based on my time_point(like the example).

std::time_t now_c = std::chrono::system_clock::to_time_t(time_point); //does not compile

Error:

/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono: In instantiation of ‘constexpr std::chrono::time_point<_Clock, _Dur>::time_point(const std::chrono::time_point<_Clock, _Dur2>&) [with _Dur2 = std::chrono::duration<long int, std::ratio<1l, 1000000000l> >; _Clock = std::chrono::system_clock; _Dur = std::chrono::duration<long int, std::ratio<1l, 1000000l> >]’:
time.cpp:13:69:   required from here
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:540:32: error: no matching function for call to ‘std::chrono::duration<long int, std::ratio<1l, 1000000l> >::duration(std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long int, std::ratio<1l, 1000000000l> > >::duration)’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:540:32: note: candidates are:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:247:14: note: template<class _Rep2, class _Period2, class> constexpr std::chrono::duration::duration(const std::chrono::duration<_Rep2, _Period2>&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:247:14: note:   template argument deduction/substitution failed:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:243:46: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:240:23: note: template<class _Rep2, class> constexpr std::chrono::duration::duration(const _Rep2&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:240:23: note:   template argument deduction/substitution failed:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:236:27: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:234:12: note: constexpr std::chrono::duration<_Rep, _Period>::duration(const std::chrono::duration<_Rep, _Period>&) [with _Rep = long int; _Period = std::ratio<1l, 1000000l>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:234:12: note:   no known conversion for argument 1 from ‘std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long int, std::ratio<1l, 1000000000l> > >::duration {aka std::chrono::duration<long int, std::ratio<1l, 1000000000l> >}’ to ‘const std::chrono::duration<long int, std::ratio<1l, 1000000l> >&’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:232:12: note: constexpr std::chrono::duration<_Rep, _Period>::duration() [with _Rep = long int; _Period = std::ratio<1l, 1000000l>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/chrono:232:12: note:   candidate expects 0 arguments, 1 provided

Answer

HighCommander4 picture HighCommander4 · Apr 3, 2013

(In this post I will omit std::chrono:: qualifications for clarity. I trust you know where they go.)

The reason your code example fails to compile is that there is a mismatch between the return type of system_clock::now() and the type of variable you are trying to assign this to (time_point<system_clock, nanoseconds>).

The documented return value of system_clock::now() is system_clock::time_point, which is a typedef for time_point<system_clock, system_clock::duration>. system_clock::duration is implementation-defined, with microseconds and nanoseconds being commonly used. It seems that your implementation uses microseconds, so the return type of system_clock::now() is time_point<system_clock, microseconds>.

time_points with different durations are not implicitly convertible to one another, so you get a compiler error.

You can explicitly convert time points with different durations using time_point_cast, so the following would compile on your system:

time_point<system_clock, nanoseconds> time_point;
time_point = time_point_cast<nanoseconds>(system_clock::now());

Notice the explicit template parameter to time_point_cast is the target duration type, not the target time_point type. The clock types must match in a time_point_cast, so specifying the entire time_point type (which is templated on both the clock type and the duration type) would be redundant.

Of course in your case, since you are just looking to print the time point, there is no need for it to be at any specific resolution, so you can just declare time_point to be the same type as what system_clock::now() returns to begin with. A simple way to do that is to use the system_clock::time_point typedef:

system_clock::time_point time_point;
time_point = system_clock::now();  // no time_point_cast needed

Since this is C++11, you can also just use auto:

auto time_point = system_clock::now(); 

Having solved this compiler error, the conversion to time_t works just fine:

std::time_t now_c = std::chrono::system_clock::to_time_t(time_point);

and you can now use standard methods for displaying time_t values, like std::ctime or std::strftime. (As Cassio Neri points out in a comment to your question, the more C++-y std::put_time function is not yet supported by GCC).