系统使用的时区如何确定

4
我正在编写一些需要了解系统中哪个时区处于活动状态的代码(我正在使用Linux操作系统):
  • 我的第一个方法是检查TZ环境变量,它为空,除非我设置它(例如调用tzset函数)。

  • 之后,我尝试使用extern long timezone(time.h),但这个变量始终为0。

  • 最后,我计算了我的时区和UTC +0之间的差异,但我没有得到我的真实时区,因为我不知道是否应用夏令时。

我相信有一种更简单(而且最一致)的方法来实现这一点。我正在寻找类似于“Europe/Paris”或“UTC +2”之类的东西。
任何帮助将不胜感激!

1
https://dev59.com/z2Yr5IYBdhLWcg3wR4Qs - David Ranieri
@KeineLust 谢谢,但我想要的是时区而不是相对于 GMT 的当前偏移量。无论如何,这是一个好的线索。 - Joan Esteban
这是我正在使用的代码:https://github.com/HowardHinnant/date/blob/master/tz.cpp#L3030-L3097 这是C++代码,但你可以很容易地将其翻译成C。 - Howard Hinnant
3个回答

3
作为起点,我建议这样做:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
  char str[64];
  time_t timer;
  struct tm * ptm;
  timer = time(NULL);
  ptm = localtime(&timer); 
  strftime(str, sizeof(str), "%Z", ptm);
  printf("TZ: %s\n", str);
  return(0);
}

1
我认为 sizeof(str-1) 不是你想象中的那样。 - unwind
这几乎是我想要的!我得到了巴黎的“CET”,纽约的“EST”和哥斯达黎加的“CST”。 - Joan Esteban
1
减1是不必要的。strftime(str, sizeof str , "%Z", ptm);没问题。最好检查它的返回值。 - chux - Reinstate Monica
@JoanEsteban 这个答案为什么不是你想要的呢?如果结果是“CET”,那么这就是代码理解的时区名称。该名称不是“Europe/Paris”。在另一个系统上,代码可能会返回“Europe/Paris”,因为那个系统上的名称是这样的。你是如何将你的系统设置为“Paris”的呢?也许这就是短板所在? - chux - Reinstate Monica
1
@Joan。如果你想更深入地了解,你需要使用所谓的Olson数据库(以Arthur David Olson命名),位于/usr/share/zoneinfo中。例如,在Olson数据库中,你的/etc/localtime应该是指向时区的符号链接,如Asia/Tokyo。通过几个系统调用,你可以轻松追踪到这一点。这不适用于有限的嵌入式Linux系统,在这些系统中仍然使用缩写形式的POSIX TZ字符串(如EST5EDT,M03.2.0,M11.1.0)。 - Djee

1

选项1)

在调用tzset()之后,timezone和tzname可能会可用:

cout << "Before tzset: " << timezone << " " << tzname[0] << " " << tzname[1] << endl;
tzset();
cout << "After tzset: " << timezone << " " << tzname[0] << " " << tzname[1] << endl;

输出结果(今天,在欧洲):

Before tzset: 0 GMT GMT
After tzset: -3600 CET CEST

选项2)一些版本的 "struct tm"(GNU、BSD等)包含字段 "tm_zone" 和 "tm_isdst":

time_t timer;
struct tm *ptm;

timer = time(NULL);
ptm = localtime( &timer );
cout << ptm->tm_zone <<  " " << ptm->tm_isdst << endl;

timer -= 60*24*3600; // 60 days ago
ptm = localtime( &timer );
cout << ptm->tm_zone <<  " " << ptm->tm_isdst << endl;

输出:

CET 0
CEST 1

0

date +%Z 命令显示当前时区,但实际上您想要的是正确设置它。首先删除当前时区文件:

# rm -f /etc/localtime

然后设置您所在时区的正确时间:

# ln -s /usr/share/zoneinfo/<your-time-zone-here> /etc/localtime

执行 ls /usr/share/zoneinfo/ 命令以查看可用的时区。对于我来说,它是 /usr/share/zoneinfo/Europe/Amsterdam

然后使用上述提到的 date 命令进行验证。


那不是我要问的,我已经用几个时区来检查我的代码了,但我想从C程序中获取我的时区(当然,我无法读取/etc/localtime链接,因为它并不总是一个链接)。 - Joan Esteban

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接