時間處理是系統程式常見需求,標準庫提供 <time.h> 核心函數,但涉及執行緒安全、時區、儲存期等易踩坑細節。
#include <time.h>
struct tm *localtime(const time_t *timer);
time_t (自 1970-01-01 UTC 秒數)。struct tm * (年/月/日/時/分/秒/星期/儒略日/夏令時)。localtime_r (POSIX) / localtime_s (C11 Annex K),需自備 struct tm 緩衝區。time_t mktime(struct tm *tmptr);
tm 視為本地時間,自動修正欄位 (如 tm_sec=60 進位)。time_t,-1 表示錯誤。tm_wday, tm_yday, 修正越界值)。double difftime(time_t time1, time_t time0);
time1 - time0 的雙精度秒數差。time_t 減法方式 (標準未保證 time_t 為算術型別)。| 陷阱 | 後果 | 解決方案 |
|---|---|---|
| 直接使用 localtime 返回指標 | 多執行緒/後續呼叫資料競爭 | 立即複製 tm 結構,或用 localtime_r |
| 假設 time_t 為有符號長整數 | 部分平台為無符號/64位/結構體 | 僅透過 difftime/mktime 操作 |
| 忽略夏令時 (tm_isdst) | 時間轉換偏移 1 小時 | 設定 tm_isdst=-1 讓 mktime 自動判斷 |
| 跨平台格式化輸出 | strftime 格式字串差異 | 用標準 %Y-%m-%d %H:%M:%S |
#include <time.h>
#include <stdio.h>
int main() {
time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now); // 執行緒安全
// 加 30 天
tm_now.tm_mday += 30;
time_t future = mktime(&tm_now); // 自動修正月份/年份
double diff = difftime(future, now);
printf("30 天后: %.0f 秒 (%.1f 天)\n", diff, diff/86400);
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm_now);
printf("未來日期: %s\n", buf);
return 0;
}