英文:
C++ String to DateTime Functions
问题
来自C#的我对C++中的日期时间功能感到有些迷茫。我只是想将格式为2023-01-12T07:00:00+08:00的字符串转换为自2023年1月1日UTC以来的秒数。
以及反向操作,即将自2023年初以来的秒数整数转换为格式为"%Y-%m-%dT%H:%M:%S%z"的字符串。任何代码或指向正确方向的指针都将不胜感激。
已经尝试了使用chrono和time_t的各种选项,似乎可以工作:
std::time_t getTime(const std::string& dateTime) {
std::chrono::sys_time<std::chrono::seconds> tTime;
std::istringstream stream(dateTime);
std::chrono::from_stream(stream, "%Y-%m-%dT%H:%M:%S%z", tTime);
return std::chrono::system_clock::to_time_t(tTime);
}
const time_t EPOCH_2023 = getTime("2023-01-01T00:00:00+00:00");
int stringToIntTime(const std::string& dateTime) {
return static_cast<int>(getTime(dateTime) - EPOCH_2023);
}
要获取整数值。
但我对如何执行反向操作毫无头绪。
英文:
Coming from C# I'm a bit lost with the datetime functionality in C++. I am simply looking to convert from a string in the format 2023-01-12T07:00:00+08:00 to the number of seconds since 1-1-2023 UTC.
And the reverse, i.e. an int of the number of seconds since the start of 2023 to a string in the format "%Y-%m-%dT%H:%M:%S%z". Any code or pointers in the right direction would be greatly appreciated.
Have tried various options using chrono and time_t which seems to work:
std::time_t getTime(const std::string& dateTime) {
std::chrono::sys_time<std::chrono::seconds> tTime;
std::istringstream stream(dateTime);
std::chrono::from_stream(stream, "%Y-%m-%dT%H:%M:%S%z", tTime);
return std::chrono::system_clock::to_time_t(tTime);
}
const time_t EPOCH_2023 = getTime("2023-01-01T00:00:00+00:00");
int stringToIntTime(const std::string& dateTime) {
return static_cast<int>(getTime(dateTime) - EPOCH_2023);
}
to get the int.
But I haven't a clue on doing the reverse.
答案1
得分: 2
以下是我推荐的代码:
#include <chrono>
#include <format>
#include <iostream>
#include <sstream>
using namespace std::chrono_literals;
constexpr std::chrono::sys_seconds EPOCH_2023 = std::chrono::sys_days{2023y/01/01};
int stringToIntTime(const std::string& dateTime)
{
using namespace std;
using namespace std::chrono;
sys_seconds tTime;
istringstream stream(dateTime);
stream >> parse("%FT%T%Ez", tTime);
return (tTime - EPOCH_2023)/1s;
}
std::string intToStringTime(int i)
{
using namespace std;
using namespace std::chrono;
sys_seconds t = EPOCH_2023 + seconds{i};
return format("{:%FT%T%Ez}", zoned_time{"Etc/GMT-8", t});
}
int main()
{
using namespace std;
int i = stringToIntTime("2023-01-12T07:00:00+08:00");
string s = intToStringTime(i);
cout << i << '\n';
cout << s << '\n';
}
这段代码的输出应该是:
946800
2023-01-12T07:00:00+08:00
我已经对stringToIntTime
函数进行了一些简化:
-
你的
EPOCH_2023
常量可以更高效地存储为sys_seconds
类型,而不是字符串,并使其为constexpr
。在目标代码中,这将只是一个整数文字,表示从你的纪元到1970年01月01日的system_clock
纪元的秒数。 -
stringToIntTime
是正确的,但我将其简化为一个函数,并使用parse
代替from_stream
,以获得稍微更清晰的语法。parse
是一个稍微高级的API。 -
还要注意在格式化字符串中使用
%Ez
替代%z
。前者包括UTC偏移的小时和分钟之间的:
分隔符。 -
无需通过C API使用
time_t
。可以直接从解析的UTC时间tTime
中减去你的纪元。这将得到自你的纪元以来的秒数。要将其转换为int
,只需除以1秒。 -
intToStringTime
从将int
转换为秒开始,然后将其添加到你的纪元中。这会给t
一个sys_seconds
类型,具有自system_clock
纪元以来的秒数值。 -
最后,只需格式化
t
,使用具有 +08:00 UTC偏移的时区,并使用所需的格式。请注意在名称中使用-8
来获得 +8 的偏移量。这只是IANA继承的POSIX怪癖。如果需要其他时区,只需将其替换为"Etc/GMT-8"
。 -
注意使用
%T
,它是%H:%M:%S
的快捷方式,以及%F
,它是%Y-%m-%d
的快捷方式。
英文:
Here is what I recommend:
#include <chrono>
#include <format>
#include <iostream>
#include <sstream>
using namespace std::chrono_literals;
constexpr std::chrono::sys_seconds EPOCH_2023 = std::chrono::sys_days{2023y/01/01};
int
stringToIntTime(const std::string& dateTime)
{
using namespace std;
using namespace std::chrono;
sys_seconds tTime;
istringstream stream(dateTime);
stream >> parse("%FT%T%Ez", tTime);
return (tTime - EPOCH_2023)/1s;
}
std::string
intToStringTime(int i)
{
using namespace std;
using namespace std::chrono;
sys_seconds t = EPOCH_2023 + seconds{i};
return format("{:%FT%T%Ez}", zoned_time{"Etc/GMT-8", t});
}
int
main()
{
using namespace std;
int i = stringToIntTime("2023-01-12T07:00:00+08:00");
string s = intToStringTime(i);
cout << i << '\n';
cout << s << '\n';
}
Which should output:
946800
2023-01-12T07:00:00+08:00
I've taken the liberty of simplifying your stringToIntTime
somewhat:
-
Your
EPOCH_2023
constant can be made more efficient by storing it in asys_seconds
type as opposed to astring
, and making itconstexpr
. In the object code this will just be a integral literal which is the count of seconds between your epoch and thesystem_clock
epoch of 1970-01-01. -
stringToIntTime
is correct, but I've simplified it down to one function and usedparse
in place offrom_stream
just for slightly cleaner syntax.parse
is a slightly higher level API. -
Also note the use of
%Ez
in place of%z
. The former includes the:
separator between the hours and minutes of the UTC offset. -
There's no need to go through the C API with
time_t
. One can just subtract the parsed UTC timetTime
from your epoch. This results in seconds since your epoch. To convert that toint
, just divide by 1 second. -
intToStringTime
starts with converting theint
to seconds and adding that to your epoch. This givest
the typesys_seconds
and the value of atime_point
with seconds since thesystem_clock
epoch. -
Finally just format
t
, using a time zone with the +08:00 UTC offset, using the desired format. Note the use of -8 in the name to give +8 for the offset. This is simply POSIX weirdness that IANA inherits. If some other time zone is desired, just sub that in for"Etc/GMT-8"
. -
Note the use of
%T
which is a shortcut for%H:%M:%S
and%F
which is a shortcut for%Y-%m-%d
.
答案2
得分: 0
最好的方式可能是使用 sscanf_s(自 C11 起在 stdio.h 中可用)或 strptime(POSIX 标准)将字符串转换为单个值或 tm 类型(time.h)。然后,您可以使用 mktime(time.h)将其转换回 time_t 类型。然后只需将它们相减。 https://stackoverflow.com/questions/11213326/how-to-convert-a-string-variable-containing-time-to-time-t-type-in-c
英文:
The best way is probably to use sscanf_s (stdio.h since C11) or strptime (POSIX standard) to convert the string into either individual values or a tm type (time.h), respectively. From there you can use mktime (time.h) to get back a time_t type. Then just subtract them. https://stackoverflow.com/questions/11213326/how-to-convert-a-string-variable-containing-time-to-time-t-type-in-c
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论