Home > Back-end >  C String to DateTime Functions
C String to DateTime Functions

Time:01-09

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 a sys_seconds type as opposed to a string, and making it constexpr. In the object code this will just be a integral literal which is the count of seconds between your epoch and the system_clock epoch of 1970-01-01.

  • stringToIntTime is correct, but I've simplified it down to one function and used parse in place of from_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 time tTime from your epoch. This results in seconds since your epoch. To convert that to int, just divide by 1 second.

  • intToStringTime starts with converting the int to seconds and adding that to your epoch. This gives t the type sys_seconds and the value of a time_point with seconds since the system_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 ?

  •  Tags:  
  • c
  • Related