Расстояние UTC - LocalTime в Linux - PullRequest
4 голосов
/ 12 ноября 2010

Я пишу приложение для Linux (Ubuntu и Debian Lenny) на C ++.

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

Кто-нибудь знает, как это сделать?

Редактировать: Читая первый ответ, я думаю, что меня неправильно поняли: я не хочу сравнивать даты / время. У меня есть значения даты / времени, которые я хочу преобразовать из UTC в местное время.

Ответы [ 3 ]

3 голосов
/ 12 ноября 2010

Подготовьте структуру тм с датой:

struct tm date;
memset(&date,0,sizeof(date));
date.tm_year = year - 1900;
date.tm_mon = month - 1;
date.tm_mday = day;
date.tm_hour = hour;
date.tm_min = minute;
date.tm_sec = second;
date.tm_isdst = -1; // VERY IMPORTANT

mktime(&date); /// fill rest of fields

А затем взгляните на tm_gmtoff

printf("%d\n",date.tm_gmtoff);

Это расстояние от UTC.

Теперь это специфично для Linux и BSD, это не будет работать на других системах, и это работает по ДСТ.

Читайте man mktime для получения дополнительной информации. И заполнение struct tm правильными значениями

П.С .: Преобразование из UTC в Локальное и обратно?

time_t posix_time = timegm(&UTC_Filled_struct_tm); // Linux specific line
localtime_r(&posix_time,&local_Filled_struct_tm);

Местный до UTC

time_t posix_time = mktime(&local_Filled_struct_tm);
gmtime_r(&posix_time,&UTC_Filled_struct_tm);
2 голосов
/ 12 ноября 2010

Я думаю, что вы можете получить выгоду от использования Boost.DateTime или ICU .

Что касается Boost.DateTime, tt может выглядеть следующим образом:

1) Вы подготавливаете базу данных с информацией о часовом поясе Boost.Datetime и создаете часовой пояс.Часовые пояса важны, поскольку они содержат информацию о DST

tz_database tz_db;
tz_db.load_from_file("./date_time_zonespec.csv");
time_zone_ptr nyc = tz_db.time_zone_from_region("America/New_York"); // or other timezone


Или просто создайте часовой пояс, подобный этому.

std::string kaliningrad_string = "EET+02:00:00EEST+01:00:00,M3.5.0/02:00:00,M10.5.0/03:00:00";
boost::local_time::time_zone_ptr kaliningrad_tzone_posix(new boost::local_time::posix_time_zone(kaliningrad_string));
std::string vladivostok_string = "VLAT+10:00:00VLAST+01:00:00,M3.5.0/02:00:00,M10.5.0/03:00:00";
boost::local_time::time_zone_ptr vladivostok_tzone_posix(new boost::local_time::posix_time_zone(vladivostok_string));

Создание часовых поясов с использованиемСтроковая спецификация часовых поясов выглядит более сложной, но вы можете использовать ее, если не можете найти определенный часовой пояс в date_time_zonespec.csv.Например, Самара раньше была в UTC + 4 до марта 2010 года, а теперь она в UTC + 3.date_time_zonespec.csv не имеет истории изменений, поэтому в этой ситуации необходимо создать часовой пояс из спецификации строки.Однако я напоминаю, что у ICU, похоже, есть часовые пояса с такой историей Классы часовых поясов ICU :

Данные о часовых поясах часто изменяются в ответ на изменения правительствами по всему миру в своих местных правилах иобласти, где они применяются.Данные о часовом поясе ICU обновляются для каждого выпуска, и самым простым способом оставаться в курсе может быть обновление до последнего выпуска ICU, который также предоставляет исправления ошибок, улучшения кода и дополнительные функции.


3) Создайте нужное местное время, например,

local_date_time tmp(boost::gregorian::date(2010, 3, 28), boost::posix_time::time_duration(1,59,0),nyc, boost::local_time::local_date_time::EXCEPTION_ON_ERROR);

4) И затем вычислите разницу, используя функции utc_time и local_time
.страница:

ptime pt(date(2004,Nov,5), 
         hours(10));
time_zone_ptr zone(new posix_time_zone("MST-07"));
local_date_time az(pt, zone);
az.utc_time(); // 10am 2004-Nov-5
az.local_time(); // 3am 2004-Nov-5


5) Еще один пример.Местное время такое же, но UTC другое

local_date_time tmp(boost::gregorian::date(2010, 3, 28), boost::posix_time::time_duration(1,59,0),kaliningrad_tzone_posix, boost::local_time::local_date_time::EXCEPTION_ON_ERROR);
std::cout << "As is: " << tmp << ", UTC: "  << tmp.utc_time() << std::endl;

local_date_time tmp(boost::gregorian::date(2010, 3, 28), boost::posix_time::time_duration(1,59,0),vladivostok_tzone_posix, boost::local_time::local_date_time::EXCEPTION_ON_ERROR);
std::cout << "As is: " << tmp << ", UTC: "  << tmp.utc_time() << std::endl;
0 голосов
/ 12 ноября 2010

Убедитесь, что все времена преобразованы в UTC (см., Например, mktime()).Затем вы можете использовать либо difftime () , либо пример функции timeval_subtract из той же ссылки, в зависимости от того, в какой структуре хранится время.

...