C ++ timegm преобразование DST в определенный часовой пояс в данный момент в будущем?

Мне нужно точное преобразование в моем классе из времени UTC в местное время данного часового пояса, с действующим или без DST. Моя проблема в том, что когда я использую struct tm Я должен предоставить член tm_isdst или оставить его -1, который будет определен автоматически.

from mktime(3) - linux man page:
"The value specified in the tm_isdst field informs mktime() whether or not daylight saving time (DST) is in effect for the time supplied in the tm structure:
a positive value means DST is in effect;
zero means that DST is not in effect;
and a negative value means that mktime() should (use timezone information and system databases to) attempt to determine whether DST is in effect at the specified time.

Теперь вот моя проблема. Я работаю с биржами со всего мира (из Чикаго, Нью-Йорка, Сан-Паулу, Мельбурна, Буэнос-Айреса, Йоханнесбурга, Шанхая, Сеула …). У меня есть таблица с названием каждого часового пояса для каждой биржи: например, Африка / Йоханнесбург, Америка / Чикаго, Америка / Виннипег.

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

Короче говоря, моя текущая реализация добавляет 1 дополнительный час ко времени истечения тех активов, у которых не должно быть действующего DST (например, инструмент, срок действия которого истекает в декабре, а местное время — Америка / Чикаго, должен добавить смещение -360 минут). и DST 0, в то время как другой, срок действия которого истекает в июне в том же часовом поясе, должен иметь смещение часового пояса -360 + смещение летнего времени DST, что будет смещением -300 к отметке времени UTC. С чем я сейчас сталкиваюсь, например, для месяц декабрь я получаю 9:30 вместо 8:30, поскольку временная метка UTC уже содержит смещение dst.

Вот моя функция для преобразования, которая явно не работает:

#ifdef WIN32
#define timegm _mkgmtime
#endif

SimpleDateTime BusinessDateCalculator::UTC2TZ(const SimpleDateTime& utcDateTime, const int tz_utc_offset, const int tz_dst)
{
struct tm stm;
memset(&stm, 0, sizeof(stm));
stm.tm_year = utcDateTime.getYear() - 1900;
stm.tm_mon = utcDateTime.getMonth() - 1;
stm.tm_mday = utcDateTime.getDay();
stm.tm_hour = utcDateTime.getHour();
stm.tm_min = utcDateTime.getMinute();
stm.tm_sec = utcDateTime.getSecond();
stm.tm_isdst = -1; //see note at the top of this file

time_t tt = timegm( &stm );
tt += (tz_utc_offset + tz_dst) * 60;

struct tm ntm;
memset(&ntm, 0, sizeof(ntm));
gmtime_r( &tt, &ntm );
return SimpleDateTime(ntm.tm_year + 1900, ntm.tm_mon + 1, ntm.tm_mday, ntm.tm_hour, ntm.tm_min, ntm.tm_sec, utcDateTime.getMillisecond());
}

Где SimpleDateTime — класс даты и времени с дополнительными функциями, такими как преобразование из различных форматов даты / времени (SQL, FIX, Timeonly, DateOnly).

У меня есть информация о часовом поясе определенного обмена, доступная в любое время. Мой вопрос, могу ли я как-то указать название часового пояса, и пусть timegm выполнить поиск в базе данных и определить, действует ли DST в часовом поясе Америки / Чикаго 2014-12-19 и, соответственно, не добавлять дополнительные 60 минут к времени UTC и в тот же день, например, в южном часовой пояс полушария Америка / Сан-Паулу действует до 16 февраля 2015 года, и к этой отметке времени следует добавить 60 минут, чтобы получить точное местное время для указанной даты.

0

Решение

Когда вы ссылаетесь на часовой пояс по его идентификатору IANA (например, "America/Chicago") — это уже включает всю информацию о летнем времени и полную историю часового пояса. По крайней мере, в исходных данных база данных часовых поясов IANA.

Ты упомянул Увеличение (в комментариях). Хотя Boost поддерживает эти типы идентификаторов, он допускает ошибку, предполагая, что они постоянно фиксируются во времени. Это неправда, поскольку часовые пояса мира постоянно меняют свои смещения и правила летнего времени. Учтите, что США изменили свои правила перехода на летнее время в 2007 году, и что Россия значительно меняет свои часовые пояса позднее в этом году (октябрь 2014 года). Если вы посмотрите на Увеличить файл данных часового пояса, вы увидите, что его формат удаляет всю историю и просто отображает каждый идентификатор в единый набор правил. По этой причине я рекомендую вам сделать не Используйте Boost для преобразования часового пояса.

Вместо этого рассмотрите возможность использования ICU. Помимо прочего, он включает функции преобразования часовых поясов и использует полную копию базы данных часовых поясов IANA. Вы можете прочитать больше здесь, и посмотреть Пример кода здесь. Я не особо разбираюсь в C ++, но может показаться, что вы можете использовать ICU Calendar класс для проецирования времени UTC по местному времени в определенном часовом поясе.

Другой вариант будет использовать функции часового пояса, встроенные в библиотека GNU C. Он также использует полную базу данных часовых поясов. Есть простой пример преобразования UTC по местному времени с использованием идентификатора IANA / Olson на этом сайте, который я также разместил ниже:

/*
C source code example: Convert UTC to local time zone, considering daylight
savings. Uses mktime(), gmtime() and localtime(). Works for dates between
years 1902 and 2037. Should compile and run with any recent GNU C if your
tzdata is healthy. Written by Robert Larsson  http://rl.se

Code put in public domain; do what you want with it.
*/

#include    <stdio.h>
#include    <stdlib.h>
#include    <time.h>

#define     DESTZONE    "TZ=Europe/Stockholm"       // Our destination time zone

int main(void)
{
struct tm   i;
time_t      stamp;                              // Can be negative, so works before 1970

putenv("TZ=UTC");                               // Begin work in Greenwich …

i.tm_year = 2009-1900;                          // Populate struct members with
i.tm_mon  = 8-1;                                // the UTC time details, we use
i.tm_mday = 29;                                 // 29th August, 2009 12:34:56
i.tm_hour = 12;                                 // in this example
i.tm_min  = 34;
i.tm_sec  = 56;

stamp = mktime(&i);                             // Convert the struct to a Unix timestamp

putenv(DESTZONE);                               // Switch to destination time zone

printf("UTC  : %s", asctime(gmtime(&stamp)));
printf("Local: %s", asctime(localtime(&stamp)));

return 0;                                       // That’s it, folks.
}
0

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector