兩者差異對照
| 屬性 | time_t | DATE (double) |
| 基準點 | 1970-01-01 00:00:00 UTC | 1899-12-30 00:00:00 本地時間 |
| 單位 | 秒 (整數) | 天 (整數部) + 秒 (小數部) |
| 時區 | UTC | 本地時間 (需知時區才有意義) |
| 範圍 | 1970~2038 (32位) 或更廣 (64位) | 可表示基準點前負值 |
轉換公式 (含時區修正)
// time_t → DATE
inline double timet_to_date(time_t t) {
// 1970-01-01 到 1899-12-30 相差 25569 天
// timezone 為全域變數 (秒),標準庫提供,代表本地偏移 UTC
return static_cast(t + timezone) / (24.0 * 3600.0) + 25569.0;
}
// DATE → time_t
inline time_t date_to_timet(double dt) {
return static_cast((dt - 25569.0) * 86400.0 - timezone + 0.5); // +0.5 四捨五入
}
測試程式碼
#include <ctime>
#include <cassert>
#include <ATLComTime.h> // COleDateTime
int main() {
time_t now = time(nullptr);
COleDateTime ole(timet_to_date(now));
printf("UTC: %04d-%02d-%02d %02d:%02d:%02d\n",
ole.GetYear(), ole.GetMonth(), ole.GetDay(),
ole.GetHour(), ole.GetMinute(), ole.GetSecond());
time_t back = date_to_timet(ole.m_dt);
assert(back == now); // 往返一致
return 0;
}
補充:time_t ↔ SYSTEMTIME (Win32)
#include <windows.h>
#include <ctime>
inline SYSTEMTIME timet_to_systime(time_t t) {
tm local = *localtime(&t);
SYSTEMTIME st = {
1900 + local.tm_year, 1 + local.tm_mon, local.tm_wday, local.tm_mday,
local.tm_hour, local.tm_min, local.tm_sec, 0
};
return st;
}
inline time_t systime_to_timet(const SYSTEMTIME& st) {
tm gm = { st.wSecond, st.wMinute, st.wHour, st.wDay,
st.wMonth - 1, st.wYear - 1900, st.wDayOfWeek, 0, 0 };
return mktime(&gm);
}
注意事項
timezone、localtime、mktime 依賴進程當前時區設定 (TZ 環境變數 / 系統時區)。
- 跨時區/夏令時場景建議統一用 UTC (
time_t + gmtime/timegm) 存儲傳輸,顯示時再轉本地。
- C++20
<chrono> 提供 sys_time, zoned_time, format 完整替代方案,新專案優先使用。