云计算百科
云计算领域专业知识百科平台

40 C 语言日期与时间函数详解:time、ctime、difftime、clock(含 UTC/本地时间转换)

1 UTC 时间与本地时间

1.1 UTC 时间

  • 定义:UTC(Coordinated Universal Time,协调世界时)是全球统一的时间标准,以原子钟的高精度计时为基础,独立于地球自转。
  • 特点:
    • 不受地理位置或时区影响,是全球各时区统一参考的时间基准
    • 通过引入闰秒(每年最多增加或减少 1 秒)进行调整,以补偿地球自转速度的微小变化。
    • 确保与基于地球自转的天文时间(UT1)之间的偏差不超过 0.9 秒。
  • 示例:2025-05-20 17:20:00 UTC 表示全球统一的时间点。

1.2 本地时间

  • 定义:本地时间(Local Time) 是指将协调世界时(UTC)根据所在时区的偏移量进行调整后的时间,用于满足日常生活中对时间显示和使用的需求。
  • 时区(Time Zone):
    • 全球被划分为 24 个主要时区,相邻时区之间通常相差 1 小时
    • 部分国家或地区采用 30 分钟或 45 分钟 的非整点时区偏移,如印度(UTC+5:30)、尼泊尔(UTC+5:45)
    • 时区通常以 UTC+X 或 UTC−X 的形式表示:
      • UTC+8(如北京时间)表示比 UTC 快 8 小时
      • UTC−5(如美国东部标准时间)表示比 UTC 慢 5 小时
  • 夏令时(Daylight Saving Time, DST):
    • 某些地区在夏季实行夏令时,通常将时间提前 1 小时(把钟表的时间从当前时间向后调快 1 小时),以更好地利用自然光照,节约能源
    • 夏令时的开始与结束时间因国家和地区而异,可能导致本地时间与 UTC 的偏移在一年中发生临时变化。
  • 示例:假设当前 UTC 时间为:2025-05-20 12:00:00
    • 北京(UTC+8) 的本地时间为:2025-05-20 20:00:00
    • 纽约(UTC−5,非夏令时期间) 的本地时间为:2025-05-20 07:00:00

1.3 UTC 与本地时间的转换

  • 转换公式:
    • 本地时间 = UTC 时间 + 时区偏移量(需考虑是否启用夏令时)
    • UTC 时间 = 本地时间 – 时区偏移量(需考虑是否启用夏令时)
  • 示例:
    • 若北京时间(UTC+8,非夏令时)为 2025-05-20 10:00:00,则对应的 UTC 时间为:
      • UTC 时间 = 10:00 – 8 = 02:00,即 2025-05-20 02:00:00
    • 若 UTC 时间为 2025-05-20 12:00:00,则纽约时间(UTC-5,非夏令时)为:
      • 本地时间 = 12:00 + (-5) = 07:00,即 2025-05-20 07:00:00

1.4 时间戳

  • 定义:时间戳(Timestamp)通常表示自 1970 年 1 月 1 日 00:00:00 UTC(称为 Unix 纪元)以来经过的秒数
  • 特点:
    • 是 UTC 时间的一种数值化表示形式,不依赖于任何时区
    • 便于程序进行时间的比较、存储和计算。

2 time() 函数

2.1 函数原型

#include <time.h> // 必须包含此头文件才能使用 time() 函数

time_t time(time_t *timer);

2.2 功能说明

        time() 函数用于获取当前的日历时间(即从 1970 年 1 月 1 日 00:00:00 UTC 开始经过的秒数,不包括闰秒),并将其作为 time_t 类型的值返回

        time_t 类型通常是一个长整型(如 long 或 long long),用于表示时间戳(秒数)。在 printf 中输出时,常用 %ld 或 %lld 作为占位符,具体取决于平台。最常用写法(搭配强制转换):printf("%ld", (long)now) 

  • 参数:
    • timer:一个指向 time_t 类型变量的指针
      • 如果该参数不为 NULL,则当前时间也会被存储到该指针指向的变量中
      • 若为 NULL 或 0,则仅返回时间值
  • 返回值:
    • 成功时返回当前的时间值(以秒为单位的 time_t 类型)
    • 如果失败(例如系统无法获取当前时间),返回 (time_t)(-1)

2.3 注意事项

  • 精度限制:time() 的精度是秒级,不能获取毫秒或微秒级别的时间
  • 等价用法:time(0) 和 time(NULL) 完全等价,均用于获取当前时间戳而不存储结果
  • 跨平台兼容性:time() 是标准 C 库函数,在所有支持 C 标准库的平台上都可用
  • 避免频繁调用:虽然性能通常不是问题,但在高并发或实时系统中应谨慎使用
  • 错误处理:虽然很少发生错误,但建议检查返回值是否为 (time_t)-1
  • 2.4 应用场景

  • 记录日志时间戳:用于生成带有时间信息的日志内容。
  • 程序运行计时:可以结合两次调用 time() 来计算程序执行时间(适用于秒级精度)。
  • 超时判断:用于判断某个操作是否在规定时间内完成。
  • 文件/数据有效期控制:如生成带有时效性的缓存文件或令牌。
  • 用户界面显示时间:在 GUI 或 CLI 中显示当前日期和时间。
  • 生成唯一标识符:基于时间戳生成简单的唯一 ID(注意重复风险)。
  • 2.5 示例程序

    #include <stdio.h>
    #include <time.h> // 必须包含此头文件才能使用 time() 函数

    int main()
    {
    time_t current_time; // 声明一个 time_t 类型的变量来存储当前时间戳

    // 情况 1:参数为 NULL,仅返回当前时间值
    time_t returned_time = time(NULL);
    // 可选的检查返回值
    if (returned_time == (time_t)-1)
    {
    printf("无法获取当前时间(参数为 NULL 的情况)。\\n");
    }
    else
    {
    printf("情况1(参数为 NULL):当前时间戳:%ld\\n", (long)returned_time);
    }

    // 情况 2:参数为 0,仅返回当前时间值
    printf("情况2(参数为 0):当前时间戳:%ld\\n", (long)time(0));

    // 情况 3:参数为非 NULL,当前时间会被存储到指针指向的变量中
    time(&current_time); // 传入变量的地址,将当前时间戳存储到该变量中
    // 一般不检查返回值,直接使用
    printf("情况3(参数为非 NULL):当前时间戳:%ld\\n", (long)current_time);

    return 0;
    }

            程序在 VS Code 中的运行结果如下所示:


    3 ctime() 函数

    3.1 函数原型

    #include <time.h> // 必须包含此头文件才能使用 ctime() 函数

    char *ctime(const time_t *timer);

    3.2 功能说明

            ctime() 函数用于将 time_t 类型表示的时间值(即时间戳)转换为一个可读性良好的字符串形式,返回的是一个表示本地时间的字符串

    • 参数:
      • timer:指向一个 time_t 类型变量的指针,表示要转换的时间值
    • 返回值:
      • 成功时返回一个指向静态字符数组的指针,该数组中保存了格式化后的时间字符串
      • 如果失败(如传入的 timer 为 NULL 或系统内部错误),则返回 NULL

    3.3 注意事项

  • 自动换行符:返回的字符串末尾包含一个 \\n 换行符
  • 结果不可修改:返回的字符串是只读的,不应尝试修改其内容
  • 依赖系统本地时区:ctime() 返回的是本地时间,受操作系统时区设置影响
  • 返回值需检查:虽然很少失败,但应检查是否为 NULL
  • 3.4 应用场景

  • 打印当前时间:快速输出程序运行时的当前时间。
  • 日志记录:在日志信息前加上可读的时间戳。
  • 调试辅助:在调试过程中查看当前时间。
  • 简单时间显示:适用于不需要自定义格式的界面或控制台输出。
  • 3.5 示例程序

    #include <stdio.h>
    #include <time.h> // 必须包含此头文件才能使用 time() 和 ctime() 函数

    int main()
    {
    time_t current_time; // 声明一个 time_t 类型的变量来存储当前时间戳

    // 情况 1:参数为 NULL,仅返回当前时间值
    time_t returned_time = time(NULL);
    // 可选的检查返回值
    if (returned_time == (time_t)-1)
    {
    printf("无法获取当前时间(参数为 NULL 的情况)。\\n");
    }
    else
    {
    printf("情况1(参数为 NULL):当前时间戳:%ld\\n", (long)returned_time);
    // 使用 ctime 输出可读时间字符串
    printf("情况1 对应的本地时间:%s", ctime(&returned_time)); // 不需要换行符,ctime() 函数会自动添加
    }

    // 情况 2:参数为非 NULL,当前时间会被存储到指针指向的变量中
    time(&current_time); // 传入变量的地址,将当前时间戳存储到该变量中
    printf("情况2(参数为非 NULL):当前时间戳:%ld\\n", (long)current_time);
    // 使用 ctime 输出可读时间字符串
    printf("情况2 对应的本地时间:%s", ctime(&current_time)); // 不需要换行符,ctime() 函数会自动添加

    return 0;
    }

            程序在 VS Code 中的运行结果如下所示:


      4 difftime() 函数

      4.1 函数原型

      #include <time.h> // 必须包含此头文件才能使用 difftime() 函数

      double difftime(time_t time2, time_t time1);

      4.2 功能说明

              difftime() 函数用于计算两个时间点之间的时间差(以秒为单位)。这两个时间点通常是由 time() 函数获取的 time_t 类型的时间戳

      • 参数:
        • time2:结束时间,一个 time_t 类型值
        • time1:开始时间,一个 time_t 类型值
      • 返回值:
        • 返回 time2 – time1 的差值,结果以 double 类型表示,单位为秒
        • 如果 time2 比 time1 小(即结束时间早于开始时间),则返回负数

      4.3 注意事项

    • 返回值为 double:可以表示非整数秒的时间差(如某些系统支持更高精度时间),适合更精确的计时
    • 顺序影响结果:difftime(time2, time1) 表示从 time1 到 time2 的时间差,注意参数顺序
    • 常用于性能测试:适用于粗略测量代码执行时间(如秒级或亚秒级)
    • 可以跨时区比较:时间戳本质上是 UTC 时间,不受本地时区影响,因此适合用于跨时区的时间差计算
    • 4.4 应用场景

    • 程序运行时间统计:记录某段代码执行前后的时间戳,并计算耗时。
    • 超时控制:判断某个操作是否在规定时间内完成。
    • 用户行为分析:记录用户操作之间的间隔时间。
    • 日志记录:输出事件发生的时间间隔,便于后续分析。
    • 定时任务调度:用于判断是否满足触发条件。
    • 4.5 示例程序

      #include <stdio.h>
      #include <time.h> // 必须包含此头文件才能使用 time() 和 difftime() 函数

      int main()
      {
      time_t start_time, end_time; // 定义两个 time_t 变量用于保存时间戳

      printf("程序开始计时…\\n");
      start_time = time(NULL); // 获取开始时间

      // 模拟耗时操作(通过循环延时)
      for (unsigned long long i = 0; i < 10000000000LL; ++i)
      ; // 简单延迟

      end_time = time(NULL); // 获取结束时间

      // 使用 difftime 计算时间差
      double elapsed_seconds = difftime(end_time, start_time);

      printf("程序结束计时。\\n");
      printf("经过的时间:%lf 秒\\n", elapsed_seconds);

      return 0;
      }

              程序在 VS Code 中的运行结果如下所示:


      5 clock() 函数

      5.1 函数原型

      #include <time.h> // 必须包含此头文件才能使用 clock() 函数

      clock_t clock(void);

      5.2 功能说明

              clock() 函数返回自程序启动以来(或程序进入当前状态以来)的处理器时间(CPU 时间),单位通常是 “时钟滴答”(clock ticks)。该时间以 clock_t 类型表示,通常用于测量一段代码的 CPU 执行时间。

      • 返回值:
        • 返回当前进程使用的处理器时间(CPU 时间),单位为 CLOCKS_PER_SEC(每秒的时钟滴答数),而不是秒数
          • 示例:如果 CLOCKS_PER_SEC 是 1000000,则 clock() 返回的值除以 1000000 可以得到秒数。
          • 因此,clock() 返回的滴答数除以 CLOCKS_PER_SEC 可以得到以秒为单位的 CPU 时间
        • 返回 (clock_t)(-1)(通常是 -1),并可能设置 errno(但标准未明确要求设置 errno,具体行为依赖实现)

      5.3 注意事项

    • 仅限于当前进程:只能用于测量当前进程内的 CPU 使用情况
    • 精度问题:在某些系统上,CLOCKS_PER_SEC 的值可能较低(如 100),导致 clock() 的分辨率不高,适合粗略估计而非高精度计时
    • 平台差异性:不同操作系统实现可能有所不同,尤其注意 CLOCKS_PER_SEC 的值
    • 返回类型:返回类型是 clock_t,需根据具体平台将其转换为秒(除以 CLOCKS_PER_SEC)或其他时间单位进行解释
    • 5.4 应用场景

    • 性能分析:评估特定算法或代码段的执行效率。
    • 调试辅助:帮助开发者了解某部分代码是否耗时过长。
    • 资源监控:监测程序运行过程中对 CPU 资源的占用情况。
    • 测试工具开发:构建自动化测试框架中的一部分,用于度量测试案例的执行速度。
    • 5.5 示例程序

      #include <stdio.h>
      #include <time.h> // 必须包含此头文件才能使用 clock() 函数

      int main()
      {
      // 记录开始时间
      clock_t start_time = clock();

      // 模拟一个耗时的操作
      for (unsigned long long i = 0; i < 10000000000LL; ++i)
      ; // 简单延迟

      // 记录结束时间
      clock_t end_time = clock();

      // 计算消耗的 CPU 时间,并将其转换为秒(除以 CLOCKS_PER_SEC)
      double cpu_time_used = ((double)(end_time – start_time)) / CLOCKS_PER_SEC;

      printf("模拟操作消耗的 CPU 时间: %lf 秒\\n", cpu_time_used);

      return 0;
      }

              程序在 VS Code 中的运行结果如下所示:


      6 日期与时间函数总结

      函数名功能参数返回值
      time 获取当前时间戳(自 1970-01-01 00:00:00 UTC 起经过的秒数) time_t *timer:可为 NULL,用于接收时间戳 成功返回时间戳(time_t 类型),失败返回 (time_t)-1
      ctime 将时间戳转换为可读的本地时间字符串(格式固定,带换行符) const time_t *timer:指向时间戳的指针 成功返回指向静态字符串的指针,失败返回 NULL
      difftime 计算两个时间点之间的时间差(以秒为单位) time_t time2, time_t time1:两个时间点 返回 time2 – time1 的差值(double 类型,单位为秒)
      clock 获取当前进程使用的 CPU 时间(从程序启动开始计算) 无参数 成功返回 CPU 使用时间(以时钟周期为单位),失败返回 (clock_t)-1

      补充说明:

      • time_t 类型:通常为长整型(如 long 或 long long),用于表示自 Unix 纪元(1970-01-01 00:00:00 UTC)以来经过的秒数,即时间戳
      • ctime() 的线程安全性该函数返回一个指向内部静态缓冲区的指针,内容在每次调用时会被覆盖
      • difftime() 的优势:该函数基于标准 C 定义,能够准确计算两个时间点之间的差值,单位为秒(支持小数),适用于跨平台、跨时区的时间差比较,是推荐的标准方法
      • clock() 的局限性:它返回的是程序所占用的 CPU 时间,而非真实世界时间(wall-clock time),因此不适合用于测量 I/O 操作、睡眠或等待外部事件的时间
      赞(0)
      未经允许不得转载:网硕互联帮助中心 » 40 C 语言日期与时间函数详解:time、ctime、difftime、clock(含 UTC/本地时间转换)
      分享到: 更多 (0)

      评论 抢沙发

      评论前必须登录!