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

C/C++ 時間日期處理完全指南:從 time.h 到 chrono 的演進與實戰

     編輯:關於C++

C/C++ 時間處理經歷了從 C 風格 time.h 到 C++11 <chrono> 的演進。本文系統梳理核心概念、資料結構、標準庫函式與格式化輸出,並對比新舊 API 優劣。

核心概念釐清

術語定義關鍵特性
UTC (Collaborated Universal Time)協調世界時 / 格林威治標準時間無時區偏移基準,中國為 UTC+8
Calendar Time (日曆時間)從 Epoch 起經過的秒數型別 time_t,全球同一時刻數值相同
Epoch (時間基點)標準庫定義的起始時間點多為 1970-01-01 00:00:00 UTC (Unix 時間)
Clock Tick (時鐘計時單元)CPU 計時最小單位CLOCKS_PER_SEC 定義每秒計數,通常 1ms 或 1μs
Broken-down Time (分解時間)年月日時分秒分離的結構結構體 tm,便於顯示與運算

C 風格 API (time.h/ctime) 完整速查

資料結構

struct tm {
    int tm_sec;   // 0-59 (允許 60 閏秒)
    int tm_min;   // 0-59
    int tm_hour;  // 0-23
    int tm_mday;  // 1-31
    int tm_mon;   // 0-11 (0=一月)
    int tm_year;  // 年份-1900
    int tm_wday;  // 0-6 (0=星期日)
    int tm_yday;  // 0-365 (0=1月1日)
    int tm_isdst; // 夏令時標誌: >0 生效, 0 不生效, <0 未知
};
typedef long time_t;  // 32 位系統 2038 年溢位,64 位已解決

核心函式分類

分類函式用途備註
取得時間time(time_t*)取得當前日曆時間回傳值與參數同值
clock()取得程序 CPU 時間精度 CLOCKS_PER_SEC,非牆鐘時間
_time64()64 位版 time (MSVC)支援至 3001 年
轉換localtime(time_t*)日曆時間 → 本地分解時間回傳靜態緩衝區,執行緒不安全
gmtime(time_t*)日曆時間 → UTC 分解時間同上,需自行複製
mktime(tm*)分解時間 → 日曆時間自動修正欄位溢位 (如月份 13→翌年1月)
格式化asctime(tm*)分解時間 → 固定格式字串"Wed Jan 02 02:03:55 1980\n\0"
ctime(time_t*)日曆時間 → 固定格式字串等同 asctime(localtime(t))
strftime(char*,size_t,const char*,tm*)自訂格式輸出支援 %Y-%m-%d %H:%M:%S 等豐富格式
wcsftime寬字元版 strftimeUnicode 環境適用
計算差值difftime(time_t,time_t)兩時間點秒數差 (double)僅秒級精度

strftime 格式化符號精選

%Y  四位數年份 (2024)     %y  兩位數年份 (24)
%m  月份 01-12            %b  月份縮寫 (Jan)    %B  月份全名 (January)
%d  日期 01-31            %e  日期 1-31 (空白填充)
%H  24制時 00-23          %I  12制時 01-12      %p  AM/PM
%M  分鐘 00-59            %S  秒數 00-59
%F  等同 %Y-%m-%d         %T  等同 %H:%M:%S
%z  時區偏移 (+0800)      %Z  時區名稱 (CST)
%c  標準日期時間          %x  標準日期          %X  標準時間
%%  字面 % 字元

實戰範例:多種時間操作

#include <ctime>
#include <iostream>
#include <iomanip>

void demo() {
    // 1. 當前時間
    time_t now = time(nullptr);
    std::cout << "Calendar time: " << now << '\n';

    // 2. 本地時間分解
    tm local = *localtime(&now);  // 複製避免靜態緩衝區覆蓋
    std::cout << "Local: " << std::put_time(&local, "%F %T") << '\n';

    // 3. UTC 時間
    tm utc = *gmtime(&now);
    std::cout << "UTC:   " << std::put_time(&utc, "%F %T") << '\n';

    // 4. 自訂格式
    char buf[64];
    strftime(buf, sizeof(buf), "Today is %A, %d %B %Y", &local);
    std::cout << buf << '\n';

    // 5. 指定時間點構造 (1997-07-01)
    tm target = {}; target.tm_year = 97; target.tm_mon = 6; target.tm_mday = 1;
    time_t t = mktime(&target);
    std::cout << "1997-07-01 是 " << std::put_time(localtime(&t), "%A") << '\n';

    // 6. 計算程式碼執行時間 (clock)
    clock_t start = clock();
    // ... 執行待測程式碼 ...
    clock_t end = clock();
    std::cout << "Elapsed: " << double(end-start)/CLOCKS_PER_SEC << "s\n";
}

C++11 <chrono> 現代時間庫

解決 C API 的執行緒不安全、精度限制、型別不安全、時區處理缺失等痛點。

核心型別體系


// 時間長度
using namespace std::chrono;
nanoseconds ns(100);
milliseconds ms = duration_cast<milliseconds>(ns);  // 0ms (截斷)
microseconds us = ms;  // 隱含轉換 (無精度損失)

// 時間點
system_clock::time_point now = system_clock::now();
time_t tt = system_clock::to_time_t(now);  // 互轉 C API

steady_clock::time_point start = steady_clock::now();
// ... 程式碼 ...
auto elapsed = steady_clock::now() - start;  // 高精度持續時間
std::cout << duration_cast<milliseconds>(elapsed).count() << "ms\n";

// 字面值 (C++14)
using namespace std::chrono_literals;
auto timeout = 30s + 500ms;  // 30.5 秒

格式化輸出 (C++20 <format> / std::chrono::format)

// C++20
#include <format>
#include <chrono>
auto now = std::chrono::system_clock::now();
std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", now) << '\n';
// 輸出: 2024-01-15 14:30:45

// 時區支援 (C++20  tzdb)
auto zt = std::chrono::zoned_time{"Asia/Taipei", now};
std::cout << std::format("{:%Y-%m-%d %H:%M:%S %Z}", zt) << '\n';

新舊 API 選擇建議

場景推薦 API理由
簡單顯示當前時間time + strftime相容性佳,無依賴
高精度效能計時steady_clock單調、納秒級、不受系統時間調整影響
跨平台時區處理C++20 zoned_time / Howard Hinnant's date.hC API 無時區資料庫
時間運算 (加減天/月)C++20 year_month_day / date.hmktime 僅支援秒級運算
舊代碼維護time.h + localtime_r/gmtime_r執行緒安全版本 (POSIX)

2038 年問題與 64 位遷移

  • 32 位 time_t 最大值 0x7FFFFFFF 對應 2038-01-19 03:14:07 UTC。
  • 現代 64 位編譯器預設 time_t 為 64 位 (MSVC 需定義 _USE_32BIT_TIME_T=0)。
  • 跨平台專案建議統一使用 int64_t 或 std::chrono::system_clock::time_point 存儲時間點。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved