在C++中处理日期和时间,主要有以下几种方式:
头文件) (C-style Date and Time (
Header))这是C语言继承过来的,在C++中依然可用。它们通常以time_t
类型表示时间戳,以tm
结构体表示分解后的日期和时间。
time_t
类型 ( time_t
Type):
time()
函数获取。#include
#include // For time_t, time()
int main() {
time_t now = time(0); // 获取当前时间戳 (get current timestamp)
std::cout << "Number of seconds since January 1, 1970: " << now << std::endl;
return 0;
}
tm
结构体 ( tm
Structure):
一个结构体,包含年、月、日、时、分、秒等成员。
成员:
struct tm {
int tm_sec; // Seconds (0-60)
int tm_min; // Minutes (0-59)
int tm_hour; // Hours (0-23)
int tm_mday; // Day of the month (1-31)
int tm_mon; // Months since January (0-11)
int tm_year; // Years since 1900
int tm_wday; // Days since Sunday (0-6)
int tm_yday; // Days since January 1 (0-365)
int tm_isdst; // Daylight Saving Time flag (positive if DST, 0 if not, negative if unknown)
};
相关函数:
localtime()
: 将 time_t
转换为本地时间(Local Time)的 tm
结构体。gmtime()
: 将 time_t
转换为协调世界时(UTC, Coordinated Universal Time)的 tm
结构体。mktime()
: 将 tm
结构体转换为 time_t
。asctime()
: 将 tm
结构体或 time_t
转换为可读的日期和时间字符串(如 “Fri Jun 13 23:29:19 2025”)。ctime()
: 将 time_t
转换为可读的日期和时间字符串。strftime()
: 格式化时间,允许你指定输出格式。示例:获取和格式化本地时间 (Example: Get and Format Local Time):
#include
#include
#include // For std::string
int main() {
time_t now = time(0); // 获取当前时间戳 (get current timestamp)
// 将时间戳转换为本地时间结构体 (convert timestamp to local time structure)
tm* ltm = localtime(&now);
// 使用asctime()直接输出 (output directly with asctime())
std::cout << "Local time using asctime: " << asctime(ltm) << std::endl;
// 使用strftime()进行格式化输出 (formatted output with strftime())
char buffer[80];
// YYYY-MM-DD HH:MM:SS
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ltm);
std::cout << "Formatted local time: " << buffer << std::endl;
// 获取UTC时间 (get UTC time)
tm* gmt = gmtime(&now);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S UTC", gmt);
std::cout << "Formatted UTC time: " << buffer << std::endl;
return 0;
}
计算时间差 (Calculating Time Difference):
difftime()
: 计算两个 time_t
值之间的秒数差。#include
#include
#include // For std::this_thread::sleep_for
#include // For std::chrono::seconds
int main() {
time_t start_time = time(0);
std::cout << "Start time: " << ctime(&start_time);
// 模拟一些工作 (simulate some work)
std::this_thread::sleep_for(std::chrono::seconds(2));
time_t end_time = time(0);
std::cout << "End time: " << ctime(&end_time);
double diff_seconds = difftime(end_time, start_time);
std::cout << "Time difference: " << diff_seconds << " seconds" << std::endl;
return 0;
}
chrono
库 (C++11 chrono
Library)从C++11开始,chrono
库提供了更现代、类型安全和灵活的方式来处理时间。它主要包含三个核心组件:
时钟 (Clocks):
std::chrono::system_clock
: 系统范围的实时时钟,通常与系统时间同步,可能会因系统时间调整而跳跃。std::chrono::steady_clock
: 单调递增的时钟,不会因系统时间调整而倒退,适合测量时间间隔(如性能测试)。std::chrono::high_resolution_clock
: 提供了最高的精度,通常是 system_clock
或 steady_clock
的别名。时间点 (Time Points):
duration
类型组成。std::chrono::system_clock::time_point
时间段 (Durations):
std::chrono::seconds
, std::chrono::milliseconds
, std::chrono::microseconds
, std::chrono::nanoseconds
等。std::chrono::duration_cast<>
: 用于在不同时间单位之间进行转换。示例:测量代码执行时间 (Example: Measuring Code Execution Time):
#include
#include // For chrono library
#include // For std::this_thread::sleep_for
int main() {
// 获取当前时间点 (get current time point)
auto start = std::chrono::steady_clock::now();
// 模拟一些工作 (simulate some work)
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 睡眠100毫秒 (sleep for 100 milliseconds)
auto end = std::chrono::steady_clock::now();
// 计算时间差 (calculate time difference)
auto duration = end - start;
// 转换为不同时间单位 (convert to different time units)
std::cout << "Execution time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()
<< " milliseconds" << std::endl;
std::cout << "Execution time: "
<< std::chrono::duration_cast<std::chrono::microseconds>(duration).count()
<< " microseconds" << std::endl;
// 直接转换为秒 (convert directly to seconds)
double seconds = std::chrono::duration_cast<std::chrono::duration<double>>(duration).count();
std::cout << "Execution time: " << seconds << " seconds" << std::endl;
return 0;
}
示例:获取当前系统时间 (Example: Getting Current System Time):
#include
#include
#include // For std::time_t, std::localtime, std::mktime
#include // For std::put_time
int main() {
// 获取当前系统时间点 (get current system time point)
auto now_chrono = std::chrono::system_clock::now();
// 转换为time_t (convert to time_t)
std::time_t now_c = std::chrono::system_clock::to_time_t(now_chrono);
// 转换为本地时间结构体 (convert to local time structure)
// 注意:localtime返回的是指向静态分配内存的指针,多线程环境需注意
// Note: localtime returns a pointer to statically allocated memory; be careful in multi-threaded environments.
std::tm* local_tm = std::localtime(&now_c);
// 使用put_time进行格式化输出 (formatted output with put_time)
// %F 是 %Y-%m-%d 的简写,%T 是 %H:%M:%S 的简写 (abbreviation)
std::cout << "Current local time: " << std::put_time(local_tm, "%F %T") << std::endl;
// 也可以直接获取时间戳 (can also directly get timestamp)
// auto epoch_duration = now_chrono.time_since_epoch();
// std::cout << "Seconds since epoch: " << std::chrono::duration_cast(epoch_duration).count() << std::endl;
return 0;
}
std::chrono
日历扩展 (C++20 std::chrono
Calendar Extensions)C++20 对 chrono
库进行了大幅度扩展,引入了日期类型(如 year_month_day
)、时区支持(time_zone
)、格式化(format
)等功能,使得日期和时间的处理更加完善和方便。
主要概念:
std::chrono::year_month_day
: 表示年、月、日。std::chrono::weekday
: 表示星期几。std::chrono::hh_mm_ss
: 表示小时、分钟、秒。std::chrono::zoned_time
: 带时区的时间点。std::chrono::format()
: 类似 strftime
,但更强大和类型安全。std::chrono::parse()
: 解析字符串为时间点。示例 (C++20):
#include
#include
#include // C++20 for std::format
int main() {
// 获取当前时间点 (get current time point)
auto now = std::chrono::system_clock::now();
// 转换为日期和时间组件 (convert to date and time components)
auto today = std::chrono::floor<std::chrono::days>(now); // 转换为天的时间点
auto ymd = std::chrono::year_month_day{today}; // 从时间点获取年-月-日
// 输出年、月、日 (output year, month, day)
std::cout << "Year: " << (int)ymd.year() << std::endl;
std::cout << "Month: " << (unsigned)ymd.month() << std::endl;
std::cout << "Day: " << (unsigned)ymd.day() << std::endl;
// 格式化输出 (formatted output) - C++20 std::format
// 类似于 python 的 f-string 或者 java 的 String.format
std::cout << std::format("Current date and time: {:%Y-%m-%d %H:%M:%S}", now) << std::endl;
// 获取当前时区的时间 (get time in current timezone)
// C++20 需要 IANA 时区数据库支持,可能需要额外配置
// C++20 requires IANA timezone database support, which may need additional configuration.
try {
auto zoned_now = std::chrono::current_zone()->to_local(now);
std::cout << std::format("Current zoned time: {:%Y-%m-%d %H:%M:%S %Z}", zoned_now) << std::endl;
} catch (const std::runtime_error& e) {
std::cerr << "Error getting current time zone (C++20 feature might not be fully supported or configured): " << e.what() << std::endl;
}
return 0;
}
注意: C++20 的
扩展功能需要较新的编译器支持(如 GCC 10+, Clang 10+),并且在某些环境下可能需要额外的库或配置来正确处理时区信息。
): 简单直接,但类型不安全,容易出错,且对时区和精度支持有限。适合快速获取当前时间戳或基本格式化。chrono
: 现代C++推荐的方式。类型安全、高精度、灵活。非常适合测量时间间隔(性能分析)、处理时间点。chrono
扩展: 进一步完善了 chrono
库,提供了更全面的日期、时间、时区和格式化功能,使得日期时间处理更加直观和强大。