You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将描述UTC日期的struct tm转换为time_t值?

你说得没错,C标准库的mktime()确实只处理本地时间,没法直接把UTC的struct tm转成time_t。不过有几种可靠的方法来解决这个问题,我按推荐程度给你列出来:

1. 使用POSIX标准的timegm()函数

这是最直接的方案,timegm()就是mktime()的UTC版本——它会把传入的struct tm当作UTC时间来解析,直接返回对应的time_t值,不需要手动调整时区。

举个简单的例子:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 构造一个UTC时间:2024年5月20日12:30:00
    struct tm utc_tm = {0};
    utc_tm.tm_year = 2024 - 1900; // struct tm的年份是从1900开始算的偏移量
    utc_tm.tm_mon = 5 - 1;        // 月份从0(1月)到11(12月)
    utc_tm.tm_mday = 20;
    utc_tm.tm_hour = 12;
    utc_tm.tm_min = 30;
    utc_tm.tm_sec = 0;
    utc_tm.tm_isdst = 0;          // 明确禁用夏令时(UTC没有夏令时)

    time_t utc_time = timegm(&utc_tm);
    if (utc_time == (time_t)-1) {
        perror("Failed to convert UTC tm to time_t");
        return EXIT_FAILURE;
    }

    printf("UTC time as time_t: %lld\n", (long long)utc_time);
    return EXIT_SUCCESS;
}

注意:timegm()是POSIX标准的函数,不是C标准的一部分。所以在Windows平台上,你需要用微软提供的_mkgmtime()函数,用法和timegm()几乎一致。

2. 手动临时切换时区(跨平台兼容方案)

如果你的代码需要在不支持timegm()的系统上运行,可以通过临时修改时区环境变量,让mktime()误以为当前时区是UTC,完成转换后再恢复原时区。

示例代码如下:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

time_t utc_tm_to_time_t(struct tm *utc_tm) {
    // 保存原有的时区设置
    char *old_tz = getenv("TZ");
    char *saved_tz = NULL;
    if (old_tz != NULL) {
        saved_tz = strdup(old_tz);
        if (saved_tz == NULL) {
            return (time_t)-1;
        }
    }

    // 设置时区为UTC(空字符串表示UTC)
    if (setenv("TZ", "", 1) != 0) {
        free(saved_tz);
        return (time_t)-1;
    }
    tzset(); // 让时区设置立即生效

    // 明确禁用夏令时,然后调用mktime
    utc_tm->tm_isdst = 0;
    time_t result = mktime(utc_tm);

    // 恢复原有时区
    if (old_tz != NULL) {
        setenv("TZ", saved_tz, 1);
        free(saved_tz);
    } else {
        unsetenv("TZ");
    }
    tzset();

    return result;
}

int main() {
    struct tm utc_tm = {0};
    utc_tm.tm_year = 2024 - 1900;
    utc_tm.tm_mon = 5 - 1;
    utc_tm.tm_mday = 20;
    utc_tm.tm_hour = 12;
    utc_tm.tm_min = 30;
    utc_tm.tm_sec = 0;

    time_t utc_time = utc_tm_to_time_t(&utc_tm);
    if (utc_time == (time_t)-1) {
        perror("Conversion failed");
        return EXIT_FAILURE;
    }

    printf("UTC time as time_t: %lld\n", (long long)utc_time);
    return EXIT_SUCCESS;
}

注意事项:

  • 这种方法依赖环境变量TZ,不是线程安全的——如果多个线程同时修改TZ,会导致冲突。如果是多线程程序,你可能需要用线程本地存储(TLS)或者同步机制来保护这个操作。
  • 一定要记得恢复原时区,否则会影响后续依赖时区的函数调用。
3. 不推荐:手动计算time_t

我强烈不建议自己手动计算time_t,因为要处理闰年、闰秒、不同月份的天数等复杂规则,很容易出错,而且不同平台的time_t定义可能有差异(比如32位和64位)。除非万不得已,否则尽量用库函数来处理。

内容的提问来源于stack exchange,提问作者Andreas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:09:26