Reputation: 55
i try to convert from struct tm, to std::time_t with the following sample code :
void test_time_t() {
tm time;
time.tm_year = 2004-1900;
time.tm_mon = 11;
time.tm_mday = 5;
time.tm_hour = 12;
time.tm_min = 2;
char buff[25];
strftime(buff, 20, "%Y %b %d %H:%M",&time);
printf("%s\n",buff);
auto t = std::mktime(&time);
struct tm *tmp = localtime(&t);
strftime(buff, 20, "%Y %b %d %H:%M",tmp);
printf("%s\n",buff);
}
this will output :
2004 Dec 05 12:02
2005 Jun 16 22:41
the date is changed, can anybody tell me what i do wrong here? i think timezone will not cause such different in date
Upvotes: 0
Views: 1140
Reputation: 117298
You need to initialize your time
:
tm time{}; // zero-initialized
"I just forget that
tm
is aC
struct."
That's common. You can however inherit std::tm
and use your own type in the code instead.
struct tm_ext : std::tm {
tm_ext() : std::tm{} {}; // zero initialize on default construction
};
You can now use tm_ext
without risking to miss the initialization:
tm_ext time; // now fine
While you're at it, you may even add some other convenience functions to it.
struct tm_ext : std::tm {
tm_ext() : std::tm{} {}; // zero initialize on default construction
explicit tm_ext(int year, int mon = 1, int mday = 1, int hour = 0,
int min = 0, int sec = 0, int isdst = 0) :
tm_ext() // delegate to default constructor
{
tm_year = year - 1900;
tm_mon = mon - 1;
tm_mday = mday;
tm_hour = hour;
tm_min = min;
tm_sec = sec;
// A negative value of tm_isdst causes mktime to attempt to determine if
// Daylight Saving Time was in effect.
tm_isdst = isdst;
errno = 0;
if(std::mktime(this) == -1 && errno != 0) {
throw std::runtime_error("mktime failed");
}
}
tm_ext(const std::tm& t) : std::tm(t) {} // conversion ctor
operator std::time_t () const { // implicit conversion to time_t
tm_ext copy(*this);
errno = 0;
return std::mktime(©);
}
// implicit conversion to a pointer - perhaps an exaggeration
operator const tm_ext* () const { return this; }
bool set_localtime(const std::time_t& t) {
std::tm* tmp = std::localtime(&t);
if(not tmp) return false;
*this = *tmp;
return true;
}
bool set_utc(const std::time_t& t) {
std::tm* tmp = std::gmtime(&t);
if(not tmp) return false;
*this = *tmp;
return true;
}
};
And using it:
void test_time_t() {
tm_ext time(2004, 12, 5, 12, 2); // use real world values
char buff[25];
// implicit conversion to a const tm_ext* below:
strftime(buff, 20, "%Y %b %d %H:%M", time);
printf("%s\n",buff);
std::time_t t = time; // implicit conversion from tm_ext to time_t
tm_ext tmp;
if(tmp.set_localtime(t)) std::cout << "successfully set localtime\n";
// implicit conversion to a const tm_ext* below:
strftime(buff, 20, "%Y %b %d %H:%M", tmp);
printf("%s\n",buff);
}
Before going overboard with this, one may want to take a look at Howard Hinnant's date.h
though.
Upvotes: 5