将时间戳打印到 ostream 的最简单方法

Easiest way to print timestamp to ostream

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

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

所以我基本上定义了一个空 class,使用全局声明并重载“<<”运算符。这感觉不对。像 timestamp() 这样的静态函数可能更适合,但我不太确定如何继续这样做。我在网上找到的所有示例都使用了重载的 '<<' 运算符,但这样做通常更有意义,因为输出了一些 class 状态。我可以在函数中本地创建一个 ostream 和 return 吗?

你做这件事的方式没有错。但是如果你正在寻找替代品,你可以创建一个 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

您可以使用日期和时间库中的标准 std::chrono::time_point class 来表示时间戳。然后,您需要将该时间戳转换为 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 class 表示有关源代码的某些信息,例如文件名、行号和函数名。它正在合并到 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

如果你只是在寻找一个独立的函数,这是我从 "static function like timestamp()" 中了解到的,你可以 return 日期作为字符串:

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

记得包含 sstream