Seltsame Zeitlogik mit negativen Sekunden

Ich habe mktime / localtime für die Zeitverwaltung verwendet, einschließlich einiger schwerer Berechnungen für Daten / Zeiten.

Ich bemerkte etwas sehr Seltsames, als ich eine Struktur mit negativen Werten für mktime bereitstellte.

Nimm den Code unten. In LA hat sich die Sommerzeit am 3. November 2013 geändert. Wenn ich die Zeit in tm als 04.11.2013 Mitternacht eingebe und 24 Stunden abziehe, erhalte ich denselben Wert wie am 03.11.2013 Mitternacht. Es ist ein Unterschied von 25 Stunden in UTC, was in Ordnung ist, da man bei isdst = -1 sagen könnte, dass wir auf die Zeit um die Wanduhr schauen. Das gleiche gilt, wenn ich 1440 Minuten (24 * 60) abziehe. Wenn ich jedoch 86400 (24 * 60 * 60) Sekunden subtrahiere, erhalte ich den 03.11.2013 um 1 Uhr morgens. Das ist ein Unterschied von 24 Stunden in UTC. Hier ist die Ausgabe des folgenden Codes:

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

Für mich macht es keinen Sinn - warum werden Sekunden anders behandelt als Minuten, Stunden und Tage? Ich schaute auf Mann und den C-Standard, konnte aber nichts finden.

Dieses Verhalten bricht einige meiner Annahmen und kompliziert die Dinge. Kennt jemand eine gute Alternative zu mktime / localtime (Boost, ICU und tzcode habe ich getestet, alles zu langsam für das, was ich brauche)?

Vielen Dank im Voraus für alle Gedanken :)

#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;
}

Antworten auf die Frage(1)

Ihre Antwort auf die Frage