如何用C/C++/Win32 API将1904纪元秒数转换为日期时间?
1904纪元秒数转格式化时间/struct tm 的实现方法
好问题!其实C/C++标准库或者Win32 API里并没有直接提供从1904纪元秒数转换的函数,但我们可以通过计算固定纪元偏移量来轻松实现这个需求——毕竟1904年1月1日午夜(UTC)到1970年1月1日午夜(UTC)的时间差是固定值。
核心思路:计算纪元偏移量
首先我们需要确定两个纪元之间的总秒数差:
从1904到1970共66年,其中包含17个闰年(1904、1908...1968),总天数为 66*365 +17 = 24107 天,换算成秒数就是:24107 * 24 * 3600 = 2082844800 秒
这个值就是我们需要的偏移量——把1904纪元的秒数减去这个值,就能得到标准的Unix时间戳(1970纪元秒数),之后就可以用常规函数处理了。
方法一:使用C/C++标准库
步骤:
- 将1904纪元秒数转换为Unix时间戳(
time_t) - 用
localtime/gmtime转换为struct tm - 用
strftime格式化输出目标字符串
代码示例:
#include <ctime> #include <cstdint> #include <cstdio> int main() { // 1904纪元到1970纪元的秒数偏移量 const uint64_t SECONDS_1904_TO_1970 = 2082844800ULL; // 示例:1904-01-01 00:00:00 的秒数(值为0) uint64_t epoch1904_sec = 0; // 转换为Unix时间戳(注意处理溢出:如果epoch1904_sec < 偏移量,说明是1904之前的时间,需额外处理) if (epoch1904_sec < SECONDS_1904_TO_1970) { fprintf(stderr, "Error: Time is before 1904-01-01 UTC\n"); return 1; } time_t unix_time = static_cast<time_t>(epoch1904_sec - SECONDS_1904_TO_1970); // 转换为本地时间的struct tm(用gmtime则得到UTC时间) struct tm* time_info = localtime(&unix_time); if (!time_info) { fprintf(stderr, "Error converting time\n"); return 1; } // 格式化为"hh:mm:ss MM. dd, yyyy"(%H是24小时制,%I是12小时制,按需选择) char time_str[100]; strftime(time_str, sizeof(time_str), "%H:%M:%S %m. %d, %Y", time_info); printf("Formatted time: %s\n", time_str); return 0; }
方法二:使用Win32 API
如果是Windows平台,也可以用Win32的时间函数来处理,核心是把1904纪元秒数转换为FILETIME(Win32的时间格式,以1601年为纪元,100纳秒为单位),再转成SYSTEMTIME或直接格式化。
代码示例:
#include <windows.h> #include <cstdint> #include <cstdio> int main() { // 1904纪元到1601纪元的100纳秒单位偏移量 const uint64_t TICKS_1904_TO_1601 = 95620744000000000ULL; const uint64_t SEC_TO_TICKS = 10000000ULL; // 1秒=10^7个100纳秒 // 示例:1904-01-01 00:00:00 的秒数 uint64_t epoch1904_sec = 0; // 转换为FILETIME的100纳秒计数 uint64_t filetime_ticks = TICKS_1904_TO_1601 + (epoch1904_sec * SEC_TO_TICKS); FILETIME ft; ft.dwLowDateTime = static_cast<DWORD>(filetime_ticks & 0xFFFFFFFF); ft.dwHighDateTime = static_cast<DWORD>(filetime_ticks >> 32); // 转换为SYSTEMTIME(本地时间,若要UTC用FileTimeToSystemTime直接转) SYSTEMTIME st; if (!FileTimeToSystemTime(&ft, &st)) { fprintf(stderr, "FileTimeToSystemTime failed\n"); return 1; } // 手动格式化或用Win32的GetDateFormat/GetTimeFormat char time_str[100]; sprintf(time_str, "%02d:%02d:%02d %02d. %02d, %04d", st.wHour, st.wMinute, st.wSecond, st.wMonth, st.wDay, st.wYear); printf("Formatted time: %s\n", time_str); return 0; }
注意事项
- 溢出问题:如果你的1904纪元秒数是32位整数,它只能表示到2036年左右(因为2^32秒约等于136年),建议用64位整数(
uint64_t)来存储和计算,避免溢出。 - 时区差异:
localtime和FileTimeToSystemTime默认转换为本地时区时间,如果需要UTC时间,改用gmtime(标准库)或直接使用FileTimeToSystemTime(因为FILETIME本身是UTC的)。
内容的提问来源于stack exchange,提问作者ravin.wang
相关产品推荐
相关产品推荐

