As I said in my comment, all your output is wrong. It seems that it is a bug in clang. I searched on the Bugzilla page of the LLVM project but found nothing. Maybe you want to submit the bug report with your example code.
A workaround is to parse the string manually with std::sscanf()
and fill the std::tm
struct. The following code does that for your input string i
. See the whole example with the output of std::get_time()
and the std::sscanf()
method at ideone. If the string is different then adapt that solution to your needs.
This solution is using %d:%d:%d %d:%d:%d
as format string. You could also use %4d:%2d:%2d %2d:%2d:%2d
which would accept only numbers which have length smaller or equal than the number between %
and d
.
Output:
2016:07:30 09:27:06 | sscanf() time = 1469870826
2016:07:30 09:27:06 | std::get_time() time = 1469870826
2016:07:30 09:27:07 | sscanf() time = 1469870827
2016:07:30 09:27:07 | std::get_time() time = 1469870827
2016:07:30 09:27:08 | sscanf() time = 1469870828
2016:07:30 09:27:08 | std::get_time() time = 1469870828
Code:
#include <vector>
#include <string>
#include <iostream>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <cstring>
int main()
{
std::vector<std::string> vec;
vec.push_back("2016:07:30 09:27:06");
vec.push_back("2016:07:30 09:27:07");
vec.push_back("2016:07:30 09:27:08");
for (auto & i : vec)
{
struct std::tm tm;
/* std::sscanf() method: */
std::memset(&tm, 0, sizeof(tm));
if (6 != std::sscanf(i.c_str(), "%d:%d:%d %d:%d:%d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec))
{
return -1;
}
/* correct the numbers according to:
* see: http://en.cppreference.com/w/cpp/chrono/c/tm */
--tm.tm_mon;
tm.tm_year -= 1900;
/* mktime determines if Daylight Saving Time was in effect
* see: http://en.cppreference.com/w/cpp/chrono/c/mktime */
tm.tm_isdst = -1;
std::time_t time = std::mktime(&tm);
std::cout << i << " | sscanf() time = " << time << std::endl;
/************************************************************/
/* std::get_time() method: */
std::istringstream iss;
iss.str(i);
iss >> std::get_time(&tm, "%Y:%m:%d %H:%M:%S");
time = std::mktime(&tm);
std::cout << i << " | std::get_time() time = " << time << std::endl;
}
}
It is necessary to subtract one of the tm_mon
because it begins at 0. Further the tm_year
member are years since 1900. See the description of std::tm
here.
Further it is needed to set tm_isdst
to -1 to let std::mktime()
determine if the Daylight Saving Time was in effect.
To convert the std::time_t
Linux timestamp back to a std::string
of your given format: %Y:%m:%d %H:%M:%S
you can use std::strftime()
with std::localtime(). See live example on ideone.
Output:
time = 1469870826 | 2016:07:30 09:27:06
Code:
#include <vector>
#include <string>
#include <iostream>
#include <ctime>
int main()
{
char buff[20];
time_t timestamp = 1469870826;
std::strftime(buff, sizeof(buff), "%Y:%m:%d %H:%M:%S", std::localtime(×tamp));
std::string timeStr(buff);
std::cout << "time = " << timestamp << " | " << timeStr;
}
std::get_time()
is buggy? – Holt$ Apple LLVM version 8.1.0 (clang-802.0.42) $ Target: x86_64-apple-darwin16.7.0
, not sure if I can update. – Manyplies