Linux C时间函数
在Linux系统编程中,时间处理是一项基础且重要的任务,无论是日志记录、任务调度,还是性能分析,都需要准确获取和操作时间,Linux C标准库提供了丰富的时间函数,涵盖时间获取、格式化、转换等多个方面,本文将详细介绍这些函数的用法、特点及注意事项,帮助开发者高效处理时间相关需求。
时间表示:time_t与struct tm
Linux C中使用两种核心结构表示时间:time_t和struct tm。time_t是一个整数类型,通常用于表示自1970年1月1日00:00:00 UTC(Unix纪元)以来经过的秒数,它通过time()函数获取,适用于简单的时间戳存储和计算。
struct tm则是一个更详细的时间结构体,定义在<time.h>中,包含年、月、日、时、分、秒等字段:
struct tm {
int tm_sec; // 秒(0-59)
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)
int tm_isdst; // 夏令时标志(0表示非夏令时)
};
通过gmtime()和localtime()函数,可以将time_t转换为struct tm。gmtime()返回UTC时间,而localtime()返回本地时间。
时间获取:time()与gettimeofday()
time()函数是最简单的时间获取方式,其原型为:
time_t time(time_t *t);
若参数t非空,则将时间值同时存储在t指向的内存中;若为空,则仅返回时间值。
time_t now = time(NULL);
对于更高精度的时间需求(如微秒级),可以使用gettimeofday()函数:
#include <sys/time.h> int gettimeofday(struct timeval *tv, struct timezone *tz);
struct timeval包含秒(tv_sec)和微秒(tv_usec)字段,适用于性能测量或事件计时。
时间格式化:strftime()与strptime()
将时间转换为可读字符串或解析字符串为时间结构体,是时间处理的常见需求。strftime()函数提供了强大的格式化功能:
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
format参数支持多种格式说明符,如%Y(四位年)、%m(月)、%d(日)等,示例:
char buffer[80]; struct tm *now = localtime(&now); strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", now);
反之,strptime()函数用于将字符串解析为struct tm:
char *strptime(const char *s, const char *format, struct tm *tm);
const char *date_str = "2023-10-01 12:30:45";
struct tm tm = {0};
strptime(date_str, "%Y-%m-%d %H:%M:%S", &tm);
时间计算:mktime()与difftime()
mktime()函数将struct tm转换为time_t,并自动处理非法值(如2月30日),它会调整tm_wday和tm_yday,并返回转换后的时间戳:
struct tm tm = {0};
tm.tm_year = 2023 - 1900; // 2023年
tm.tm_mon = 9; // 10月
tm.tm_mday = 1; // 1日
time_t timestamp = mktime(&tm);
difftime()则用于计算两个time_t值的时间差(秒):
time_t t1 = time(NULL); sleep(5); time_t t2 = time(NULL); double diff = difftime(t2, t1); // 返回5.0
高精度计时:clock_gettime()
对于需要纳秒级精度的场景,clock_gettime()是最佳选择,它支持多种时钟类型,如CLOCK_REALTIME(系统时间)和CLOCK_MONOTONIC(单调递增时间):
#include <time.h> struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); // ts.tv_sec: 秒,ts.tv_nsec: 纳秒
CLOCK_MONOTONIC不受系统时间调整影响,适合测量耗时。
注意事项
- 线程安全:
gmtime()和localtime()返回静态指针,多线程环境下需使用gmtime_r()和localtime_r()。 - 时区处理:
localtime()依赖系统时区设置,可通过TZ环境变量或tzset()修改。 - 精度限制:
time_t在32位系统上可能在2038年溢出,建议使用64位类型或timeval。
实践示例
以下是一个综合示例,展示时间获取、格式化和计算:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main() {
// 获取当前时间
time_t now = time(NULL);
struct tm *tm_now = localtime(&now);
// 格式化输出
char buffer[100];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %Z", tm_now);
printf("当前时间: %s\n", buffer);
// 计算时间差
sleep(2);
time_t later = time(NULL);
printf("时间差: %.2f秒\n", difftime(later, now));
// 高精度计时
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
usleep(100000); // 100毫秒
clock_gettime(CLOCK_MONOTONIC, &end);
double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("高精度耗时: %.6f秒\n", elapsed);
return 0;
}
Linux C时间函数提供了从秒级到纳秒级的多种时间处理能力,合理选择函数并注意线程安全、时区等问题,可以高效实现时间相关的功能,开发者应根据实际需求(如精度、可读性、跨平台性)灵活运用这些工具,确保时间处理的准确性和可靠性。












