C语言如何转换Unix时间戳?

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

下面我将详细介绍几种常见的转换方法,从最基本到更灵活的用法。

c语言 unix时间戳 转换
(图片来源网络,侵删)

核心函数

主要涉及 <time.h> 中的以下几个函数:

  1. time_t time(time_t *t): 获取当前的 Unix 时间戳。
  2. struct tm *localtime(const time_t *timer): 将 time_t(时间戳)转换为本地时间的 struct tm 结构体。
  3. struct tm *gmtime(const time_t *timer): 将 time_t(时间戳)转换为 UTC (GMT) 时间的 struct tm 结构体。
  4. char *asctime(const struct tm *timeptr): 将 struct tm 结构体转换为易读的字符串(格式固定,如 "Wed Jun 30 21:49:08 1993\n")。
  5. size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr): 最推荐,将 struct tm 结构体按照你指定的格式转换为字符串,非常灵活。

使用 localtimeasctime(简单但不灵活)

这是最直接的方法,但缺点是输出的格式是固定的,无法自定义。

#include <stdio.h>
#include <time.h>
int main() {
    // 1. 假设我们有一个 Unix 时间戳
    time_t timestamp = 1678886400; // 对应北京时间 2025-03-15 08:00:00
    // 2. 使用 localtime 将时间戳转换为本地时间的 tm 结构体
    //    注意:localtime 不是线程安全的,在多线程程序中应使用 localtime_r
    struct tm *local_tm = localtime(&timestamp);
    if (local_tm == NULL) {
        perror("localtime failed");
        return 1;
    }
    // 3. 使用 asctime 将 tm 结构体转换为字符串
    //    asctime 会返回一个类似 "Wed Mar 15 08:00:00 2025\n" 的字符串
    char *time_str = asctime(local_tm);
    // 4. 打印结果
    printf("Unix Timestamp: %ld\n", timestamp);
    printf("Converted Time (using asctime): %s", time_str); // 注意 asctime 会自带换行符
    return 0;
}

输出:

Unix Timestamp: 1678886400
Converted Time (using asctime): Wed Mar 15 08:00:00 2025

使用 localtimestrftime(推荐,最灵活)

这是最常用和最推荐的方法,因为它允许你完全自定义输出日期和时间的格式。

c语言 unix时间戳 转换
(图片来源网络,侵删)

strftime 的格式化字符( 开头)与 printf 类似,但专门用于时间:

  • %Y: 4位年份 (e.g., 2025)
  • %m: 2位月份 (01-12)
  • %d: 2位日期 (01-31)
  • %H: 24小时制的小时 (00-23)
  • %M: 分钟 (00-59)
  • %S: 秒 (00-60)
  • %F: 等同于 %Y-%m-%d
  • %T: 等同于 %H:%M:%S
  • 等等...
#include <stdio.h>
#include <time.h>
int main() {
    // 1. 定义一个 Unix 时间戳
    time_t timestamp = 1678886400; // 2025-03-15 08:00:00 UTC
    // 2. 定义一个足够大的字符数组来存储结果字符串
    char time_str[80];
    // 3. 使用 localtime 将时间戳转换为 tm 结构体
    struct tm *local_tm = localtime(&timestamp);
    if (local_tm == NULL) {
        perror("localtime failed");
        return 1;
    }
    // 4. 使用 strftime 进行格式化转换
    //    格式: "YYYY-MM-DD HH:MM:SS"
    //    strftime 会返回写入的字符数,如果空间不足则返回 0
    if (strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", local_tm) == 0) {
        printf("strftime failed: buffer too small or other error.\n");
        return 1;
    }
    // 5. 打印结果
    printf("Unix Timestamp: %ld\n", timestamp);
    printf("Converted Time (using strftime): %s\n", time_str);
    // --- 更多格式化示例 ---
    // 格式: "Wednesday, March 15, 2025"
    strftime(time_str, sizeof(time_str), "%A, %B %d, %Y", local_tm);
    printf("Formatted as (Day, Month Name, Year): %s\n", time_str);
    return 0;
}

输出:

Unix Timestamp: 1678886400
Converted Time (using strftime): 2025-03-15 08:00:00
Formatted as (Day, Month Name, Year): Wednesday, March 15, 2025

处理 UTC 时间(使用 gmtime

如果你的时间戳代表的是 UTC 时间,并且你想直接显示 UTC 时间(而不是转换为本地时区),应该使用 gmtime 而不是 localtime

#include <stdio.h>
#include <time.h>
int main() {
    // 这个时间戳代表 2025-03-15 08:00:00 UTC
    time_t timestamp = 1678886400;
    // 使用 gmtime 转换为 UTC 的 tm 结构体
    struct tm *utc_tm = gmtime(&timestamp);
    if (utc_tm == NULL) {
        perror("gmtime failed");
        return 1;
    }
    char time_str[80];
    // 格式化并打印 UTC 时间
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S UTC", utc_tm);
    printf("UTC Time: %s\n", time_str);
    // 为了对比,我们同时打印本地时间
    struct tm *local_tm = localtime(&timestamp);
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %Z", local_tm); // %Z 会打印时区缩写,如 CST
    printf("Local Time (e.g., in China): %s\n", time_str);
    return 0;
}

输出(假设你在中国,时区为 CST,UTC+8):

c语言 unix时间戳 转换
(图片来源网络,侵删)
UTC Time: 2025-03-15 08:00:00 UTC
Local Time (e.g., in China): 2025-03-15 16:00:00 CST

可以看到,UTC 时间和北京时间正好相差8小时。


重要注意事项

  1. time_t 的范围

    • time_t 在不同的系统上可能是 intlong,在现代64位系统上,它通常是64位的 long long,可以处理到“year 292,277,026,596”,但在一些旧的32位系统上,它是32位的 int,将在 2038年1月19日 达到上限,导致“2038年问题”,如果你的应用需要处理非常遥远的未来或过去的时间,需要使用更高级的库,如 libtld 或直接处理64位整数。
  2. 线程安全

    • localtimeasctime 函数使用内部静态缓冲区来返回结果,这意味着它们不是线程安全的,如果在多线程中调用,一个线程的结果可能会被另一个线程覆盖。
    • 解决方案:使用它们的 "reentrant"(可重入)版本:
      • localtime_r 替代 localtime
      • asctime_r 替代 asctime
    • gmtimestrftime 本身就是线程安全的。

    localtime_r 的用法示例:

    // struct tm local_tm;
    // localtime_r(&timestamp, &local_tm); // 结果直接存入 local_tm 变量
    // char *time_str = asctime_r(&local_tm, time_str_buffer);
  3. 错误处理

    • 总是检查 localtimegmtime 的返回值是否为 NULL,如果输入的时间戳超出了 struct tm 能表示的范围(例如在32位系统上处理一个超出32位范围的时间戳),它们会返回 NULL
方法 优点 缺点 适用场景
localtime + asctime 代码简单,一行搞定 格式固定,不可自定义;线程不安全 快速调试,对格式无要求的简单脚本
localtime + strftime 高度灵活,可自定义任意格式;strftime 是线程安全的 代码稍长 绝大多数生产环境应用的首选
gmtime + strftime 处理 UTC 时间,不受本地时区影响 需要明确知道时间戳是 UTC 需要显示标准时间、日志记录、网络通信等

对于任何严肃的 C 语言项目,强烈推荐使用 localtime (或 localtime_r) 结合 strftime 的方法,它提供了最佳的灵活性和安全性。

-- 展开阅读全文 --
头像
dede搜索框如何实现关键字搜索功能?
« 上一篇 今天
C语言中a=y的方程如何定义与使用?
下一篇 » 今天

相关文章

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

目录[+]