首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 標準庫高效獲取本地時間:tm 結構體與 localtime 實戰

     編輯:關於C

前言:為什麼選擇 C 標準庫時間函式

在效能敏感、跨平台或嵌入式場景,C 標準庫 <time.h> 提供的 time()、localtime()、struct tm 組合,較 Objective-C NSDate、C++ <chrono> 等高層封裝具備 3-4 倍效能優勢、零動態分配、無執行緒安全額外開銷。本文詳細解析 tm 結構體欄位語意、localtime 使用細節與實戰封裝技巧。

tm 結構體完整欄位對照表

欄位型別含義範圍/備註
tm_secint秒0-60 (60 為閏秒)
tm_minint分0-59
tm_hourint時 (24制)0-23
tm_mdayint月份中的日期1-31
tm_monint月份 (自 1 月起算)0-11 (0=1月)
tm_yearint年份 (自 1900 起算)年份-1900
tm_wdayint星期幾 (自星期日)0-6 (0=週日)
tm_ydayint年間第幾天0-365
tm_isdstint夏令時旗標>0 生效, 0 不生效, <0 未知
tm_gmtofflongUTC 偏移秒數POSIX 擴充,非標準
tm_zonechar*時區縮寫POSIX 擴充,非標準

關鍵陷阱:tm_mon 從 0 開始、tm_year 從 1900 起算,這是最常見的 Off-by-one 錯誤來源。

標準流程:time → localtime → tm

#include <time.h>
#include <stdio.h>

int main() {
    time_t now = time(NULL);          // 獲取當前時間戳 (UTC)
    struct tm *local = localtime(&now); // 轉換為本地時間 (靜態緩衝區)
    
    if (local) {
        printf("當前時間:%04d-%02d-%02d %02d:%02d:%02d\n",
               local->tm_year + 1900,
               local->tm_mon + 1,
               local->tm_mday,
               local->tm_hour,
               local->tm_min,
               local->tm_sec);
    }
    return 0;
}

進階封裝:支援毫秒與執行緒安全

標準 localtime 回傳靜態緩衝區指標,**非執行緒安全**,且無毫秒精度。生產級封裝建議:

方案 A:localtime_r / localtime_s (C11/C17 標準)

// POSIX (Linux/macOS)
struct tm result;
localtime_r(&now, &result);

// Windows (MSVC)
struct tm result;
localtime_s(&result, &now);

方案 B:gettimeofday 獲取微秒並合併


struct tm* get_local_time_with_ms(int *out_ms) {
    struct timeval tv;
    gettimeofday(&tv, NULL);           // 微秒精度
    
    time_t sec = tv.tv_sec;
    static __thread struct tm buf;     // 執行緒區域儲存 (GCC/Clang)
    // Windows 可用 thread_local struct tm buf; (C++11)
    localtime_r(&sec, &buf);
    
    if (out_ms) *out_ms = tv.tv_usec / 1000;
    
    buf.tm_year += 1900;  // 修正為完整年份
    buf.tm_mon  += 1;     // 修正為 1-12 月
    return &buf;
}

注意:修正 tm_year/tm_mon 會改變靜態/執行緒區域緩衝區內容,若後續仍需標準欄位值,請先備份或改用拷貝方式。

格式化輸出:strftime 最佳實踐


char buffer[64];
struct tm *t = get_local_time_with_ms(NULL);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
// 輸出:2025-01-15 14:30:45

strftime 支援豐富格式化指令,比手動 printf 更安全、可在地化、效能更優。

效能對比數據 (參考)

方法相對耗時分配記憶體執行緒安全毫秒支援
C time.h (localtime_r)1.0x (基準)無是需額外 gettimeofday
C++ <chrono> (system_clock)~2.5x可能是內建
Objective-C NSDate~3.5x是是內建
Python datetime.now()~15x是GIL內建

總結

掌握 struct tm 欄位語意、localtime_r 執行緒安全用法、gettimeofday 亞秒精度補充、strftime 格式化輸出,即可構建高效、可移植、生產就緒的時間處理模組。對於 C/C++ 系統程式、嵌入式固件、高頻交易引擎、日誌框架,這是比高層封裝更可控的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved