mktime und tm_isdst

Lesezeit: 7 Minuten

Benutzer-Avatar
Hari

Ich habe viele verschiedene Ansichten gesehen, also dachte ich, hier zu fragen.

ich lese man mktime:

 (A positive or zero value for tm_isdst causes mktime() to presume initially
 that summer time (for example, Daylight Saving Time) is or is not in
 effect for the specified time, respectively.  A negative value for
 tm_isdst causes the mktime() function to attempt to divine whether summer
 time is in effect for the specified time. 

Meine Frage ist, sollte nicht tm_isdst so gehalten werden -1 das System entscheiden zu lassen, ob es dst ist oder nicht, und auf diese Weise wird der Code dst-agnostisch?

Übersehe ich etwas?

Benutzer-Avatar
Reich Jahn

Sie sollten es nach Möglichkeit vermeiden, tm_isdst auf -1 zu setzen. Das System kann den DST-Status nicht immer allein anhand von Datum und Uhrzeit bestimmen. Es ist die Stunde vor und nach dem Ende der Sommerzeit mehrdeutig. Zum Beispiel, wenn Sie bestehen mktime() 01:30 Uhr 4. November 2012, das sind nicht genug Informationen, um eine richtige Antwort zu erhalten time_t Wert ab mktime(). Normalerweise habe ich gesehen mktime() Nehmen Sie Standardzeit an, falls es mehrdeutig ist, aber ich habe keine Dokumentation gesehen, die dieses Verhalten auf allen Plattformen garantiert. 01:30 Uhr 4. November 2012 mit tm_isdst == 1 wäre 1 Stunde vorher, weil sich die Stunde 1:00:00 bis 1:59:59 wiederholt.

#include <stdio.h>
#include <time.h>

int main()
{
    time_t daylight, standard;
    struct tm timestr;
    double diff;

    timestr.tm_year = 2012 - 1900;
    timestr.tm_mon = 11 - 1;
    timestr.tm_mday = 4;
    timestr.tm_hour = 1;
    timestr.tm_min = 30;
    timestr.tm_sec = 0;

    /* first with standard time */
    timestr.tm_isdst = 0;
    standard = mktime(&timestr);

    /* now with daylight time */
    timestr.tm_isdst = 1;
    daylight = mktime(&timestr);

    diff = difftime(standard, daylight);

    printf("Difference is %f hour(s)", diff/60.0/60.0);

    return 0;
}

Dies erzeugt:

Difference is 1.000000 hour(s)

Beide sind der 4. November 2012, 1:30 Uhr, aber beide sind zwei unterschiedliche time_t-Werte im Abstand von 1 Stunde.

mktime() hat im Wesentlichen 2 Ausgänge:

  • Zeit_t
  • reparierte Zeitstruktur

Die Zeitstruktur ist sowohl eine Eingabe als auch eine Ausgabe. Es wird modifiziert durch mktime() um alle Strukturmitglieder auf nominale Bereiche zurückzusetzen. Wenn Sie beispielsweise das Mitglied tm_hour erhöhen += 500, d.h. die Zeit um 500 Stunden erhöhen. Das tm_hour Mitglied wird auf einen Wert von 00 bis 23 geändert, und die tm_day, tm_mdayusw. werden entsprechend angepasst. tm_isdst ist auch Eingang und Ausgang. Seine Werte sind wie folgt:

  • 1 (DST in Kraft, dh Sommerzeit)
  • 0 (DST nicht in Kraft, dh Standardzeit)
  • -1 (Unbekannter DST-Status)

Also gibt mktime() entweder eine 1 oder 0 für tm_isdst aus, niemals -1.

-1 ist möglich Eingang, aber ich würde es als “Unbekannt” bezeichnen. Betrachten Sie es nicht als “automatisch bestimmen”, denn im Allgemeinen mktime() kann es nicht immer automatisch bestimmen.

Der explizite DST-Status (0 oder 1) sollte von etwas außerhalb der Software stammen, zum Beispiel in der Datei oder Datenbank gespeichert werden oder den Benutzer auffordern.

  • Nun, wenn Sie die Sommerzeit nicht kennen, müssen Sie sie selbst bestimmen (viel Glück damit) oder auf einstellen -1. Es gibt keine andere Möglichkeit. Wenn Sie es auf 0 setzen, erhalten Sie überhaupt keine DST, was garantiert falsch ist, wenn Sie es auf 1 setzen, erzwingen Sie DST, was auch garantiert falsch ist.

    – rostig

    5. August 2016 um 12:25 Uhr


  • @RustyX Hardcoding auf -1, 0 oder 1 ist immer falsch. -1 ist am wenigsten schlimm, aber immer noch schlecht. Der explizite Status (0 oder 1) sollte sein Eingang an die Software vom Benutzer oder in den Daten (Datei oder Datenbank) gespeichert. Grundsätzlich muss es von etwas außerhalb der Anwendung kommen.

    – Rich Jahn

    20. Dezember 2016 um 15:44 Uhr


  • @RichJahn: Es wird in einer Datenbank gespeichert: der TZ-Datenbank von ungefähr jedem UNIX / Linux-System. Der einfachste Weg, es von dort für eine bestimmte Zeit abzurufen, besteht darin, mktime mit tm_isdst auf -1 auszuführen … Und erinnern Sie sich, wann DST-Änderungen auftreten? Es ist nicht sinnvoll, diese Informationen vom Benutzer zu verlangen. “Sie sollten es vermeiden, tm_isdst auf -1 zu setzen wenn möglich.” – In welchen sinnvollen, gängigen Nutzungsszenarien ist dies möglich?

    – SF.

    31. März 2017 um 10:52 Uhr

  • @SF. Mein ganzer Punkt ist, dass “es” nirgendwo gespeichert ist. Der Computer weiß es nicht. Wenn ich analog sagte: Der absolute Wert ist 5, war die ursprüngliche Zahl positiv oder negativ? Sie können kein Programm schreiben, um das herauszufinden, es sei denn, es handelt sich um ein Gedankenleseprogramm. Die Antwort ist: Ich weiß nicht, sagen Sie es mir. Ich weiß, dass am 5. November 2017 Mitternacht US CDT und 5:00 Uhr US CST ist. Aber 1:30 Uhr? Ich weiß nicht, du sagst es mir. Anwendungen, die ich geschrieben habe, machen es zu einem schwerwiegenden Fehler oder fordern den Benutzer auf, wenn die Zeit mehrdeutig ist. Ich denke, die meisten Datumsauswahl-Benutzeroberflächen ignorieren dieses Problem leider vollständig.

    – Rich Jahn

    4. April 2017 um 21:27 Uhr


  • “Also gibt mktime() entweder eine 1 oder 0 aus” –> Ich würde erwarten, dass dies “Also gibt mktime() entweder a aus positiver Wert oder 0″. Doch vielleicht sind verschiedene Unix-Varianten spezifischer.

    – chux – Wiedereinsetzung von Monica

    13. August 2018 um 15:53 ​​Uhr


Ich glaube, der ursprüngliche Grund dafür ist, dass einige Zeitzonen keine Sommerzeit haben. Da mktime weder async-sicher noch eintrittsinvariant ist, erlaubt die Implementierung, den aktuellen Wert der Sommerzeit im externen POSIX-Chartznamen zu speichern[2]indiziert nach Tageslicht [0 or 1]. Dies bedeutet tzname[0]=”[std TZ name]” und tzname=”[daylight TZ name, e.g. EDT]”

Weitere Informationen hierzu finden Sie auf Ihrer tzset()-Manpage. Standardkonformes mktime() muss sich trotzdem so verhalten, als würde es tzset() aufrufen. Diese Art vermeidet die Verwendung von tm_isdst, IMO.

Fazit: Ihre spezielle Implementierung und Zeitzone(n) würde vorschreiben, ob Sie -1, 0 oder 1 für tm_isdst verwenden würden. Es gibt keinen standardmäßig korrekten Weg für alle Implementierungen.

Ich denke, dass Sie in der Tat verwenden sollten -1 für die tm_isdst Feld, es sei denn, Sie haben Informationen über die Art der Zeit, mit der Sie es zu tun haben.

In Kalifornien haben wir zum Beispiel immer noch PST und PDT. Wenn Sie ein Datum analysieren und diese Zeitzoneninformationen vorhanden sind, sollten Sie die festlegen tm_isdst entsprechend. Wie Jim McNamara erwähnte, sind diese Namen im verfügbar tzname[] Array nach einem Aufruf an tzset().

Schreiben Sie beispielsweise den folgenden C++-Code PST/PDT:

int main(int argc, char * argv [])
{
    tzset();
    std::cerr << tzname[0] << "https://stackoverflow.com/" << tzname[1] << "\n";

    return 0;
}

Der Versatz in der tzname[] array entspricht dem Wert von tm_isdst. (PST – Pazifische Standardzeit, tm_isdst = 0und PDT, pazifische Sommerzeit, tm_isdst = 1.)

Wenn Sie die Zeitzoneninformationen nicht in Ihrer Eingabe haben, verwenden Sie -1 ist die beste Wahl. Sie haben ein Problem nur wenn das Datum dem Tag und der Uhrzeit der Änderung entspricht. Wie Rich Jahn erklärt, hatte er am 4. November 2012 eine Zeitumstellung zwischen Standard- und Sommerzeit und ungefähr zu dieser Zeit, gmtime() muss eine Wahl treffen, und es ist nicht anders als das Gegenteil von dem, was Sie erwarten würden. Davon abgesehen passiert es nur insgesamt 2 Stunden im Jahr und mitten in der Nacht. Wenn Sie also nicht an einer kritischen Art von Software arbeiten, bei der das Datum sehr wichtig ist, spielt es wahrscheinlich keine Rolle.

Also als Rekapitulation:

  • Wenn Sie die Zeitzone an das Datum angehängt haben, das Sie konvertieren möchten, verwenden Sie diese Informationen, um den Wert von zu bestimmen tm_isdst (Trotzdem bin ich mir nicht sicher, wie Sie damit umgehen, falls Sie alle Zeitzonen unterstützen müssen … die tzname[] array gibt Ihnen nur die aktuelle Zeitzone des Benutzers.)
  • in allen anderen Fällen verwenden -1

  • Was Sie sagen, ist wahr, schätze ich, aber es klingt so passiv, und so ein niedriger Balken, als hätte ich die Informationen nicht, schätze, ich werde es einfach leben. Wenn Sie nur eine Ortszeit eingeben, wird Ihre Zeit in 99,98 % der Fälle korrekt sein, aber nur mit leicht mehr Code kann es 100% der Zeit richtig sein. Offensichtlich würden die Leute keine Wahlmaschinen akzeptieren, die in 0,02 % der Fälle 2 Stimmen statt 1 aufgezeichnet haben. Mein Rat ist, ein eindeutiges Format wie ISO 8601 zu verwenden.

    – Rich Jahn

    23. August 2019 um 0:00 Uhr

  • @RichJahn, haben Sie versucht, herumzugehen, sagen wir bei Walmart, und die Leute zu fragen, wie die Zeitzone an diesem Ort ist? Wie viele haben dir die richtige Antwort gegeben? Es ist eine enorme Belastung, über 7 Milliarden Menschen beizubringen, was eine Zeitzone ist. Die meisten werden jedoch wissen, was Datum und Uhrzeit sind. Mein Rat wäre, alle Regierungen der Welt zu bitten, die Winter- gegen die Sommerzeit fallen zu lassen, um loszulegen.

    – Alexis Wilke

    23. August 2019 um 2:34 Uhr

1158770cookie-checkmktime und tm_isdst

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy