使用VC141

时间:2018-09-12 09:56:03

标签: c++ std chrono

我刚刚在Visual Studio 2013中使用

#include <chrono>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <sstream>

std::string Time_Point_String(const std::chrono::high_resolution_clock::time_point & timePoint)
{
    time_t timeNow = std::chrono::system_clock::to_time_t(timePoint);

    tm time = *localtime(&timeNow);

    std::stringstream timeString;
timeString << std::setfill('0') << 1900 + time.tm_year << "-" << std::setw(2) << time.tm_mon + 1 << "-" << std::setw(2) << time.tm_mday << " " << std::setw(2) << time.tm_hour << ":" << std::setw(2) << time.tm_min << ":" << std::setw(2) << time.tm_sec;

    return timeString.str();
}

int main()
{
    const std::chrono::high_resolution_clock::time_point & timePoint = std::chrono::high_resolution_clock::now();

    std::cout << Time_Point_String(timePoint);
    return 0;
}

但是在Visual Studio 2017中,我得到了一个编译器错误:

  

错误C2664'__time64_t std :: chrono :: system_clock :: to_time_t(const std :: chrono :: system_clock :: time_point&)noexcept':无法从'const std :: chrono :: steady_clock ::转换参数1 time_point'改为'const std :: chrono :: system_clock :: time_point&'

因此,不可能再将high_resolution_clock::time_point转换为不同的time_point,例如system_clock::time_point,并且不可能将high_resolution_clock::time_point转换为time_t直接吗?

如何处理这种情况? 可能吗(有些SO帖子说它们只是完全不同的时钟,转换没有意义)? 据我所知,该函数完成了Visual Studio 2013应用程序中的预期工作,它为high_resolution time_point提供了正确的本地时间。

3 个答案:

答案 0 :(得分:3)

这是因为std::chrono::high_resolution_clock<template> <custom-element view-model.ref="custom"></custom-element> <custom-element2 opened.call="custom.opened()"></custom-element2> </template> std::chrono::system_clock的类型别名:

  

std::chrono::steady_clock代表实现所提供的最小滴答周期的时钟。它可以是std::chrono::high_resolution_clockstd::chrono::system_clock的别名,也可以是第三个独立的时钟。

这意味着std::chrono::steady_clock可以是std::chrono::high_resolution_clock::time_point的类型别名,也可以是其他类型。从您的问题中,您可以猜到它对MSVC2013有用,使您的代码有效,但对MSVC2017无效,使您的代码无效。

结论是,以下代码可能以未指定的方式有效(或无效)(取决于编译器及其目标体系结构):

std::chrono::system_clock::time_point

答案 1 :(得分:1)

您只能在同一时钟的time_point之间进行转换。 std::chrono::high_resolution_clock是另一个时钟的别名。如果恰好是std::chrono::system_clock,则可以转换为time_t。

如果std::chrono::high_resolution_clock是另一个时钟,则可以通过计算当前时间与std::chrono::system_clock中的输入时间之间的差并将该差添加到系统时间来将其近似转换为std::chrono::high_resolution_clock

#include <iostream>
#include <chrono>

int main()
{
  auto input = std::chrono::high_resolution_clock::now();

  auto highResNow = std::chrono::high_resolution_clock::now();
  auto systemNow = std::chrono::system_clock::now();
  auto output = systemNow + (highResNow - input);
  std::cout << std::chrono::system_clock::to_time_t( output ) << "\n";
}

请注意,转换仅是近似的,理想情况下highResNowsystemNow需要同时计算,但是它们之间会有很小的差距。输入时间和当前时间间隔越远,转换也将越不可靠。

答案 2 :(得分:1)

这只是数据。 C++ 类型系统功能强大,但不是绝对的。您可以在 std::chrono::system_clock 和 time_t 之间转换的原因是它们共享相同的纪元,或“时钟开始的时间”。对于 time_t,这是自纪元“1969 年 12 月 31 日星期三 19:00:00”或自 UTC 1970 年 1 月 1 日 00:00 以来的秒数,although it is not defined。因此,转换系统时钟就像将时钟的原始分辨率转换为自纪元以来的秒数一样简单。 time_point 封装了自纪元以来的时间。对于 high_resolution_clock 或除 system_clock 之外的任何其他时钟,不能保证纪元是相同的。可能是电脑开机的时候,或者是插上cmos电池的时候,程序开始的时候……谁知道呢?谁在乎?时代的差异是它们不兼容的原因。不一定是他们的类型。虽然...,别名将确保共享相同的纪元。因此,任何给定时间点的纪元之间的差异(以秒为单位的偏移量)将为我们提供转换。这里没有更多的热身是代码:

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

namespace joe {

    template<typename Test, template<typename...> class Ref>
    struct is_specialization : public std::false_type {};
    template<template<typename...> class Ref, typename... Args>
    struct is_specialization<Ref<Args...>, Ref> : public std::true_type {};

    template <class Duration >
    using is_duration = is_specialization<Duration, std::chrono::duration>;

    template<class, class = void>
    struct is_clock : public std::false_type {};
    template<class Clock>
    struct is_clock<Clock, std::void_t<typename Clock::rep, typename Clock::period, typename Clock::duration,
        typename Clock::time_point, decltype(Clock::is_steady), decltype(Clock::now())>> : public std::true_type {};

    template<typename Clock, class Duration = typename Clock::duration>
    [[nodiscard]] static inline time_t to_time_t(const std::chrono::time_point<Clock, Duration>& time) noexcept {
        static_assert(joe::is_clock<Clock>::value, "The given type for Clock does not fulfill the requirements of a clock.");
        static_assert(joe::is_duration<Duration>::value, "The given type for Duration is not of std::chrono::duration.");
        static const long long offset = (std::is_same< Clock, std::chrono::system_clock>::value) ? 0
            : (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count()
                - std::chrono::duration_cast<std::chrono::seconds>(Clock::now().time_since_epoch()).count());
        return std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count() + offset;
    }

    template<typename Clock, class Duration = typename Clock::duration>
    [[nodiscard]] static inline std::chrono::time_point<Clock, Duration> from_time_t( time_t time) noexcept {
        static_assert(joe::is_clock<Clock>::value, "The given type for Clock does not fulfill the requirements of a clock.");
        static_assert(joe::is_duration<Duration>::value, "The given type for Duration is not of std::chrono::duration.");
        static const long long offset = (std::is_same< Clock, std::chrono::system_clock>::value) ? 0
            : (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count()
                - std::chrono::duration_cast<std::chrono::seconds>(Clock::now().time_since_epoch()).count());
        return std::chrono::time_point<Clock, Duration>{ std::chrono::duration_cast<Duration>(std::chrono::seconds{ time - offset }) };
    }

    [[nodiscard]] static inline std::string ctime( time_t result) noexcept
    {
        char str[26];
        ctime_s(str, sizeof str, &result);
        return std::string(str);
    }
}

void check_system_epoch()
{
    const std::chrono::system_clock::time_point timePoint;
    time_t time = joe::to_time_t(timePoint);
    std::cout << "system clock epoch : " << joe::ctime(time) << std::endl;
}

void check_high_res_epoch()
{
    const std::chrono::high_resolution_clock::time_point timePoint;
    time_t time = joe::to_time_t(timePoint);
    std::cout << "high resolution clock epoch : " << joe::ctime(time) << std::endl;
}

int main()
{
    const std::chrono::high_resolution_clock::time_point & timePoint = std::chrono::high_resolution_clock::now();

    time_t time = joe::to_time_t(timePoint);
    std::cout << joe::ctime( time ) << std::endl;

    std::cout << "Press the enter key to continue!\n";
    check_system_epoch();
    std::cin.ignore();
    std::cout << "Press the enter key to continue!\n";
    check_high_res_epoch();
    std::cin.ignore();
}

` 这为您提供了 to_time_t、from_time_t 和 ctime,适用于任何时钟。