计算时区函数gmt2local(time_t t)

本文深入解析了TCPdump源码中的gmt2local函数,该函数通过gmtime()和localtime()计算GMT与本地时间的差值。文章详细阐述了如何判断跨越00:00GMT时的日期差异,并通过具体示例解释了代码实现细节。

以下函数摘自tcpdump源码,用于计算时区

 

 

对上述其他好理解,下面这段比较费解

dir = loc->tm_year - gmt->tm_year;
 if (dir == 0)
  dir = loc->tm_yday - gmt->tm_yday;
 dt += dir * 24 * 60 * 60;

 

 

分析如下:

时区最多是相差24个小时,也就是一天,而且本地时间一定会>=GMT时间(反正不是>=就是<=,先按>=解释)

假设GMT时间为  1998.12.31.23:00
LOCAL时间为    1999.1.1.1:00

这段代码
dir = loc->tm_year - gmt->tm_year;
if (dir == 0)
dir = loc->tm_yday - gmt->tm_yday;
dt += dir * 24 * 60 * 60;

表示,如果dir = loc->tm_year - gmt->tm_year;差一年,则说明两个时间的天一定是不一样的,如果从LOCAL时间中借位一天,即
LOCAL时间变为1998.12.31.(1:00+24:00)=1998.12.31.25:00
则两个时间减下就能算出时区

如果年一样的话dir = loc->tm_yday - gmt->tm_yday;表示天的差异,这是dir不是0就是1,是0的话直接算出时区,是1的话相当于从天这借位,换算成小时和分钟,同样可以算出时区

 

如果说为什么没有加上loc->tm_sec- gmt->tm_sec,我想时区一般是1个时区,半个时区算的,秒算上没有多大意义。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> int main() { // 示例输入:带时区的日期时间字符串(格式:YYYY-MM-DD HH:MM:SS +HHMM) const char *input_time = "2023-10-05 14:30:00 +0800"; // 解析输入字符串 struct tm tm_time = {0}; char timezone_sign; int tz_hour, tz_min; int offset_seconds; // 使用sscanf解析字符串 if (sscanf(input_time, "%d-%d-%d %d:%d:%d %c%02d%02d", &tm_time.tm_year, &tm_time.tm_mon, &tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min, &tm_time.tm_sec, &timezone_sign, &tz_hour, &tz_min) != 9) { fprintf(stderr, "解析失败\n"); return 1; } // 调整tm结构:年从1900起计,月从0起计 tm_time.tm_year -= 1900; tm_time.tm_mon -= 1; tm_time.tm_isdst = -1; // 自动判断夏令时 // 计算时区偏移秒数(东区为正,西区为负) offset_seconds = (timezone_sign == '+' ? 1 : -1) * (tz_hour * 3600 + tz_min * 60); // 方法1:直接计算UTC时间戳(可移植性方法) time_t timestamp = mktime(&tm_time) - offset_seconds - timezone * 60; // 注意:此处需考虑系统时区,以下提供更可靠的方法 // 方法2:设置时区后使用mktime(更准确) // 保存当前时区 char *old_tz = getenv("TZ"); // 设置临时时区为UTC setenv("TZ", "UTC", 1); tzset(); // 使用timegm函数(非标准但常见)或手动调整 time_t utc_timestamp = mktime(&tm_time) - offset_seconds; // 恢复原始时区 if (old_tz) { setenv("TZ", old_tz, 1); } else { unsetenv("TZ"); } tzset(); // 转换为本地时间结构体 struct tm *local_tm = localtime(&utc_timestamp); char local_buf[64]; strftime(local_buf, sizeof(local_buf), "%Y-%m-%d %H:%M:%S %Z", local_tm); // 输出结果 printf("UTC时间戳: %ld\n", (long)utc_timestamp); printf("本地时间: %s\n", local_buf); return 0; }
09-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值