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.
CodePudding user response:
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
.
CodePudding user response:
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. How to convert a string variable containing time to time_t type in c ?