使用settimeofday 设置时区不起作用,代码如下:
void show_time(struct tm *p_tm)
{
printf("%d-%02d-%02d %02d:%02d:%02d\n",
p_tm->tm_year+1900,p_tm->tm_mon+1,p_tm->tm_mday,
p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec);
}
int set_time(struct tm *p_tm,int tzone)
{
struct timeval tv;
struct timezone tz;
tv.tv_sec = mktime(p_tm);
tv.tv_usec = 0;
tz.tz_minuteswest = tzone*-60;
tz.tz_dsttime = 0;
DEBUG_PRINT("tz:%d\n",tz.tz_minuteswest);
if(settimeofday(&tv, &tz)<0)
{
DEBUG_PRINT("settimeofday failed!\n");
return -1;
}
time_t now;
time(&now);
struct tm t_tm;
localtime_r(&now, &t_tm); //换算成本地时间以验证时区是否设置成功
show_time(&t_tm);
return 0;
}
测试设置时间:2019-03-21 8:00:00 tzone = 8
期望打印时间:2019-03-21 16:00:00
实际打印时间:2019-03-21 8:00:00
内核版本:3.18.21
从实际打印时间看出,时区设置不生效,到底是为什么呢?
查看手册,man settimeofday 发现
The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL.
timezone structure 的作用已经被废弃,tz 参数一般要设为NULL
好吧,被废弃了?也不知道是从哪个版本开始废弃的。
那么还有什么办法可以设置时区?
使用 tzset ,使用tzset 前需要设置TZ 环境变量。
void set_tz(int tz)
{
char tzstr[256] = {0};
int tzhour = -tz;
snprintf(tzstr,sizeof(tzstr),"GMT%+02d",tzhour);
if(setenv("TZ", tzstr, 1)!=0)
{
DEBUG_PRINT("setenv failed \n");
}
DEBUG_PRINT("time zone:%s\n",tzstr);
tzset();
}
int set_time(struct tm *p_tm,int tzone)
{
struct timeval tv;
struct timezone tz;
tv.tv_sec = mktime(p_tm);
tv.tv_usec = 0;
tz.tz_minuteswest = tzone*-60;
tz.tz_dsttime = 0;
DEBUG_PRINT("tz:%d\n",tz.tz_minuteswest);
if(settimeofday(&tv, &tz)<0)
{
DEBUG_PRINT("settimeofday failed!\n");
return -1;
}
set_tz(tzone);
time_t now;
time(&now);
struct tm t_tm;
localtime_r(&now, &t_tm);
show_time(&t_tm);
return 0;
}
测试设置时间:2019-03-21 8:00:00 tzone = 8
期望打印时间:2019-03-21 16:00:00
实际打印时间:2019-03-21 16:00:00 (符合期望!)
这下是正确了!但是在中断中用date 命令查看时间,结果却还是时区不生效!
#date
#Thu Mar 21 8:02:48 GMT 2019
这是为什么呢?
查了很多文章,终于找到了最佳答案:
Linux在C语言下的时区设置与修改(三) - chinaclock的专栏 - CSDN博客
https://blog.csdn.net/chinaclock/article/details/43795651
总结来说就是:子进程里的TZ 变量对父进程不起作用。