Как я нахожу часовой пояс существующей системы?

На Linux я должен найти в настоящее время настраиваемый часовой пояс как местоположение Olson. Я хочу, чтобы мой (C или C++) код был портативным к как можно большему количеству систем Linux.

Например. Я живу в Лондоне, таким образом, моим текущим местоположением Olson является "Европа/Лондон". Я не интересуюсь идентификаторами часового пояса как "BST", "EST" или что бы то ни было.

Debian и Ubuntu имеют файл /etc/timezone это содержит эту информацию, но я не думаю, что могу полагаться на тот файл, всегда являющийся там, не так ли? Gnome имеет функцию oobs_time_config_get_timezone() который также возвращает правильную строку, но я хочу, чтобы мой код работал над системами без Gnome.

Так, что лучший общий путь состоит в том, чтобы получить в настоящее время настраиваемый часовой пояс как местоположение Olson на Linux?

23
задан Tobu 21 January 2015 в 14:44
поделиться

5 ответов

Получить надежный ответ сложно. Лучше всего полагаться на такие вещи, как /etc/timezone.

(Переменная tzname и член tm_zone в struct tm, как предлагается в других ответах, обычно содержит сокращение, такое как GMT/BST и т.д., а не строку времени Олсона, как запрашивается в вопросе).

  • В системах на базе Debian (включая Ubuntu), /etc/timezone - это файл, содержащий правильный ответ.
  • На некоторых системах на базе Redhat (включая, по крайней мере, некоторые версии CentOS, RHEL, Fedora), вы можете получить необходимую информацию, используя readlink() на /etc/localtime, который является симлинком на (например) /usr/share/zoneinfo/Europe/London.
  • OpenBSD, похоже, использует ту же схему, что и RedHat.

Однако, есть некоторые проблемы с вышеуказанными подходами. Каталог /usr/share/zoneinfo также содержит такие файлы, как GMT и GB, поэтому пользователь может настроить симлинк так, чтобы он указывал туда.

Также ничто не мешает пользователю вместо создания симлинка скопировать туда нужный файл с временными зонами.

Одна из возможностей обойти это (которая, кажется, работает в Debian, RedHat и OpenBSD) - сравнить содержимое файла /etc/localtime с файлами в /usr/share/zoneinfo, и посмотреть, какие из них совпадают:

eta:~% md5sum /etc/localtime
410c65079e6d14f4eedf50c19bd073f8  /etc/localtime
eta:~% find /usr/share/zoneinfo -type f | xargs md5sum | grep 410c65079e6d14f4eedf50c19bd073f8
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/London
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Belfast
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Guernsey
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Jersey
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Isle_of_Man
...
...

Конечно, недостатком является то, что это покажет вам все часовые пояса, которые идентичны текущему. (Это означает идентичны в полном смысле - не только "в настоящее время в одно и то же время", но и "всегда переводят часы в один и тот же день, насколько известно системе". )

Лучшим вариантом может быть комбинирование вышеуказанных методов: используйте /etc/timezone, если он существует; в противном случае попробуйте разобрать /etc/localtime как симлинк; если это не удастся, ищите подходящие файлы определения часовых поясов; если это не удастся - сдавайтесь и идите домой ;-)

(И я понятия не имею, применимо ли что-либо из вышеперечисленного на AIX...)

24
ответ дан 29 November 2019 в 01:38
поделиться

Согласно этой странице, похоже, что если вы #include объявите следующее.

void tzset (void);
extern char *tzname[2];
extern long timezone;
extern int daylight;

Это дает вам необходимую информацию?

0
ответ дан 29 November 2019 в 01:38
поделиться

В Linux мне нужно найти текущий часовой пояс в качестве местоположения Олсона. Я хочу, чтобы мой код (C или C ++) был переносимым на как можно больше систем Linux.

Если вы хотите быть портативным, используйте для внутренних целей только GMT. Из-за многопользовательского режима системные часы * NIX обычно находятся в GMT, и нет общесистемного часового пояса, потому что разные пользователи, подключенные к системе, могут жить в разных часовых поясах.

Пользовательский часовой пояс отражен в переменной среды TZ , и вам может потребоваться использовать ее только при преобразовании внутренней даты / времени в читаемую пользователем форму. В противном случае localtime () позаботится об этом автоматически.

0
ответ дан 29 November 2019 в 01:38
поделиться

Так как tzselect никем не упоминался и вам действительно нужно решение, почти защищенное от дурака, работайте с тем, что сделал Олсон. Получите файлы tzcode и tzdata от elsie, а также файлы вкладок.

ftp://elsie.nci.nih.gov

В марте 2017 года правильным местом для загрузки будет ftp://ftp.iana.org/tz/releases (и загрузите tzcode2017a.tar.gz и tzdata2017a.tar.gz ).

Затем получите tzselect.ksh из загрузки glibc. Затем вы увидите, как реконструировать часовые пояса.Один камень преткновения: иногда вам придется спрашивать, в какой стране и городе находится Linux-система. Вы можете сериализовать эти данные, если хотите, а затем сверить их с данными о часовом поясе, которые вы можете найти.

Невозможно делать это постоянно и надежно без возможности вмешательства пользователя, например, как часть установки программы.

Удачи в Аризоне в целом и в Западной Индиане ... надеюсь, ваш код будет работать где-нибудь еще.

0
ответ дан 29 November 2019 в 01:38
поделиться

Для этого не существует стандартной функции c или c ++. Однако у GNU libc есть расширение. его структура struct tm имеет два дополнительных члена:

long tm_gmtoff;           /* Seconds east of UTC */
const char *tm_zone;      /* Timezone abbreviation */

Это означает, что если вы используете одну из функций, которая заполняет структуру struct tm (например, localtime или gmtime ) вы можете использовать эти дополнительные поля. Конечно, это возможно только в том случае, если вы используете GNU libc (и ее достаточно свежую версию).

Также во многих системах есть функция int gettimeofday (struct timeval * tv, struct timezone * tz); (POSIX), которая заполняет структуру struct timezone . Здесь есть следующие поля:

struct timezone {
    int tz_minuteswest;     /* minutes west of Greenwich */
    int tz_dsttime;         /* type of DST correction */
};

Не совсем то, что вы просили, но близко ...

6
ответ дан 29 November 2019 в 01:38
поделиться