Convert date to unix time stamp in c++

2020-06-21 09:09发布

问题:

As some websites that convert those unix time stamps say, the stamp of

2013/05/07 05:01:00 (yyyy/mm/dd, hh:mm:ss) is 1367902860.

The way I do it in C++, the stamp differs from the date. Here is the code:

time_t rawtime;
struct tm * timeinfo;

int year=2013, month=5, day=7, hour = 5, min = 1, sec = 0;

/* get current timeinfo: */
time ( &rawtime ); //or: rawtime = time(0);
/* convert to struct: */
timeinfo = localtime ( &rawtime ); 

/* now modify the timeinfo to the given date: */
timeinfo->tm_year   = year - 1900;
timeinfo->tm_mon    = month - 1;    //months since January - [0,11]
timeinfo->tm_mday   = day;          //day of the month - [1,31] 
timeinfo->tm_hour   = hour;         //hours since midnight - [0,23]
timeinfo->tm_min    = min;          //minutes after the hour - [0,59]
timeinfo->tm_sec    = sec;          //seconds after the minute - [0,59]

/* call mktime: create unix time stamp from timeinfo struct */
date = mktime ( timeinfo );

printf ("Until the given date, since 1970/01/01 %i seconds have passed.\n", date);

The resulting time stamp is

1367899260, but not 1367902860.

What is the problem here? Even if I change to hour-1 or hour+1, it does not match. EDIT: Well yes if i add 1 to hour, it works. previously also added 1 to minutes.

回答1:

You must use timegm() instead of mktime(), and that's all. Because mktime is for localtime and timegm for UTC/GMT time.

Converting Between Local Times and GMT/UTC in C/C++



回答2:

Do you have daylight saving time when you are from? The tm::tm_isdst parameter is a flag for daylight saving time. This will get filled by the localtime call based on where you are and the time of year and you do not reset it. So even if both you and the web page are using the same time, if you have the daylight saving flag set and the web page doesn't then you will end up different by 1 hour.

Note you don't really need the localtime call. You can just fill in all the parts manually because tm::tm_wday and tm::tm_yday are ignored by mktime. Check out http://www.cplusplus.com/reference/ctime/tm/ and http://www.cplusplus.com/reference/ctime/mktime/



回答3:

Don't use a pointer to localtime. Save the actual value

struct tm timeinfo;
...
timeinfo = *localtime(&rawtime);
...
date = mktime(&timeinfo);

You don't know what else may be using the pointer that localtime is returning. mktime might possibly be using it.



回答4:

It looks like the website is assuming the time is in the UTC timezone, and your computer is set to some other timezone.

You can call gmtime rather than localtime to use UTC for that; but I've just noticed that you're not actually using localtime to do anything except get a pointer to a tm. You'd be better off declaring a local tm; the one used by localtime could be reused whenever you call another time library function.

Unfortunately, there's no standard variation of mktime using UTC. If you want UTC, your options are:

  • Set the timezone using setenv("TZ", "", 1);. Note that this affects the whole program, so can be awkward if you also need to deal with local time.
  • Use a library like Boost.DateTime, which is slightly better at handling dates and timezones than the C library.


回答5:

mktime() converts local calendar time to a time since epoch as a time_t object, so your result will be different from the website's if you are in a different time-zone. The website takes 2013/05/07 05:01:00 as a UTC time. The same code on my machine has a result of 1367874060, which is 8 hour away from the website's value. I'm in UTC+8:00 time-zone, so mktime() on my machine takes the input 2013/05/07 05:01:00 as a UTC+8:00 time, thus causing the difference.

PS: localtime() returns a pointer to a static internal struct tm object. The structure may be shared between gmtime(), localtime(), and ctime(), and may be overwritten on each invocation. So it's a better practice to have your own local copy of a struct tm object.