C++问题:从字符串到time_t对象?

huangapple go评论142阅读模式
英文:

C++ Question: From string to time_t object?

问题

我正在编写一个程序,用于从命令行或文件中获取格式为:
9999.365 --> Fri 31 Dec 9999
的输入。输出需要看起来像示例中的第二部分。我在理解如何将格式为xxxx.xxx的字符串转换为表示值的正确time_t对象方面遇到了困难。有人有关于这个的建议吗?

我尝试过查找如何实现这一点,但我的C++知识有限,而且我对这门语言非常陌生,因此我找到的许多信息似乎不起作用,或者我只是不理解它。

英文:

I have a program I'm writing to take inputs from the command line or a file with the format:
9999.365 --> Fri 31 Dec 9999
Where the output needs to look like the second part of that example. I'm having trouble understanding how to go about taking a string formatted like xxxx.xxx and converting it to a proper time_t object representing a value. Anyone have advice for this?

I've tried looking up how to do so, but my C++ knowledge is not wide and I'm very new to the language so much of what I've found doesn't appear to work or I just don't understand it.

答案1

得分: 1

你可以简单地使用std::chrono中的流解析工具

using time_point = std::chrono::system_clock::time_point;
std::optional<time_point> parse_time(std::string date_string)
{
  std::stringstream ss(date_string);
  time_point retval;
  if (!from_stream(ss, "%Y.%j", retval))
    return std::nullopt;
  return retval;
}

对于time_t,我们可以进行转换:

std::optional<time_t> parse_time_t(std::string date_string)
{
  if (auto time = parse_time(date_string))
    return std::chrono::system_clock::to_time_t(*time);
  return std::nullopt;
}

使用方法:

if (auto time = parse_time_t("1999.1")) {
  // *time 现在是1999年1月1日
} else {
  // 解析失败
}

如果你不是在每像素帧的基础上执行此操作(或类似操作),你可以尝试通过编写自己的解析器来提高性能,因为基于流的C++不是很快,但如果不是在每像素帧的基础上执行此操作,我不会费心。(即,获取一个字符串,以.分割它,检查是否有2个部分,将第一个部分转换为年份,创建一个时间点,添加日期等)。

添加一些std::move可能会是微小的优化。转换为std::string_view也可能改善性能,但基于流的std::string_view解析是C++23的功能。

我不建议使用time_t,除非你需要与C库或类似的内容进行互操作。C++的std::chrono时间原语在设计上不那么古老;存在许多难以通过std::chrono生成但使用time_t很容易触发的错误。

英文:

You could simply use the stream parsing utilities in std::chrono.

using time_point = std::chrono::system_clock::time_point;
std::optional&lt;time_point&gt; parse_time( std::string date_string )
{
  std::string_stream ss(date_string);
  time_point retval;
  if (!from_stream(ss, &quot;%Y.%j&quot;, retval))
    return std::nullopt;
  return retval;
}

for time_t we just then convert:

std::optional&lt;time_t&gt; parse_time_t( std::string date_string ) {
  if (auto time = parse_time(date_string))
    return std::chrono::system_clock::to_time_t(*time);
  return std::nullopt;
}

Use:

if (auto time = parse_time_t( &quot;1999.1&quot; )) {
  // *time is now jan 1, 1999
} else {
  // parse failed
}

you could probably make this faster by rolling your own parser, as stream-based C++ isn't all that super fast, but if you aren't doing this on a per-pixel*frame basis (or similar) I wouldn't bother. (Ie, take a string, split it on ., and check there are 2 parts, convert the first to a year, make a time point, add on the day, etc).

Adding some std::moves would be microoptimizations. Moving over to a std::string_view might also improve things, but stream-based parsing of std::string_view is C++23.

I'd discourage use of time_t unless you need it for interop with C libraries or the like. C++'s std::chrono time primitives are far less ancient in design; there are a pile of bugs that are difficult to generate with std::chrono but are trivial to hit with time_t.

huangapple
  • 本文由 发表于 2023年3月7日 22:20:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663184.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定