使用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 變量對父進程不起作用。