我想转换UTC日期&以年,月,日等数字给出的时间到time_t.有些系统为此目的提供mkgmtime或timegm等功能,但这不是标准功能,在我的Solaris系统上不存在.
到目前为止我找到的唯一解决方案是使用setenv将本地时区设置为UTC,然后调用mktime.但是,这种方法不是线程安全的,慢的,不可移植的,甚至会在我的系统上产生内存泄漏.
我也看到了尝试使用gmtime确定当前UTC偏移然后将其添加到mktime结果的方法.但据我所知,所有这些方法都有差距.毕竟,从本地时间到UTC的转换并不是唯一的.
您认为什么是最佳解决方案?
解决方法
我决定实现我自己的mkgmtime版本,它比我想象的要容易.
const int SecondsPerMinute = 60; const int SecondsPerHour = 3600; const int SecondsPerDay = 86400; const int DaysOfMonth[12] = {31,28,31,30,31}; bool IsLeapYear(short year) { if (year % 4 != 0) return false; if (year % 100 != 0) return true; return (year % 400) == 0; } time_t mkgmtime(short year,short month,short day,short hour,short minute,short second) { time_t secs = 0; for (short y = 1970; y < year; ++y) secs += (IsLeapYear(y)? 366: 365) * SecondsPerDay; for (short m = 1; m < month; ++m) { secs += DaysOfMonth[m - 1] * SecondsPerDay; if (m == 2 && IsLeapYear(year)) secs += SecondsPerDay; } secs += (day - 1) * SecondsPerDay; secs += hour * SecondsPerHour; secs += minute * SecondsPerMinute; secs += second; return secs; }
我主要担心的是mkgmtime必须与gmtime一致.这样gmtime(mktime(t))返回原始输入值.因此,我比较了time_t的0和MAX_INT之间61的所有倍数的结果,它们确实相等(至少在我的系统上).因此上述例程是正确的.
这个结果也意味着C库不会考虑闰秒,这本身就是一件坏事,但对我的目的有好处.这两个功能将长期保持一致.为了绝对确定,我使用此函数的Timestamp类总是快速检查程序启动并证明一些有意义的值的一致性.