Reputation: 19694
Is there a C/C++/STL/Boost clean method to convert a date time string to epoch time (in seconds)?
yyyy-mm-dd hh:mm:ss
Upvotes: 11
Views: 13612
Reputation: 218700
In C++20 (over a decade since the question was asked :-) ), this can more easily be done with std::chrono::parse
.
The question can be interpreted in a couple of ways:
Is the yyyy-mm-dd hh:mm:ss string:
In C++20, whatever the timezone the string represents, it can be correctly handled.
#include <chrono>
#include <cstdint>
#include <iostream>
#include <sstream>
#include <string>
std::int64_t
convert_utc(std::string s)
{
std::istringstream in{std::move(s)};
in.exceptions(std::ios::failbit);
std::chrono::sys_seconds tp;
in >> std::chrono::parse("%F %T", tp);
return tp.time_since_epoch().count();
}
sys_seconds
is a type-alias for a seconds-precision chrono::time_point
based on system_clock
. This can be parsed into using parse
in a wide variety of formats. Finally the underlying integral count is extracted from the time_point
and returned.
std::int64_t
convert_local(std::string s)
{
std::istringstream in{std::move(s)};
in.exceptions(std::ios::failbit);
std::chrono::local_seconds tp;
in >> std::chrono::parse("%F %T", tp);
auto tz = std::chrono::current_zone();
return tz->to_sys(tp).time_since_epoch().count();
}
The code is similar if the string represents the computer's local time zone. The main difference is to parse into a local_seconds
instead of a sys_seconds
, and then use the current local time zone to convert the local_time
to a sys_time
.
std::int64_t
convert_LA(std::string s)
{
std::istringstream in{std::move(s)};
in.exceptions(std::ios::failbit);
std::chrono::local_seconds tp;
in >> std::chrono::parse("%F %T", tp);
auto tz = std::chrono::locate_zone("America/Los_Angeles");
return tz->to_sys(tp).time_since_epoch().count();
}
Or you can choose any other IANA time zone to do the conversion from local_seconds
to sys_seconds
.
Upvotes: 0
Reputation:
On Windows platform you can do something like this if don't want to use Boost:
// parsing string
SYSTEMTIME stime = { 0 };
sscanf(timeString, "%04d-%02d-%02d %02d:%02d:%02d",
&stime.wYear, &stime.wMonth, &stime.wDay,
&stime.wHour, &stime.wMinute, &stime.wSecond);
// converting to utc file time
FILETIME lftime, ftime;
SystemTimeToFileTime(&stime, &lftime);
LocalFileTimeToFileTime(&lftime, &ftime);
// calculating seconds elapsed since 01/01/1601
// you can write similiar code to get time elapsed from other date
ULONGLONG elapsed = *(ULONGLONG*)&ftime / 10000000ull;
If you prefer standard library, you can use struct tm and mktime() to do the same job.
Upvotes: 3
Reputation: 8001
See: Date/time conversion: string representation to time_t
And: [Boost-users] [date_time] So how come there isn't a to_time_t helper func?
So, apparently something like this should work:
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
std::string ts("2002-01-20 23:59:59");
ptime t(time_from_string(ts));
ptime start(gregorian::date(1970,1,1));
time_duration dur = t - start;
time_t epoch = dur.total_seconds();
But I don't think it's much cleaner than Rob's suggestion: use sscanf
to parse the data into a struct tm
and then call mktime
.
Upvotes: 11
Reputation: 6089
http://www.boost.org/doc/libs/1_39_0/doc/html/date_time.html Should do the trick.
Upvotes: 1