获取当地时间

将时间戳转换为进程当前时区的当地时间;时区通常由 TZ 或系统默认时区决定。“TZ 时间”不是独立的时间标准。

localtime

time_t now = time(NULL);

struct tm *tm_now = localtime(&now);

printf("%04d-%02d-%02d %02d:%02d:%02d\n",
       tm_now->tm_year + 1900,
       tm_now->tm_mon + 1,
       tm_now->tm_mday,
       tm_now->tm_hour,
       tm_now->tm_min,
       tm_now->tm_sec);

localtime_r

适用于多线程,函数原型:

/*
功能:将 time_t 类型的时间戳(自 1970-1-1 的秒数)转换为本地时间的 struct tm 结构体。
	timep:指向 time_t 变量的指针。
	result(仅 localtime_r):用户提供的 struct tm 存储地址。
*/
struct tm *localtime_r(const time_t *timep, struct tm *result);

例程:

time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now);

获取UTC时间

gmtime

struct tm *gmtime(const time_t *timer);  // 非线程安全

gmtime_r

/*
功能:将 time_t 类型的时间戳(自 Epoch 的秒数)转换为UTC 时间(协调世界时)。
	timer:指向 time_t 变量的指针。
	result(仅 gmtime_r):用户提供的 struct tm 存储地址。

*/
struct tm *gmtime_r(const time_t *timer, struct tm *result); 
time_t now = time(NULL);  // 获取当前时间戳

struct tm tm_utc;  // 用户分配的存储空间

if (gmtime_r(&now, &tm_utc) == NULL) 
{
    perror("gmtime_r failed");
    return -1;
}

printf("UTC 时间:%04d-%02d-%02d %02d:%02d:%02d\n",
       tm_utc.tm_year + 1900, tm_utc.tm_mon + 1, tm_utc.tm_mday,
       tm_utc.tm_hour, tm_utc.tm_min, tm_utc.tm_sec);

本地时间转换为时间戳:mktime

把 struct tm 中的本地年月日时分秒按当前时区转换为 Unix 时间戳。下面示例显式设置 UTC+8,输出才对应北京时间;POSIX TZ 字符串中的符号方向与 UTC 偏移相反。

/* POSIX 示例:需要 <stdlib.h>、<time.h> 和 <stdio.h>。
   TZ 是进程级设置,应在启动阶段配置,避免多线程运行时反复修改。 */
if (setenv("TZ", "CST-8", 1) != 0) {
    perror("setenv");
    return -1;
}
tzset();
struct tm local = {0};

local.tm_year = 2026 - 1900;
local.tm_mon  = 10 - 1;
local.tm_mday = 10;
local.tm_hour = 12;
local.tm_min  = 0;
local.tm_sec  = 0;
local.tm_isdst = -1;

// 把本地时间转换为 Unix 时间戳
time_t timestamp = mktime(&local);

printf("timestamp = %lld\n", (long long)timestamp);

struct tm utc;
struct tm bj;

gmtime_r(&timestamp, &utc);
localtime_r(&timestamp, &bj);

printf("UTC: %02d:%02d\n", utc.tm_hour, utc.tm_min);
printf("BJ : %02d:%02d\n", bj.tm_hour, bj.tm_min);
/*
timestamp = 1791604800
UTC: 04:00
BJ : 12:00
*/