【问题标题】:Easiest way to print timestamp to ostream将时间戳打印到 ostream 的最简单方法
【发布时间】:2020-05-10 00:56:41
【问题描述】:

我想为 std::cout / std::cerr ostreams 的某些输出添加时间戳,而不使用修改后的标准流,如下所示:

std::cerr << timestamp << "Warning!\n";

左右:

std::cerr << timestamp() << "Warning!\n";

输出应如下所示:

[2020-01-23 17:40:15 CET] Warning!

但我真的对自己的想法不满意:

class TimeStamp {};

std::ostream &operator<<(std::ostream &stream, const TimeStamp &ts) 
{
    std::time_t t = std::time(nullptr);
    stream << "[" << std::put_time(std::localtime(&t), "%F %T %Z") << "] ";
    return stream;
}

TimeStamp ts;

int main()
{
    std::cerr << ts << "Warning!\n";
    std::cerr << ts << "Another warning!\n";
}

所以我基本上定义了一个空类,使用全局声明并重载“

【问题讨论】:

  • 使用无非是标签的类型让operator&lt;&lt; 做一些特别的事情一点都没错。你看有什么缺点吗?为什么你认为它是错误的?
  • 我同意这是一个非常聪明的解决您的问题的方法。只需标记ts constexpr

标签: c++ timestamp operator-overloading ostream


【解决方案1】:

你的做法没有错。但如果您正在寻找替代品,您可以创建一个 ostream 包装器:

class Logger {
  private:
    std::ostream &stream;

    void print_time() {
        std::time_t t = std::time(nullptr);
        stream << "[" << std::put_time(std::localtime(&t), "%F %T %Z") << "] ";
    }
  public:
    //Maybe also take options for how to log?
    Logger(std::ostream &stream) : stream(stream) { }

    template <typename T>
    std::ostream &operator<<(const T &thing)  {
        print_time();
        return stream << thing;
    }
};

int main()
{
    Logger log(std::cerr);
    log << "Warning!" << std::endl;
    log << "Another warning!" << std::endl;
}

在这里运行:https://ideone.com/YRawuQ

【讨论】:

  • 非常快,谢谢!这确实很有用,我不知道我可以这么容易地创建一个包装器。我最终使用了一些东西的组合,我已经将我的 TimeStamp 类更改为一个更有用的带有标签等的 Message 类,因此使用 friend ... operator&lt;&lt; 再次变得更有意义。但是像你建议的那样使用ostream 包装器可能是可行的方法,它看起来真的很方便。
【解决方案2】:

您可以使用日期和时间库中的标准std::chrono::time_point 类来表示时间戳。然后,您需要将该时间戳转换为std::time_t 类型,并最终将日期和时间信息从给定的日历时间转换为根据格式字符串的字符串。

auto const now = std::chrono::system_clock::now();
auto now_time = std::chrono::system_clock::to_time_t(now);
std::cout << std::put_time(std::localtime(&now_time), "%F %T") << std::endl;

对于那些想了解更多的人......

您可以使用source_location 类来表示有关源代码的某些信息,例如文件名、行号和函数名。它正在合并到 ISO C++ 中并可供使用。

完整代码

#include <ctime>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <string_view>
#include <experimental/source_location>

void error(std::string_view const& message,
           std::ostream& os = std::cout,
           std::experimental::source_location const& location = std::experimental::source_location::current()) {
    auto const now = std::chrono::system_clock::now();
    auto now_time = std::chrono::system_clock::to_time_t(now);
    os << "[" << std::put_time(std::localtime(&now_time), "%F %T") << "] "
       << "[INFO] "
       << location.file_name() << ":"
       << location.line() << " "
       << message << '\n';
}

void info(std::string_view const& message,
          std::ostream& os = std::cout,
          std::experimental::source_location const& location = std::experimental::source_location::current()) {
    auto const now = std::chrono::system_clock::now();
    auto now_time = std::chrono::system_clock::to_time_t(now);
    os << "[" << std::put_time(std::localtime(&now_time), "%F %T") << "] "
       << "[INFO] "
       << location.file_name() << ":"
       << location.line() << " "
       << message << '\n';
}

int main() {
    error("Some error");
    info("Some info");

    // or

    error("Some error 2", std::cerr);
    info("Some info 2", std::cerr);

    return 0;
}

看看live

【讨论】:

  • 打印文件和行的要求从何而来?
  • 我的意思是这没有错,但是您使用 &lt;chrono&gt; 的好建议隐藏在与问题没有明显关系的内容后面
  • 你是对的...我只是想给 OP 比他要求的多一点和另一种观点...我将尝试突出与问题相关的内容
  • 我建议将流作为这些函数的参数(可能默认为 std::cerr / std::cout)。硬编码 std::cout 有时会让人头疼
  • @foreknownas_463035818 答案已更新。 tnx 寻求指导
【解决方案3】:

如果您只是在寻找我从“像 timestamp() 这样的静态函数”中理解的独立函数,您可以将日期作为字符串返回:

std::string timeStamp(){
    std::ostringstream strStream;
    std::time_t t = std::time(nullptr);
    strStream<< "[" << std::put_time(std::localtime(&t), "%F %T %Z") << "] ";
    return strStream.str();
}


int main(){
    std::cout<<timeStamp()<<" Testing!";   
    return 0;
}

记得添加流

【讨论】:

  • 这很快,谢谢!是的,我想std::ostringstream 是我在我的问题中真正想要的。我以前用过std::strftime,但是它需要一个C风格的字符串,并带来了一些其他的问题。再次感谢您!
  • 感谢使用 ostringstream 而不是 stringstream 直接。小事,但通过选择所需的确切类型,您可以更清楚地表达操作意图
猜你喜欢
  • 2012-03-01
  • 1970-01-01
  • 2015-02-07
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多