英文:
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<time_point> parse_time( std::string date_string )
{
std::string_stream ss(date_string);
time_point retval;
if (!from_stream(ss, "%Y.%j", retval))
return std::nullopt;
return retval;
}
for time_t
we just then convert:
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;
}
Use:
if (auto time = parse_time_t( "1999.1" )) {
// *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::move
s 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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论