Самый простой способ напечатать метку времени в ostream - PullRequest
4 голосов
/ 23 января 2020

Я бы хотел добавить временную метку к определенным выходным данным в ostreams std :: cout / std :: cerr, без использования модифицированных стандартных потоков, например:

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

Так что я Я в основном определяю пустой класс, используя глобальное объявление и перегружая оператор <<. Это неправильно. Возможно, лучше подойдет функция stati c, такая как timestamp (), но я не совсем уверен, как это сделать go. Во всех примерах, которые я нашел в Интернете, использовался перегруженный оператор «<<», но обычно это имело больше смысла, поскольку выводилось некоторое состояние класса. Могу ли я локально создать ostream и вернуть его в функцию? </p>

Ответы [ 3 ]

3 голосов
/ 23 января 2020

Если вы просто ищете автономную функцию, которую я понял из «stati c function 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;
}

Не забудьте включить sstream

3 голосов
/ 23 января 2020

Нет ничего плохого в том, как ты это сделал. Но если вы ищете альтернативы, вы можете создать 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

2 голосов
/ 23 января 2020

Вы можете использовать стандартный 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

...