На Linux я должен найти в настоящее время настраиваемый часовой пояс как местоположение Olson. Я хочу, чтобы мой (C или C++) код был портативным к как можно большему количеству систем Linux.
Например. Я живу в Лондоне, таким образом, моим текущим местоположением Olson является "Европа/Лондон". Я не интересуюсь идентификаторами часового пояса как "BST", "EST" или что бы то ни было.
Debian и Ubuntu имеют файл /etc/timezone
это содержит эту информацию, но я не думаю, что могу полагаться на тот файл, всегда являющийся там, не так ли? Gnome имеет функцию oobs_time_config_get_timezone()
который также возвращает правильную строку, но я хочу, чтобы мой код работал над системами без Gnome.
Так, что лучший общий путь состоит в том, чтобы получить в настоящее время настраиваемый часовой пояс как местоположение Olson на Linux?
Получить надежный ответ сложно. Лучше всего полагаться на такие вещи, как /etc/timezone
.
(Переменная tzname
и член tm_zone
в struct tm
, как предлагается в других ответах, обычно содержит сокращение, такое как GMT
/BST
и т.д., а не строку времени Олсона, как запрашивается в вопросе).
/etc/timezone
- это файл, содержащий правильный ответ. /etc/localtime
, который является симлинком на (например) /usr/share/zoneinfo/Europe/London
. Однако, есть некоторые проблемы с вышеуказанными подходами. Каталог /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...)
Согласно этой странице, похоже, что если вы #include
объявите следующее.
void tzset (void);
extern char *tzname[2];
extern long timezone;
extern int daylight;
Это дает вам необходимую информацию?
В Linux мне нужно найти текущий часовой пояс в качестве местоположения Олсона. Я хочу, чтобы мой код (C или C ++) был переносимым на как можно больше систем Linux.
Если вы хотите быть портативным, используйте для внутренних целей только GMT. Из-за многопользовательского режима системные часы * NIX обычно находятся в GMT, и нет общесистемного часового пояса, потому что разные пользователи, подключенные к системе, могут жить в разных часовых поясах.
Пользовательский часовой пояс отражен в переменной среды TZ
, и вам может потребоваться использовать ее только при преобразовании внутренней даты / времени в читаемую пользователем форму. В противном случае localtime ()
позаботится об этом автоматически.
Так как tzselect никем не упоминался и вам действительно нужно решение, почти защищенное от дурака, работайте с тем, что сделал Олсон. Получите файлы tzcode и tzdata от elsie, а также файлы вкладок.
В марте 2017 года правильным местом для загрузки будет ftp://ftp.iana.org/tz/releases (и загрузите tzcode2017a.tar.gz
и tzdata2017a.tar.gz
).
Затем получите tzselect.ksh из загрузки glibc. Затем вы увидите, как реконструировать часовые пояса.Один камень преткновения: иногда вам придется спрашивать, в какой стране и городе находится Linux-система. Вы можете сериализовать эти данные, если хотите, а затем сверить их с данными о часовом поясе, которые вы можете найти.
Невозможно делать это постоянно и надежно без возможности вмешательства пользователя, например, как часть установки программы.
Удачи в Аризоне в целом и в Западной Индиане ... надеюсь, ваш код будет работать где-нибудь еще.
Для этого не существует стандартной функции 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 */
};
Не совсем то, что вы просили, но близко ...