Как вы печатаете time_point C ++ 11?

Я создал точку времени, но мне не удается распечатать ее на терминале.

#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;
}

Единственная документация, которую я могу найти, которая печатает time_point, находится здесь: http://en.cppreference.com/w/cpp/chrono/time_point

однако я даже не могу создать time_t на основе моего time_point (как в примере).

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

Ошибка:

/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

person Trevor Hickey    schedule 03.04.2013    source источник


Ответы (7)


(В этом посте я опущу std::chrono:: оговорки для ясности. Надеюсь, вы знаете, куда они идут.)

Причина, по которой ваш пример кода не компилируется, заключается в несоответствии между типом возвращаемого значения system_clock::now() и типом переменной, которой вы пытаетесь присвоить это значение (time_point<system_clock, nanoseconds>).

Задокументированное возвращаемое значение system_clock::now() - system_clock::time_point, которое является typedef для time_point<system_clock, system_clock::duration>. system_clock::duration определяется реализацией, обычно используются microseconds и nanoseconds. Кажется, что ваша реализация использует microseconds, поэтому тип возврата system_clock::now() - time_point<system_clock, microseconds>.

time_points с разной длительностью не могут быть неявно преобразованы друг в друга, поэтому вы получите ошибку компилятора.

Вы можете явно преобразовать временные точки с разной продолжительностью с помощью time_point_cast, чтобы в вашей системе компилировалось следующее:

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

Обратите внимание, что явный параметр шаблона для time_point_cast является типом целевой продолжительности, а не типом целевой time_point. Типы часов должны совпадать в time_point_cast, поэтому указание всего типа time_point (который шаблонизирован как для типа часов, так и для типа продолжительности) будет избыточным.

Конечно, в вашем случае, поскольку вы просто хотите распечатать точку времени, нет необходимости в том, чтобы она была в каком-либо конкретном разрешении, поэтому вы можете просто объявить time_point тем же типом, что и то, что возвращает system_clock::now() для начала. Простой способ сделать это - использовать system_clock::time_point typedef:

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

Поскольку это C ++ 11, вы также можете просто использовать auto:

auto time_point = system_clock::now(); 

После устранения этой ошибки компилятора преобразование в time_t работает нормально:

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

и теперь вы можете использовать стандартные методы для отображения time_t значений, например std::ctime или std::strftime. (Как отмечает Кассио Нери в комментарии к вашему вопросу, функция more C ++ - y std::put_time еще не поддерживается GCC).

person HighCommander4    schedule 03.04.2013
comment
+1 Для более подробного объяснения и упоминания auto (на самом деле, это C ++, никто не объявляет переменную и не присваивает ее в следующей строке, даже без auto). - person Christian Rau; 03.04.2013
comment
@ HighCommander4: time_point с разной длительностью неявно конвертируются друг в друга, если они используют один и тот же Clock и если правая сторона Duration неявно конвертируется в левую сторону Duration. В этом примере, если system_clock::duration составляет микросекунды или наносекунды, он выполняет неявное преобразование в time_point<system_clock, nanoseconds> в соответствии с [time.point.cons] / p3. - person Howard Hinnant; 17.06.2013

Этот фрагмент может вам помочь:

#include <iomanip>
#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
}
person Matt Clarkson    schedule 22.05.2013
comment
Только std::chrono::system_clock поддерживает to_time_t, поэтому я думаю, что нет смысла использовать это в качестве шаблона. Вместо этого time_point можно было бы передать напрямую как const system_clock::time_point &time_point. - person David L.; 20.11.2013
comment
Зависит от того, создает ли пользователь определенные пользователем часы, на которых стоит to_time_t. - person Matt Clarkson; 17.02.2014

Обновленный ответ на старый вопрос:

Для std::chrono::time_point<std::chrono::system_clock, some-duration> теперь есть сторонние библиотеки, которые дают вам гораздо лучший контроль. Для time_points, основанных на других часах, все еще нет лучшего решения, чем просто получить внутреннее представление и распечатать его.

Но для system_clock, используя эту библиотеку, это так же просто, как:

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

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

который просто выводит для меня:

2016-07-19 03:21:01.910626 UTC

текущая дата и время в формате UTC с точностью до микросекунд. Если на вашей платформе system_clock::time_point имеет точность наносекунды, она распечатает для вас точность наносекунды.

2021 Обновление

Вот версия указанной выше программы на C ++ 20:

#include <chrono>
#include <iostream>

int
main()
{
    std::cout << std::chrono::system_clock::now() << " UTC\n";
}
person Howard Hinnant    schedule 19.07.2016
comment
хм, это должно быть в стандартной ИМО. - person Abhinav Gauniyal; 22.09.2016
comment
@AbhinavGauniyal: работа над этим (open-std .org / jtc1 / sc22 / wg21 / docs / paper / 2016 / p0355r1.html). Скорее всего, для этого потребуется ваша очень громкая помощь. Значительным силам в комитете это предложение не нравится, и они выиграют, если общественность не откликнется на них. - person Howard Hinnant; 15.01.2017
comment
Конкурирующие предложения с альтернативным (имхо второстепенным) дизайном. Ожидайте, что третья редакция моего предложения появится в течение недели на open-std.org/jtc1/sc22/wg21/docs/papers/2017 - person Howard Hinnant; 26.06.2017
comment
Теперь, когда слегка измененная версия date.h перешла в C ++ 2a, является ли вывод time_point его частью? Я использую последний gcc с -std = c ++ 2a и не получаю его - person haelix; 17.11.2018
comment
time_point вывод, когда time_point основан на system_clock, является частью проекта C ++ 2a. Тем не менее, это большое предложение, и никто, о котором я знаю, еще не отправил его. - person Howard Hinnant; 17.11.2018

nanoseconds, похоже, является частью проблемы, немного посмотрев документацию, я смог заставить это работать:

#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;
}

Хотя похоже, что std::chrono::microseconds работает нормально:

std::chrono::time_point<std::chrono::system_clock,std::chrono::microseconds> time_point;
person Shafik Yaghmour    schedule 03.04.2013
comment
Кстати, более лаконичный auto time_point = std::chrono::system_clock::now();, вероятно, тоже подошел бы. - person Christian Rau; 03.04.2013
comment
@ChristianRau Конечно, честно, я обычно предпочитаю сохранять код как можно ближе к исходному опубликованному коду, если он явно не сломан или неправильный. - person Shafik Yaghmour; 03.04.2013
comment
Также гораздо более лаконичный: high_resolution_clock::now(). - person zwcloud; 29.10.2018

Для всех, кто работает с time_point<steady_clock> (не 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)
{
    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";
}

Средство форматирования десятичных чисел не является наиболее эффективным, но не требует предварительного знания количества десятичных знаков, которое неизвестно, если вы хотите использовать шаблон resolution, если вы не можете придумать постоянное выражение для ceil(log10(resolution)).

person user2394284    schedule 03.07.2017
comment
Для дополнительной скорости вы можете использовать мой itoa (который действительно имеет постоянное выражение для ceil (log10 (разрешение), но только для статического утверждения, что переданный буфер достаточно велик;) ... github.com/CarloWood/ai-utils/blob/master/itoa.h#L46 - person Carlo Wood; 22.05.2021

Ctime () не работает для Visual C ++. Я использую MS Visual Studio 2013. Я изменил приведенный выше код, чтобы использовать ctime_s (...), как было предложено компилятором MSVC. Это сработало.

//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;
person Longbow    schedule 06.05.2016

Еще один фрагмент кода. Плюс в том, что он довольно автономен и поддерживает текстовое представление микросекунд.

std::ostream& operator<<(std::ostream& stream, const std::chrono::system_clock::time_point& point)
{
    auto time = std::chrono::system_clock::to_time_t(point);
    std::tm* tm = std::localtime(&time);
    char buffer[26];
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S.", tm);
    stream << buffer;
    auto duration = point.time_since_epoch();
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
    auto remaining = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - seconds);
    // remove microsecond cast line if you would like a higher resolution sub second time representation, then just stream remaining.count()
    auto micro = std::chrono::duration_cast<std::chrono::microseconds>(remaining);
    return stream << micro.count();
}
person Jonathan    schedule 21.10.2020