Учитывая дату / время в виде строки, каков наилучший способ узнать, был ли это летнее время? - PullRequest
1 голос
/ 23 февраля 2012

Допустим, мне дали строку, такую ​​как это: "2009-4-9", что означает 9 апреля 2009 года. Предполагая для начала, что меня интересует только местное время (у меня есть проблемы и с другими часовыми поясами, но ясначала займусь легкими вещами).Как лучше всего узнать, действовало ли в то время летнее время?

Можно предположить, что в системе правильно обновлены файлы часовых поясов, такие как /etc/localtime, и я заинтересован в портативных решениях.Также приемлемы c или c ++.

Вы также можете предположить, что я забочусь только о прошлых или настоящих датах, а не о будущем.

В настоящее время у меня есть "взлом", который выглядит так(Я знаю, что localtime_r - это расширение библиотеки, но оно достаточно близко к той же функциональности, что я могу сделать его переносимым)

struct tm tm;
// convert the time string to a broken down structure in localtime
if(strptime("2009-4-9", "%Y-%m-%d", &tm)) {
    // convert the broken down structure into seconds since epoch
    const time_t t = mktime(&tm);

    // convert it back to a broken down structure, this seems pointless at first...
    // but libc will fill out fields such as tm_isdst
    localtime_r(&t, &tm);

    printf("DST : %d\n", tm.tm_isdst);
}

Хотя это работает (и кажется довольно эффективным способом), я чувствую, чтоглупо конвертировать туда и обратно.Есть ли лучший способ?

Ответы [ 3 ]

4 голосов
/ 23 февраля 2012

Вам вообще не нужно звонить localtime_r().mktime() нормализует struct tm, который вы передаете, включая установку tm_isdst на неотрицательное значение, если оно было передано в значение -1.Итак, все, что вам нужно:

struct tm tm = { 0 };
// convert the time string to a broken down structure in localtime
if(strptime("2009-4-9", "%Y-%m-%d", &tm)) {
    tm.tm_isdst = -1;
    // normalise the broken down structure - this calculates tm_isdst
    mktime(&tm);

    printf("DST : %d\n", tm.tm_isdst);
}

Такое поведение mktime() требуется стандартом C;например, C99 говорит:

Функция mktime преобразует время разбивки, выраженное как местное время, в структуре, на которую указывает timeptr, в значение календарного времени с той же кодировкойкак значения, возвращаемые функцией time.Исходные значения компонентов tm_wday и tm_yday структуры игнорируются, а исходные значения других компонентов не ограничиваются указанными выше диапазонами. 276 При успешном завершении значениякомпоненты tm_wday и tm_yday структуры устанавливаются соответствующим образом, а другие компоненты задаются для представления указанного календарного времени, но их значения устанавливаются в диапазонах, указанных выше;окончательное значение tm_mday не устанавливается до тех пор, пока не будут определены tm_mon и tm_year.

со сноской 276, явно обращающейся к члену tm_isdst:

276) Таким образом, положительное или нулевое значение для tm_isdst заставляет функцию mktime изначально предполагать, что летнее время, соответственно, действует или не действует в течение указанного времени.Отрицательное значение заставляет его попытаться определить, действует ли переход на летнее время в течение указанного времени.

2 голосов
/ 23 февраля 2012

Преобразование из UTC в местное время - , а не - обратимая функция. Например, осенью, когда часы отскакивают на час назад, местное время между 02:00 и 03:00 происходит дважды. Учитывая время в этом интервале, не можно определить, произошло ли местное время в определенное время UTC по местному дневному времени или через час по местному стандартному раз.

1 голос
/ 23 февраля 2012

Я делал много преобразований времени раньше в C, и я думаю, что у вас это в значительной степени так, как я бы это сделал.Насколько я знаю, localtime_r и его родственники могут быть вашим единственным вариантом (если не существует какой-либо сторонней библиотеки дат). Конечно, Грег Хьюгилл подходит для «серого часа» между переключателями времени.

...