I\'m trying to convert a time info I reveive as a UTC string to a timestamp using std::mktime in C++. My problem is that in / &
Here is a simple, tested, hopefully portable piece of code converting from struct tm to seconds since the beginning of an adjustable UTC year, without temporary change of time zone.
// Conversion from UTC date to second, signed 64-bit adjustable epoch version.
// Written by François Grieu, 2015-07-21; public domain.
#include // needed for struct tm
#include // needed for int_least64_t
#define MY_EPOCH 1970 // epoch year, changeable
typedef int_least64_t my_time_t; // type for seconds since MY_EPOCH
// my_mktime converts from struct tm UTC to non-leap seconds since
// 00:00:00 on the first UTC day of year MY_EPOCH (adjustable).
// It works since 1582 (start of Gregorian calendar), assuming an
// apocryphal extension of Coordinated Universal Time, until some
// event (like celestial impact) deeply messes with Earth.
// It strive to be strictly C99-conformant.
//
// input: Pointer to a struct tm with field tm_year, tm_mon, tm_mday,
// tm_hour, tm_min, tm_sec set per mktime convention; thus
// - tm_year is year minus 1900;
// - tm_mon is [0..11] for January to December, but [-2..14]
// works for November of previous year to February of next year;
// - tm_mday, tm_hour, tm_min, tm_sec similarly can be offset to
// the full range [-32767 to 32767].
// output: Number of non-leap seconds since beginning of the first UTC
// day of year MY_EPOCH, as a signed at-least-64-bit integer.
// The input is not changed (in particular, fields tm_wday,
// tm_yday, and tm_isdst are unchanged and ignored).
my_time_t my_mktime(const struct tm * ptm) {
int m, y = ptm->tm_year+2000;
if ((m = ptm->tm_mon)<2) { m += 12; --y; }
// compute number of days within constant, assuming appropriate origin
#define MY_MKTIME(Y,M,D) ((my_time_t)Y*365+Y/4-Y/100*3/4+(M+2)*153/5+D)
return ((( MY_MKTIME( y , m, ptm->tm_mday)
-MY_MKTIME((MY_EPOCH+99), 12, 1 )
)*24+ptm->tm_hour)*60+ptm->tm_min)*60+ptm->tm_sec;
#undef MY_MKTIME // this macro is private
}
Key observations allowing great simplification compared to the code in this and that answers:
Here is another version not requiring 64-bit support, locked to 1970 origin.
// Conversion from UTC date to second, unsigned 32-bit Unix epoch version.
// Written by François Grieu, 2015-07-21; public domain.
#include // needed for struct tm
#include // needed for UINT_MAX
#if UINT_MAX>=0xFFFFFFFF // unsigned is at least 32-bit
typedef unsigned my_time_t; // type for seconds since 1970
#else
typedef unsigned long my_time_t; // type for seconds since 1970
#endif
// my_mktime converts from struct tm UTC to non-leap seconds since
// 00:00:00 on the first UTC day of year 1970 (fixed).
// It works from 1970 to 2105 inclusive. It strives to be compatible
// with C compilers supporting // comments and claiming C89 conformance.
//
// input: Pointer to a struct tm with field tm_year, tm_mon, tm_mday,
// tm_hour, tm_min, tm_sec set per mktime convention; thus
// - tm_year is year minus 1900
// - tm_mon is [0..11] for January to December, but [-2..14]
// works for November of previous year to February of next year
// - tm_mday, tm_hour, tm_min, tm_sec similarly can be offset to
// the full range [-32767 to 32768], as long as the combination
// with tm_year gives a result within years [1970..2105], and
// tm_year>0.
// output: Number of non-leap seconds since beginning of the first UTC
// day of year 1970, as an unsigned at-least-32-bit integer.
// The input is not changed (in particular, fields tm_wday,
// tm_yday, and tm_isdst are unchanged and ignored).
my_time_t my_mktime(const struct tm * ptm) {
int m, y = ptm->tm_year;
if ((m = ptm->tm_mon)<2) { m += 12; --y; }
return ((( (my_time_t)(y-69)*365u+y/4-y/100*3/4+(m+2)*153/5-446+
ptm->tm_mday)*24u+ptm->tm_hour)*60u+ptm->tm_min)*60u+ptm->tm_sec;
}