Странная логика mktime с отрицательными секундами

Я использовал mktime / localtime для управления временем, включая некоторую сложную арифметику для дат / времени.

Я заметил кое-что очень странное, когда предоставлял mktime структуру, содержащую отрицательные значения.

Возьми код ниже. Произошло изменение DST в Лос-Анджелесе 3 ноября 2013 г. Если я укажу время в тм как 2013-11-04 полночь и вычту 24 часа, я получу то же значение, что и 2013-11-03 полночь. Разница в UTC составляет 25 часов, и это нормально, так как с isdst = -1 можно сказать, что мы смотрим на «время настенного часа». То же самое, если вычесть 1440 минут (24 * 60). Но если я вычту 86400 (24 * 60 * 60) секунд, я получу 2013-11-03 1:00. Это разница в 24 часа по UTC. Вот вывод из кода ниже:

2013-11-03 00:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-12--27 00:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 -24:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 00:-1440:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 00:00:-86400 (gmtoff=0, isdst=-1) -> 2013-11-03 01:00:00 (gmtoff=-25200, isdst=1) -> 1383465600

Для меня это не имеет смысла - почему секунды трактуются иначе, чем минуты, часы и дни? Я посмотрел на человека и стандарт Си, но ничего не смог найти.

Такое поведение нарушает некоторые из моих предположений и усложняет вещи. Кто-нибудь знает хорошую альтернативу mktime / localtime (я тестировал boost, ICU и tzcode, все слишком медленно для того, что мне нужно).

Заранее спасибо за любые мысли :)

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* printtm(struct tm tm)
{
  static char buf[100];
  sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d (gmtoff=%ld, isdst=%d)",
    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    tm.tm_hour, tm.tm_min, tm.tm_sec,
    tm.tm_gmtoff, tm.tm_isdst);
  return buf;
}

void test(int y, int m, int d, int hh, int mm, int ss, int isdst)
{
  struct tm tm;
  memset(&tm, 0, sizeof(tm));
  tm.tm_year = y - 1900;
  tm.tm_mon = m - 1;
  tm.tm_mday = d;
  tm.tm_hour = hh;
  tm.tm_min = mm;
  tm.tm_sec = ss;
  tm.tm_isdst = isdst;
  printf("%s -> ", printtm(tm));
  time_t t = mktime(&tm);
  printf("%s -> %ld\n", printtm(tm), t);
}


int main()
{
  setenv("TZ", ":America/Los_Angeles", 1);
  tzset();

  test(2013,11,03, 0,0,0, -1);
  test(2013,12,-27, 0,0,0, -1);
  test(2013,11,04, -24,0,0, -1);
  test(2013,11,04, 0,-1440,0, -1);
  test(2013,11,04, 0,0,-86400, -1);

  return 0;
}

Ответы на вопрос(1)

Ваш ответ на вопрос