C++中相同mktime()逻辑两种实现结果不符的问题
strptime与mktime转换时间戳时两种实现结果不一致
我用strptime()和mktime()把时间字符串转成long类型的Unix时间戳,两种实现逻辑完全一样,但结果却不同——方式1能得到正确时间戳,方式2返回-1。而且两种情况下打印的struct tm字段值看起来完全一致。
方式1(正常运行)
int main() { string time = "2023-03-02 00:00:00"; struct tm tm; strptime(time.c_str(), "%Y-%d-%m %H:%M:%S", &tm); //it is supposed to give you value decreased by 1900 so if it gives you 113 it means the year is 2013. Month will also be decreased by 1, i.e. if it gives you 1, it is actually February. Just add these values: //mktime expects the value given by strptime itslf. No need to do any modifications. time_t t = mktime(&tm); cout<<"tm_sec: "<<tm.tm_sec<<endl; cout<<"tm_min: "<<tm.tm_min<<endl; cout<<"tm_hour: "<<tm.tm_hour<<endl; cout<<"tm_mday: "<<tm.tm_mday<<endl; cout<<"tm_mon: "<<tm.tm_mon<<endl; cout<<"tm_year: "<<tm.tm_year<<endl; cout<<"tm_wday: "<<tm.tm_wday<<endl; cout<<"tm_yday: "<<tm.tm_yday<<endl; cout<<"tm_isdst: "<<tm.tm_isdst<<endl; cout<<t<<endl; return 0; }
运行结果:得到时间戳t=1675382400
方式2(返回-1)
time_t convert_datetime_string_to_long_time(string time) { //convert string time to long unix time struct tm tm; strptime(time.c_str(), "%Y-%d-%m %H:%M:%S", &tm); //it is supposed to give you value decreased by 1900 so if it gives you 113 it means the year is 2013. Month will also be decreased by 1, i.e. if it gives you 1, it is actually February. Just add these values: //mktime expects the value given by strptime itslf. No need to do any modifications. cout<<"tm_sec: "<<tm.tm_sec<<endl; cout<<"tm_min: "<<tm.tm_min<<endl; cout<<"tm_hour: "<<tm.tm_hour<<endl; cout<<"tm_mday: "<<tm.tm_mday<<endl; cout<<"tm_mon: "<<tm.tm_mon<<endl; cout<<"tm_year: "<<tm.tm_year<<endl; cout<<"tm_wday: "<<tm.tm_wday<<endl; cout<<"tm_yday: "<<tm.tm_yday<<endl; time_t t = mktime(&tm); return t; } int main() { time_t ans = convert_datetime_string_to_long_time("2023-03-02 00:00:00"); cout<<ans<<endl; return 0; }
运行结果:返回时间戳ans=-1
问题原因及解决方法
问题出在**struct tm未初始化**:
strptime()只会填充它能从时间字符串中解析到的字段(比如tm_sec、tm_min、tm_hour等),但不会处理其他未解析的字段(比如tm_isdst)。这些未被处理的字段会保留栈上的垃圾值。- 方式1中,栈上的
tm_isdst刚好是有效值,所以mktime()能正常工作;而方式2中,tm_isdst的垃圾值无效,导致mktime()无法解析时间,返回-1表示错误。 - 你没注意到这点是因为方式2没有打印
tm_isdst字段,看不到它的垃圾值。
解决方法:
在声明struct tm后,先初始化所有字段为0,或者显式设置tm_isdst为-1(让系统自动判断是否处于夏令时):
修改后的方式2代码
time_t convert_datetime_string_to_long_time(string time) { //convert string time to long unix time struct tm tm = {0}; // 初始化所有字段为0 strptime(time.c_str(), "%Y-%d-%m %H:%M:%S", &tm); cout<<"tm_sec: "<<tm.tm_sec<<endl; cout<<"tm_min: "<<tm.tm_min<<endl; cout<<"tm_hour: "<<tm.tm_hour<<endl; cout<<"tm_mday: "<<tm.tm_mday<<endl; cout<<"tm_mon: "<<tm.tm_mon<<endl; cout<<"tm_year: "<<tm.tm_year<<endl; cout<<"tm_wday: "<<tm.tm_wday<<endl; cout<<"tm_yday: "<<tm.tm_yday<<endl; cout<<"tm_isdst: "<<tm.tm_isdst<<endl; // 可添加打印验证 time_t t = mktime(&tm); return t; } int main() { time_t ans = convert_datetime_string_to_long_time("2023-03-02 00:00:00"); cout<<ans<<endl; return 0; }
也可以单独设置tm_isdst:
struct tm tm; memset(&tm, 0, sizeof(struct tm)); // 用memset初始化 // 或者 struct tm tm; tm.tm_isdst = -1; // 显式设置让系统自动判断夏令时
修改后,mktime()就能正确解析时间,返回正确的Unix时间戳。
内容的提问来源于stack exchange,提问作者10may
相关产品推荐
相关产品推荐

