C++转C#:tm结构体与mktime()时间转换结果不一致问题排查
问题原因与解决方案
核心问题分析
两个结果差值为28800秒(8小时),结合代码细节,问题出在两个地方:
C++代码的
tm_year赋值错误
C的tm结构体中,tm_year字段存储的是年份减去1900,而非直接存储年份值。你当前代码中sampleTime.tm_year = year;会将年份设置为1900+2022=3922,这显然和预期的2022年不符——你提供的C结果是正常2022年的时间戳,说明这是笔误,正确写法应为sampleTime.tm_year = year - 1900;。时区处理不一致
- C++的
mktime()函数会将tm结构体中的时间视为本地时区时间,然后转换为UTC标准的Unix时间戳(从1970-01-01 00:00:00 UTC开始的秒数)。 - 你的C#代码中,
new DateTime(year, month, day, hour, minute, second)默认创建的是DateTimeKind.Unspecified类型的时间,计算与unixEpoch(同样是Unspecified)的差值时,相当于把两个时间都当作同一本地时区的时间,而非基于UTC计算,导致时区偏移差(比如东8区会差8小时)。
- C++的
修正后的等效代码
方案一:保持与C++一致的本地时区转UTC逻辑
C++修正代码:
struct tm sampleTime; time_t longTime; // 修正tm_year赋值 sampleTime.tm_year = year - 1900; sampleTime.tm_mon = month - 1; sampleTime.tm_mday = day; sampleTime.tm_hour = hour; sampleTime.tm_min = minute; sampleTime.tm_sec = second; // mktime会自动计算tm_wday和tm_yday,无需手动设置 sampleTime.tm_isdst= 0; longTime = mktime(&sampleTime); // 修正变量名:&sampleTime而非&thistime
C#对应代码:
int year = 2022; int month = 9; int day = 5; int hour = 0; int minute = 27; int second = 20; // 明确指定为本地时间 DateTime sampleTime = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Local); // 明确指定Unix纪元为UTC时间 DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // 转换为UTC后计算时间戳 ulong longTime = (ulong)(sampleTime.ToUniversalTime() - unixEpoch).TotalSeconds;
方案二:统一使用UTC时间处理(无需时区转换)
如果希望直接基于UTC时间计算,可使用以下代码:
C++代码(使用timegm替代mktime,timegm将tm视为UTC时间):
struct tm sampleTime; time_t longTime; sampleTime.tm_year = year - 1900; sampleTime.tm_mon = month - 1; sampleTime.tm_mday = day; sampleTime.tm_hour = hour; sampleTime.tm_min = minute; sampleTime.tm_sec = second; sampleTime.tm_isdst= 0; longTime = timegm(&sampleTime); // timegm不依赖本地时区,直接处理UTC时间
C#对应代码:
int year = 2022; int month = 9; int day = 5; int hour = 0; int minute = 27; int second = 20; // 明确指定为UTC时间 DateTime sampleTime = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc); DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); ulong longTime = (ulong)(sampleTime - unixEpoch).TotalSeconds;
内容的提问来源于stack exchange,提问作者pfinferno
相关产品推荐
相关产品推荐

