¿Cómo se imprime un punto de tiempo C++11?


He creado un punto de tiempo, pero he estado luchando para imprimirlo en el 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;
}

La única documentación que puedo encontrar que imprime un time_point se encuentra aquí: http://en.cppreference.com/w/cpp/chrono/time_point

Sin embargo, ni siquiera puedo crear un time_t basado en mi time_point(como en el ejemplo).

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
Author: Trevor Hickey, 2013-04-03

6 answers

(En este post omitiré std::chrono:: las calificaciones para la claridad. Confío en que sepa adónde van.)

La razón por la que su ejemplo de código no se compila es que hay un desajuste entre el tipo devuelto de system_clock::now() y el tipo de variable al que está tratando de asignar esto (time_point<system_clock, nanoseconds>).

El valor de retorno documentado de system_clock::now() es system_clock::time_point, que es un typedef para time_point<system_clock, system_clock::duration>. system_clock::duration está definido por la implementación, con microseconds y nanoseconds siendo de uso común. Parece que su implementación utiliza microseconds, por lo que el tipo de retorno de system_clock::now() es time_point<system_clock, microseconds>.

time_points con diferentes duraciones no son implícitamente convertibles entre sí, por lo que se obtiene un error del compilador.

Puede explícitamente convertir puntos de tiempo con diferentes duraciones usando time_point_cast, por lo que lo siguiente se compilaría en su sistema:

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

Observe que el parámetro de plantilla explícito para time_point_castes el tipo target duration, no el tipo target time_point. Los tipos de reloj deben coincidir en un time_point_cast, por lo que especificar todo el tipo time_point (que se templa tanto en el tipo de reloj como en el tipo de duración) sería redundante.

Por supuesto en su caso, ya que solo está buscando imprimir el punto de tiempo, no hay necesidad de que esté en una resolución específica, por lo que puede declarar que time_point es del mismo tipo que lo que system_clock::now() devuelve para empezar. Una forma sencilla de hacerlo es usar el system_clock::time_point typedef:

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

Dado que esto es C++11, también puede usar auto:

auto time_point = system_clock::now(); 

Habiendo resuelto este error del compilador, la conversión a time_t funciona bien:

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

Y ahora puede usar métodos estándar para mostrar valores time_t, como std::ctime o std::strftime. (Como Cassio Neri señala en un comentario a su pregunta, la función more C++-y std::put_time aún no es compatible con GCC).

 45
Author: HighCommander4,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-03 02:52:38

Este fragmento podría ayudarte:

#include <iostream>
#include <chrono>
#include <ctime>

template<typename Clock, typename Duration>
std::ostream &operator<<(std::ostream &stream,
  const std::chrono::time_point<Clock, Duration> &time_point) {
  const time_t time = Clock::to_time_t(time_point);
#if __GNUC__ > 4 || \
    ((__GNUC__ == 4) && __GNUC_MINOR__ > 8 && __GNUC_REVISION__ > 1)
  // Maybe the put_time will be implemented later?
  struct tm tm;
  localtime_r(&time, &tm);
  return stream << std::put_time(&tm, "%c"); // Print standard date&time
#else
  char buffer[26];
  ctime_r(&time, buffer);
  buffer[24] = '\0';  // Removes the newline that is added
  return stream << buffer;
#endif
}

int main() {
  std::cout << std::chrono::system_clock::now() << std::endl;
  // Wed May 22 14:17:03 2013
}
 14
Author: Matt Clarkson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-19 00:45:11

El nanoseconds parece ser parte del problema, mirando un poco la documentación pude hacer que esto funcionara:

#include <iostream>
#include <chrono>
#include <ctime>


int main(){

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

    std::time_t ttp = std::chrono::system_clock::to_time_t(time_point);
    std::cout << "time: " << std::ctime(&ttp);

    return 0;
}

Aunque parece que std::chrono::microseconds funciona bien:

std::chrono::time_point<std::chrono::system_clock,std::chrono::microseconds> time_point;
 10
Author: Shafik Yaghmour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-03 07:20:27

Respuesta actualizada para una vieja pregunta:

Para un std::chrono::time_point<std::chrono::system_clock, some-duration> ahora hay una 3rd bibliotecas de partido que le dan mucho mejor control. Para time_points basados en otros relojes, todavía no hay mejor solución que simplemente obtener la representación interna e imprimirla.

Pero para system_clock, usando esta biblioteca , esto es tan fácil como:

#include "date.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono;
    std::cout << system_clock::now() << " UTC\n";
}

Que acaba de salir para mí:

2016-07-19 03:21:01.910626 UTC

Que es la fecha y hora UTC actual con precisión de microsegundos. Si en su plataforma system_clock::time_point tiene una precisión de nanosegundos, imprimirá una precisión de nanosegundos para usted.

 9
Author: Howard Hinnant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-19 03:25:51

Para cualquiera que trabaje con time_point<steady_clock> (no time_point<system_clock>):

#include <chrono>
#include <iostream>

template<std::intmax_t resolution>
std::ostream &operator<<(
    std::ostream &stream,
    const std::chrono::duration<
        std::intmax_t,
        std::ratio<std::intmax_t(1), resolution>
    > &duration)
{
    const std::intmax_t ticks = duration.count();
    stream << (ticks / resolution) << '.';
    std::intmax_t div = resolution;
    std::intmax_t frac = ticks;
    for (;;) {
        frac %= div;
        if (frac == 0) break;
        div /= 10;
        stream << frac / div;
    }
    return stream;
}

template<typename Clock, typename Duration>
std::ostream &operator<<(
    std::ostream &stream,
    const std::chrono::time_point<Clock, Duration> &timepoint)
{
    typename Duration::duration ago = timepoint.time_since_epoch();
    return stream << ago;
}

int main(){
    // print time_point
    std::chrono::time_point<std::chrono::steady_clock> now =
        std::chrono::steady_clock::now();
    std::cout << now << "\n";

    // print duration (such as the difference between 2 time_points)
    std::chrono::steady_clock::duration age = now - now;
    std::cout << age << "\n";
}

El formateador de números decimales no es el más eficiente, pero no necesita un conocimiento previo del número de decimales, que no se conoce si desea que resolution sea templada, a menos que pueda idear una expresión constante para ceil(log10(resolution)).

 2
Author: user2394284,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 16:47:41

La función ctime() no funciona para Visual C++. Uso MS Visual Studio 2013. Cambié el código anterior para usar ctime_s (...), como lo solicita el compilador MSVC. Funcionó.

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

std::time_t ttp = std::chrono::system_clock::to_time_t(time_point);
char chr[50];
errno_t e = ctime_s(chr, 50, &ttp);
if (e) std::cout << "Error." << std::endl;
else std::cout << chr << std::endl;
 1
Author: Longbow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-09 23:40:35