c++ 使用Strftime格式化DateTime

wfauudbj  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(218)

我正在编写一个函数来将输入时间戳格式化为输入格式。

std::string 1stformat = "dd - MM - yyyy HH 'Hours' mm 'Minutes' ss 'Seconds' SSS 'Miliseconds –' a '– Time Zone: ' Z '-' zzzz";//will not print anything
std::string 2ndformat = "'This took about' h 'minutes and' s 'seconds.'";//will print out

格式化后

char date_string[100];
strftime(date_string, 50, format.c_str(), curr_tm);

我的问题是,有时会有输入格式太长,这使得缓冲区date_string不足以容纳内容。我刚刚进入C++在过去的三个星期,所以我没有太多的前关于这一点。

vc9ivgsu

vc9ivgsu1#

strftime()的一个 Package 器,它根据需要增加缓冲区,直到它足够大以容纳所需的时间字符串:

#include <ctime>
#include <iostream>
#include <memory>
#include <string>

std::string safe_strftime(const char *fmt, const std::tm *t) {
  std::size_t len = 10; // Adjust initial length as desired. Maybe based on the length of fmt?
  auto buff = std::make_unique<char[]>(len);
  while (std::strftime(buff.get(), len, fmt, t) == 0) {
    len *= 2;
    buff = std::make_unique<char[]>(len);
  }
  return std::string{buff.get()};
}

int main() {
  std::time_t now;
  std::time(&now);
  std::cout << safe_strftime("The date is %Y-%m-%d", std::localtime(&now))
            << '\n';
  return 0;
}
z6psavjg

z6psavjg2#

不幸的是,std::strftime()的接口没有std::snprintf()的接口有用,因为如果缓冲区太小,它将返回0,而不是写入的字符数。我们需要逐步增加缓冲区大小并重试,可能像这样:

#include <ctime>
#include <string>
#include <vector>
    
std::string time_to_string(const char *format, const std::tm* time)
{
    // first try with an on-stack buffer (fast path)
    char buf[200];
    auto written = std::strftime(buf, sizeof buf, format, time);
    if (written > 0) {
        return buf;
    }

    // now, iterate with an allocated buffer
    auto len = sizeof buf;
    std::vector<char> v;
    do {
        v.resize(len *= 2);
        written = std::strftime(v.data(), v.size(), format, time);
    } while (written == 0);

    return {v.data(), written};
}

或者,我们可以使用std::put_time()来写入输出流,而不是std::strftime(),这将根据需要扩展其存储:

#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>

std::string time_to_string(const char *format, const std::tm* time)
{
    std::ostringstream os;
    os << std::put_time(time, format);
    return os.str();
}

除了更简单之外,C++的方法还允许我们使用特定的(非默认的)区域设置来编写,方法是在流式传输日期之前添加对os.imbue()的调用。

相关问题