Подтвердить что ты не робот

Как получить текущий часовой пояс?

В большинстве примеров, которые я видел:

time_zone_ptr zone( new posix_time_zone("MST-07") ); 

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

4b9b3361

Ответ 1

Plain posix: вызвать tzset, использовать tzname.

#include <ctime>
tzset();
time_zone_ptr zone(new posix_time_zone(tzname[localtime(0)->tm_isdst]));

Posix с glibc/bsd дополнения:

time_zone_ptr zone(new posix_time_zone(localtime(0)->tm_zone));

Вышеуказанные сокращены временные интервалы Posix, определенные с точки зрения смещения от UTC и не стабильные с течением времени (там более длинная форма, которая может включать DST, но не политические и исторические переходы).

ICU является портативным и имеет логику для извлечения системного часового пояса в качестве часового пояса Олсона (фрагмент sumwale):

// Link with LDLIBS=`pkg-config icu-i18n --libs`
#include <unicode/timezone.h>
#include <iostream>

using namespace U_ICU_NAMESPACE;

int main() {
  TimeZone* tz = TimeZone::createDefault();
  UnicodeString us;
  std::string s;

  tz->getID(us);
  us.toUTF8String(s);
  std::cout << "Current timezone ID: " << s << '\n';
  delete tz;
}

В Linux ICU реализована для совместимости с tzset и выглядит TZ и /etc/localtime, что на последних Linux-системах подразумевается как символическая ссылка, содержащая идентификатор Olson (здесь история). Подробнее см. uprv_tzname.

Boost не знает, как использовать идентификатор Olson. Вы можете построить posix_time_zone, используя смещения, отличные от DST и DST, но на данный момент лучше продолжать использовать реализацию ICU. См. этот часто задаваемый вопрос.

Ответ 2

Довольно поздно, но я искал что-то подобное, так что, надеюсь, это поможет другим. На большинстве платформ работает следующий (неуправляемый) способ использования strftime:

  time_t ts = 0;
  struct tm t;
  char buf[16];
  ::localtime_r(&ts, &t);
  ::strftime(buf, sizeof(buf), "%z", &t);
  std::cout << "Current timezone: " << buf << std::endl;
  ::strftime(buf, sizeof(buf), "%Z", &t);
  std::cout << "Current timezone: " << buf << std::endl;

Или можно использовать std:: time_put для чистой версии С++.

Ответ 3

Ну, может быть, вы могли бы это сделать, используя библиотеку GeoIP. Я знаю, это немного перебор, но так как большинство компьютеров в мире подключены к Интернету, вы, возможно, сойдете с ним. По словам парня, с которым я развиваюсь, он был на 99% точным.

Примечание. Это глупая идея. Я просто растягиваю ответы.

Ответ 4

Чтобы правильно ответить на этот вопрос, важно понять, что поддержка часового пояса в Boost сильно ограничена.

  • В основном это касается часовых поясов POSIX, которые имеют несколько ограничений. Эти ограничения обсуждаются в разделе POSIX вики-метки часового пояса, поэтому я не буду повторять их здесь.

  • В нем есть функции, которые работают с идентификаторами часовых поясов IANA/Olson, но они искусственно сопоставляют их с значениями POSIX, что приводит к выравниванию часового пояса до одной точки в истории. Эти сопоставления хранятся в файле csv в исходном коде Boost.

  • Файл csv не обновляется с апреля 2011 года, и с тех пор было много изменений в часовых поясах. Таким образом, сопоставления, которые у него есть, несколько неточны.

В общем, я бы не рекомендовал Boost для работы с часовыми поясами. Вместо этого рассмотрите ICU TimeZone Classes, которые являются частью ICU. Вы обнаружите, что они полностью переносимы, и у них есть полная и правильная поддержка часовых поясов.

Следует отметить, что ICU используется во многих популярных приложениях. Например, веб-браузер Google Chrome получает поддержку часовых поясов от ICU.

В ICU текущий часовой пояс локальной системы доступен в качестве часового пояса по умолчанию. Вы можете прочитать больше в разделе "Factory Методы и часовой пояс по умолчанию" в документации ICU.

Ответ 5

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