Linux C语言如何获取系统时间?

99ANYc3cd6
预计阅读时长 25 分钟
位置: 首页 C语言 正文

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

linux c语言 系统时间
(图片来源网络,侵删)

核心概念

  1. 日历时间:这是一个简单的数值,表示从 1970年1月1日 00:00:00 UTC(也称为 Unix 纪元)到当前时刻所经过的秒数,它的数据类型是 time_t
  2. broken-down time:这是一个结构体,将时间分解为年、月、日、时、分、秒等易于理解的组成部分,它的数据类型是 struct tm
  3. 时区:时间可以表示为 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()

linux c语言 系统时间
(图片来源网络,侵删)

函数说明

  • 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()

linux c语言 系统时间
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
void的return到底该怎么用?
« 上一篇 02-10
织梦PC与手机数据如何实时同步?
下一篇 » 02-10

相关文章

取消
微信二维码
支付宝二维码

目录[+]