使用 std::chrono 在 C 中输出日期和时间

新手上路,请多包涵

我一直在升级一些旧代码,并在可能的情况下尝试更新到 c++11。以下代码是我用来在程序中显示时间和日期的方式

#include <iostream>
#include <string>
#include <stdio.h>
#include <time.h>

const std::string return_current_time_and_date() const
{
    time_t now = time(0);
    struct tm tstruct;
    char buf[80];
    tstruct = *localtime(&now);
    strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
    return buf;
}

我想使用 std::chrono(或类似的)以类似的格式输出当前时间和日期,但我不确定如何去做。任何帮助将不胜感激。谢谢

原文由 const_ref 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

<chrono> 库只处理时间而不是日期,除了 system_clock 它能够将其时间点转换为 time_t 。所以使用 <chrono> 作为日期不会有太大的改善。希望我们在不久的将来能得到类似 chrono::date 的东西。

也就是说,您可以通过以下方式使用 <chrono>

 #include <chrono>  // chrono::system_clock
#include <ctime>   // localtime
#include <sstream> // stringstream
#include <iomanip> // put_time
#include <string>  // string

std::string return_current_time_and_date()
{
    auto now = std::chrono::system_clock::now();
    auto in_time_t = std::chrono::system_clock::to_time_t(now);

    std::stringstream ss;
    ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
    return ss.str();
}

请注意, std::localtime 可能会导致数据争用。 localtime_r 或类似功能可能在您的平台上可用。

更新:

使用新版本的 Howard Hinnant 的 日期库,您可以编写:

 #include "date.h"
#include <chrono>
#include <string>
#include <sstream>

std::string return_current_time_and_date() {
  auto now = std::chrono::system_clock::now();
  auto today = date::floor<days>(now);

  std::stringstream ss;
  ss << today << ' ' << date::make_time(now - today) << " UTC";
  return ss.str();
}

这将打印出类似“2015-07-24 05:15:34.043473124 UTC”的内容。


在不相关的注释中,返回 const 对象已成为 C++11 不可取的; const 返回值不能被移出。我还删除了尾随 const,因为尾随 const 仅对成员函数有效,并且此函数不需要成为成员。

原文由 bames53 发布,翻译遵循 CC BY-SA 3.0 许可协议

尽管已经给出了正确的答案,但我决定实施另一种解决方案,该解决方案也输出秒的小数部分。

您可能会在我的代码中注意到,有时我会从 time_t 值中减去一秒, - std::chrono::seconds(1) ,这是因为根据 文档 to_time_t() 可能会舍入值而不是根据文档“如果 std::time_t 具有较低的精度,则该值是舍入还是截断是实现定义的”),因此我必须减去 1 秒才能使其截断时间。

在线尝试!

 #include <chrono>
#include <string>
#include <sstream>
#include <iomanip>

std::string FormatTime(std::chrono::system_clock::time_point tp) {
    std::stringstream ss;
    auto t = std::chrono::system_clock::to_time_t(tp);
    auto tp2 = std::chrono::system_clock::from_time_t(t);
    if (tp2 > tp)
        t = std::chrono::system_clock::to_time_t(tp - std::chrono::seconds(1));
    ss  << std::put_time(std::localtime(&t), "%Y-%m-%d %T")
        << "." << std::setfill('0') << std::setw(3)
        << (std::chrono::duration_cast<std::chrono::milliseconds>(
           tp.time_since_epoch()).count() % 1000);
    return ss.str();
}

std::string CurrentTimeStr() {
    return FormatTime(std::chrono::system_clock::now());
}

#include <iostream>

int main() {
    std::cout << CurrentTimeStr() << std::endl;
}

示例输出:

 2021-12-02 04:10:51.876


正如@AndyK 所 建议 的那样,从 C++20 开始,您可以使用 std::chrono::current_zone() 及其方法 to_local() ,它们返回 std::chrono::local_time 可以通过以下方式直接转换为您想要的字符串格式输出到 std::ostringstream 或通过 std::format() 。整个函数变得很短:

 #include <chrono>
#include <string>
#include <sstream>
#include <iostream>

std::string CurrentTimeStr() {
    return (std::ostringstream{} << std::chrono::current_zone()->to_local(
        std::chrono::system_clock::now())).str().substr(0, 23);
}

int main() {
    std::cout << CurrentTimeStr() << std::endl;
}

但是现在并不是所有的编译器都支持这个 current_zone() 函数,在线GodBolt服务器在trunk CLang和GCC上编译失败,但是MSVC编译得很好。虽然我的本地笔记本电脑安装的 CLang 也编译了它。

原文由 Arty 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题