Функция set_time()
должна занимать определенное время, добавлять к этому времени указанное количество минут и сохранять его в *t
.
#include <stdio.h>
#include <time.h>
enum {JAN, FEB, MAR, APR, MAY, JUNE, JULY, AUG, SEP, OCT, NOV, DEC};
void set_time(struct tm *t,
int year, int mon, int day,
int hour, int min, int sec,
int mins_to_add)
{
/* Copy all the values. */
t->tm_year = (year - 1900);
t->tm_mon = mon;
t->tm_mday = day;
t->tm_hour = hour;
t->tm_min = min;
t->tm_sec = sec;
// No DST since we are storing UTC time.
t->tm_isdst = 0;
/* Add minutes to time. */
t->tm_min += mins_to_add;
mktime(t);
/* Debug print */
printf("%s\n", asctime(t));
}
int main(int argc, char **argv)
{
struct tm t;
set_time(&t, 2011, AUG, 1, 10, 00, 00, 0);
return 0;
}
Итак, я прошу set_time()
ничего не добавлять к 01 августа 10:00:00 2011 г. Однако, если в моей системе Windows установлен часовой пояс EST, я получаю вывод: Mon Aug 01 11:00:00 2011
Ошибка возникает из-за того, что я выполняю задачу добавления указанного количества минут (0 в приведенном выше примере) к указанному времени (01 августа, 10:00:00 2011 в приведенном выше примере) с помощью этой части кода:
/* Add minutes to time. */
t->tm_min += mins_to_add;
mktime(t);
mktime()
вызывается для настройки всех других переменных-членов структуры в случае, если t->tm_min
превышает 59 из-за сложения. Но mktime()
обрабатывает время в struct tm
объекте как местное время. Таким образом, когда он видит, что дата 01 августа 2011 года, а местный часовой пояс - как EST, он предполагает, что DST необходимо применить, но обнаруживает, что t->tm_isdst
установлен на 0
(то есть DST не применяется ко времени в *t
). Таким образом, он применяет летнее время, устанавливает дату с 01 августа 10:00:00 2011 года по 01 августа 11:00:00 2011 года и устанавливает t->tm_isdst
в 1
.
Если бы я инициализировал t->tm_isdst
в 1
, эта проблема не возникла бы, потому что mktime()
обнаружил бы, что время в *t
уже применено к DST. Тем не менее, это могло бы испортить результат, если бы я попросил set_time()
ничего не добавлять к дате, к которой DST не должен применяться, скажем 01 января 10:00:00 2011 года. Теперь он попытается отключить DST в *t
, тем самым устанавливая t->tm_isdst
в 0 и перенастраивая дату на 01 января 09:00:00 2011.
В результате это приводит к нежелательному добавлению дополнительного часа или вычитанию дополнительного часа из указанного времени, когда я не хотел ничего добавлять. Это происходит потому, что когда mktime()
обнаруживает, что значение DST в t->tm_isdst
не соответствует требуемому местному часовому поясу системы, оно пытается установить его правильно, перенастраивая время в *t
.
Как правильно решить эту проблему?