在 Linux C 语言中,获取和操作系统时间通常涉及几个关键的系统调用和库函数,下面我将详细介绍几种常用方法,从简单到复杂,并附上完整的代码示例。

(图片来源网络,侵删)
核心概念
- 日历时间:这是一个简单的数值,表示从 1970年1月1日 00:00:00 UTC(也称为 Unix 纪元)到当前时刻所经过的秒数,它的数据类型是
time_t。 - broken-down time:这是一个结构体,将时间分解为年、月、日、时、分、秒等易于理解的组成部分,它的数据类型是
struct tm。 - 时区:时间可以表示为 UTC(世界协调时间)或本地时间。
time()和localtime()函数处理本地时间,而gmtime()函数处理 UTC 时间。
使用 time() 和 localtime() (最常用)
这是获取当前本地时间最直接、最简单的方法。
函数说明
-
time_t time(time_t *t)- 功能:获取当前的日历时间。
- 参数:
- 如果传入一个非
NULL的指针(如&now),函数会将时间值同时存入该指针指向的内存和返回值中。 - 如果传入
NULL,函数只返回时间值。
- 如果传入一个非
- 返回值:成功返回当前时间的
time_t值,失败返回(time_t)-1。
-
struct tm *localtime(const time_t *timer)- 功能:将
time_t格式的日历时间转换为本地时间的struct tm结构体。 - 参数:指向
time_t变量的指针。 - 返回值:指向
struct tm结构体的指针。注意:这个结构体通常是一个静态分配的变量,意味着每次调用localtime()都会覆盖上一次的结果,如果你需要长时间保存分解后的时间,应该手动复制这个结构体的内容。
- 功能:将
struct tm 结构体成员
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表示非夏令时, 负数表示未知 */
};
完整代码示例
#include <stdio.h>
#include <time.h> // 包含时间函数的头文件
int main() {
// 1. 获取当前日历时间
time_t raw_time;
time(&raw_time); // 等价于 time_t raw_time = time(NULL);
// 2. 将日历时间转换为本地时间的 broken-down time
struct tm *local_time = localtime(&raw_time);
if (local_time == NULL) {
perror("localtime");
return 1;
}
// 3. 打印分解后的时间
printf("Broken-down time:\n");
printf(" Year: %d\n", 1900 + local_time->tm_year);
printf(" Month: %d\n", 1 + local_time->tm_mon);
printf(" Day: %d\n", local_time->tm_mday);
printf(" Hour: %d\n", local_time->tm_hour);
printf(" Minute: %d\n", local_time->tm_min);
printf(" Second: %d\n", local_time->tm_sec);
printf(" Weekday: %d (0=Sunday)\n", local_time->tm_wday);
printf(" Day of year: %d\n", local_time->tm_yday);
printf(" Is DST: %d\n", local_time->tm_isdst);
// 4. 使用 asctime() 或 ctime() 格式化输出
// asctime() 接受 struct tm*,ctime() 接受 time_t*
// 两者都返回一个静态分配的字符串,格式为 "Wed Jun 30 21:49:08 1993\n"
printf("\nFormatted time (asctime): %s", asctime(local_time));
printf("Formatted time (ctime): %s", ctime(&raw_time));
return 0;
}
使用 gettimeofday() (高精度,微秒级)
如果你需要比秒更精确的时间(例如微秒级),可以使用 gettimeofday()。

(图片来源网络,侵删)
函数说明
int gettimeofday(struct timeval *tv, struct timezone *tz)- 功能:获取当前时间,精度为微秒。
- 参数:
tv:指向struct timeval结构体的指针,用于存储秒和微秒。tz:指向struct timezone结构体的指针,用于存储时区信息,在现代 Linux 系统中,此参数通常被忽略,可以设为NULL。
- 返回值:成功返回 0,失败返回 -1。
struct timeval 结构体
struct timeval {
long tv_sec; /* 秒 */
long tv_usec; /* 微秒 (1/1,000,000 秒) */
};
完整代码示例
#include <stdio.h>
#include <sys/time.h> // 包含 gettimeofday 的头文件
int main() {
struct timeval tv;
// 获取当前时间
if (gettimeofday(&tv, NULL) == -1) {
perror("gettimeofday");
return 1;
}
printf("Seconds since epoch: %ld\n", tv.tv_sec);
printf("Microseconds: %ld\n", tv.tv_usec);
// 可以组合成一个浮点数秒
double current_time_in_seconds = tv.tv_sec + (tv.tv_usec / 1000000.0);
printf("Current time in seconds (double): %.6f\n", current_time_in_seconds);
return 0;
}
使用 clock_gettime() (最高精度,纳秒级,推荐)
这是现代 POSIX 系统中推荐使用的方法,因为它精度更高(纳秒级),并且可以指定不同的时钟源。
函数说明
int clock_gettime(clockid_t clk_id, struct timespec *tp)- 功能:获取指定时钟的当前时间。
- 参数:
clk_id:时钟类型,可以是:CLOCK_REALTIME: 系统的实时时钟,受系统时间调整影响,这是我们通常说的“系统时间”。CLOCK_MONOTONIC: 从系统启动开始计时,不受系统时间调整(如 NTP 同步)影响,非常适合用于测量耗时。CLOCK_PROCESS_CPUTIME_ID: 当前进程使用的 CPU 时间。CLOCK_THREAD_CPUTIME_ID: 当前线程使用的 CPU 时间。
tp:指向struct timespec结构体的指针。
- 返回值:成功返回 0,失败返回 -1。
struct timespec 结构体
struct timespec {
long tv_sec; /* 秒 */
long tv_nsec; /* 纳秒 (1/1,000,000,000 秒) */
};
完整代码示例
#include <stdio.h>
#include <time.h> // clock_gettime 也在这里
int main() {
struct timespec ts;
// 获取 CLOCK_REALTIME (系统时间)
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
perror("clock_gettime(CLOCK_REALTIME)");
return 1;
}
printf("CLOCK_REALTIME:\n");
printf(" Seconds: %ld\n", ts.tv_sec);
printf(" Nanoseconds: %ld\n", ts.tv_nsec);
// 获取 CLOCK_MONOTONIC (单调时钟,用于测量耗时)
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
perror("clock_gettime(CLOCK_MONOTONIC)");
return 1;
}
printf("\nCLOCK_MONOTONIC:\n");
printf(" Seconds: %ld\n", ts.tv_sec);
printf(" Nanoseconds: %ld\n", ts.tv_nsec);
return 0;
}
设置系统时间 (需要 root 权限)
在 C 程序中,你也可以设置系统时间。这通常需要超级用户权限。
函数说明
int clock_settime(clockid_t clk_id, const struct timespec *tp)- 功能:设置指定时钟的时间。
- 参数:
clk_id:时钟类型,通常为CLOCK_REALTIME。tp:指向新的struct timespec结构体的指针。
- 返回值:成功返回 0,失败返回 -1。
重要提示
- 权限:调用此程序的用户必须是
root。 - 安全性:随意更改系统时间可能会导致依赖时间的应用程序(如数据库、证书、调度任务)出现严重问题。
完整代码示例
#include <stdio.h>
#include <time.h>
#include <stdlib.h> // for exit
#include <unistd.h> // for getuid
int main() {
// 检查是否为 root 用户
if (getuid() != 0) {
fprintf(stderr, "Error: This program must be run as root to set the time.\n");
exit(EXIT_FAILURE);
}
struct timespec new_time;
new_time.tv_sec = 1672531200; // 2025-01-01 00:00:00 UTC
new_time.tv_nsec = 0;
printf("Attempting to set system time to: %ld seconds since epoch...\n", new_time.tv_sec);
if (clock_settime(CLOCK_REALTIME, &new_time) == -1) {
perror("clock_settime");
exit(EXIT_FAILURE);
}
printf("System time set successfully.\n");
// 验证时间是否已更改
time_t raw_time;
time(&raw_time);
printf("New system time (seconds since epoch): %ld\n", raw_time);
return 0;
}
总结与对比
| 方法 | 函数 | 精度 | 描述 | 适用场景 |
|---|---|---|---|---|
| 标准方法 | time(), localtime() |
秒 | 最简单、最通用的方法,获取本地时间。 | 显示日志时间、创建时间戳等常规任务。 |
| 高精度方法 | gettimeofday() |
微秒 | 传统的高精度计时方法。 | 性能分析、测量短时间间隔。 |
| 现代方法 | clock_gettime() |
纳秒 | 推荐,精度高,可指定时钟源(如单调时钟)。 | 需要高精度计时、测量耗时、不受系统时间影响的场景。 |
| 设置时间 | clock_settime() |
纳秒 | 修改系统时间。 | 系统管理、自动化脚本(需 root 权限)。 |
对于大多数应用,time() 和 localtime() 已经足够,如果你需要更高精度或更可靠的计时(比如计算代码执行时间),强烈推荐使用 clock_gettime()。

(图片来源网络,侵删)
