【问题标题】:Using Strftime to format DateTime使用 Strftime 格式化 DateTime
【发布时间】:2023-03-18 13:11:01
【问题描述】:

我正在研究将输入时间戳格式化为输入格式的函数。

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 不足以容纳内容。过去 3 周我才刚刚接触 C++,所以我对此没有太多了解。

【问题讨论】:

  • 不幸的是,strftime() 不像snprintf() 那样返回如果足够长的话将写入目标的字符数。您必须检查它的返回值并在需要时分配一个更大的字符串,然后重试并重复,直到它足够长。
  • C++20 将有 std::chrono::format()... 如果您使用的是最新的编译器,那可能已经可用。
  • 很遗憾我只能使用 C++14
  • 我可以检查format 字符串的长度,但我无法定义char date_string[format.length];

标签: c++ strftime


【解决方案1】:

strftime() 的包装器,它根据需要增长缓冲区,直到它大到足以容纳所需的时间字符串:

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

【讨论】:

  • 我不确定我听不懂。但在此先感谢。
  • @NguyễnĐứcTâm 关键是如果提供的目标缓冲区不足以容纳整个格式化字符串,strftime() 将返回 0。所以继续用越来越大的缓冲区调用它,直到它适合为止。 (我使用 10 的初始大小来证明必须增加它;根据评论,您可能希望从更大的数字开始)。
【解决方案2】:

不幸的是,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};
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 1970-01-01
    相关资源
    最近更新 更多