среда, 14 апреля 2010 г.

Странное поведение mktime относительно летнего времени


На опыте столкнулся с тем, что результат, возвращаемый функцией mktime(3) не учитывает перехода на зимнее/летнее время (т.е. результаты для "лета" оказываются на час больше, чем нужно). Проверено на linux 2.6.18 и FreeBSD 8.0 с корректно установленной зоной MSK/MSD - так что, вероятно, именно такое странное поведение соответствует спецификации POSIX. Самое смешное в том, что (в полном соответствии с документацией) функция mktime не только возвращает типа значение time_t, но и "нормализует" содержимое переданной в нее по указателю struct timespec, заполняя совершенно корректными (учитывающеми перевод времени) значениями поля tm_isdst, tm_gmtoff и tm_zone. Очевидно, где-то в этом направлении и лежит путь борьбы с этой функцией. Т.е вместо очевидного:

struct timespec ts;

time_t tm = mktime(&ts);

Пишем теперь так:

struct timespec ts;

time_t tm = mktime(&ts) - ts.tm_isdst * 3600;

Эстетам же и забывчивым можно предложить определить вот такой макрос:

#define mktime(t) (mktime(t) - (t)->tm_isdst * 3600)

и использовать mktime, как обычно.

Еще идеи?