Forum: PC-Programmierung struct tm - Verwirung über daylight saving time flag


von Philip K. (philip_k)


Lesenswert?

Hallo,

die Struktur tm hat ein Flag tm_isdst

Unter http://www.cplusplus.com/reference/ctime/tm/ steht "The Daylight 
Saving Time flag (tm_isdst) is greater than zero if Daylight Saving Time 
is in effect, zero if Daylight Saving Time is not in effect, and less 
than zero if the information is not available."

Mir ist aufgefallen, dass wenn ich die Funktion mktime() mit einem 
gültigen tm-Objekt aufrufe, das dieses Flag gesetzt hat, dann ist danach 
eine Stunde abgezogen, in meinem Fall muss ich es also offenbar nicht 
setzen.
Irgendwie versteh ich den Zweck dieses Flags nicht. Kann mir jemand 
einen Anwendungsfall nennen?

Gruß

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hier der dazugehörige Standard-Text für UNIX:

http://pubs.opengroup.org/onlinepubs/009695399/functions/mktime.html

Da es auf eine Funktion gemäß C-Standard Bezug nimmt, ist auch das
C99Rationale hierzu interessant zu lesen, Seite 170 (7.23.2.3).

von Karl H. (kbuchegg)


Lesenswert?

Philip K. schrieb:

> Irgendwie versteh ich den Zweck dieses Flags nicht. Kann mir jemand
> einen Anwendungsfall nennen?

Die Idee ist, dass ein time_t eine arithmetisch durchgehende Zeit ist, 
mit der man auch einfach rechnen kann ohne sich um so Kinkerlitzchen wie 
Sommerzeit kümmern zu müssen.

Wohingegen ein struct tm die Zeit in einer Form repräsentiert, wie man 
sie dem Benutzer präsentieren kann und der sie auf seiner Uhr an der 
Wand wiederfinden wird.

D.h. irgendwann muss mal die 1 Stunde Differenz zwischen Sommer und 
Winterzeit berücksichtigt werden.

Zählst du an dem Samstag, an dem in der Nacht die Umstellung auf 
Sommerzeit erfolgt, um 14:00 nachmittags 24 Stunden dazu, dann landest 
du am Sonntag eben nicht auf 14:00 sondern schon auf 15:00. Sowas ist 
lästig, wenn man Zeitrechnungen machen muss, die über diese Grenze 
laufen. Daher benutzt man im Rechner am einfachsten eine durchlaufende 
Zeit (so wie wenn du deine persönliche Uhr nicht umgestellt hättest) und 
berücksichtigt bei der Ausgabe, dass im Sommer alle Zeiten um 1 Stunde 
weniger anzuzeigen sind (mit gegebenenfalls auch noch einem 
Datumswechsel, wenn sich das ganze um Mitternacht rum abspielt).
D.h. du rechnest intern immer mit einem time_t. Die Funktionen mktime 
bzw. localtime konvertieren dir dann eine time_t Zeit in eine Form bzw. 
von einer Form, die du zu Anzeigezwecke benutzen kannst.


Sommerzeit kann ganz schön tricky sein. Vor allen Dingen dann, wenn man 
dann auch noch Zeiten aus verschiedene Zeitzonen miteinander verrechnen 
muss, die unterschiedliche Regelungen haben.

: Bearbeitet durch User
von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Karl Heinz schrieb:
> und berücksichtigt bei der Ausgabe, dass im Sommer alle Zeiten um 1 Stunde
> weniger anzuzeigen sind

Und da beginnen dann schon die Mißverständnisse...

Angenommen ich erzeuge am besagten Samstag um 14:00 eine Datei, und 
schau mir danach das Erzeugungs- (oder Änderungs-) Datum an, so sehe ich 
(hoffentlich) Samstag, 14:00

Was sehe ich, wenn ich am nächsten Tag (mit Sommerzeit) in das 
Verzeichnis gucke?

Das Flag heisst nämlich nicht, dass "jetzt" die Sommerzeit aktiv ist, 
sondern zum Zeitpunkt den das entsprechende Datum/Uhrzeit angibt.

Allerdings verhält (oder verhielt) sich Windows hier eigenartig. Ich 
hatte vor Jahren große Probleme eine Datei-Synchronisation hinzukriegen, 
die immer am Sommerzeit-Wechsel gemuckt hatte. Das Problem dabei: Es 
gibt zwei Fehlerquellen (Umschaltung Winter- auf Sommerzeit, und 
umgekehrt) und du hast jeweils genau einen Testcase pro Jahr.

Nach drei Jahren lief das aber stabil :-)

Richtig spannend wirds aber, wenn dann noch zeitzonen dazukommen...

von Peter II (Gast)


Lesenswert?

Michael Reinelt schrieb:
> Richtig spannend wirds aber, wenn dann noch zeitzonen dazukommen...

was sogar das kleine Problem ist, Windows speichert auf NTFS immer UTM.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Karl Heinz schrieb:
> Sommerzeit kann ganz schön tricky sein.

Meine Rede! Daher, wo immer geht, UTC verwenden.

ABER: Das geht auch nicht immer. Konkreter fall aus meienr Praxis: Du 
erzeugst sowas wie "Aufgaben", die haben zwar eine Uhrzeit, werden aber 
nur tagesmäßig geplant. Wenn ich sage "Fang nächsten montag damit an", 
dann ist es praktisch, als geplanten Start "Montag, 09:00" anzuzeigen 
(weil vorher ist eh keiner im Büro).

Nur - wenn ich die Aufgabe jetzt einem Chinesen zuordne?

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Michael Reinelt schrieb:
>> Richtig spannend wirds aber, wenn dann noch zeitzonen dazukommen...
>
> was sogar das kleine Problem ist,

Sag das nicht.
Wenn man automatisierte Fernwartung machen will, inklusive zb Abziehen 
von Log-Files übers Netzwerk, dann ist dieser Sommer/Winterzeitwechsel 
inklusive Zeitzonenberücksichtigung (wie spät ist es in Singapur, wenn 
wir hier 02:45 haben?) einfach nur ein Pain in the Ass. Hat mich auch 
ein paar mal gefuchst, bis ich das richtig hatte.


(Bzw. wann muss ich hier in Österreich die Netzwerkverbindung aufbauen, 
wenn mich die Chinesen nur zwischen 02:30 und 03:00 ihrer Lokalzeit in 
ihren Rechner reinlassen)

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

In der Eingabe für mktime() ist das Flag nur an einer Stelle wichtig:
ich habe eine struct tm, die auf den 25. Oktober 2015, 02:33 Uhr lautet.
Je nachdem, ob nun tm_isdst gesetzt ist oder nicht, ist damit das
Auftreten dieser Uhrzeit vor oder nach der Sommerzeitabschaltung
gemeint.  Die Angabe der „Küchenzeit“ ist (im Gegensatz zu UTC) in
diesem Falle nämlich nicht eindeutig.

Ergänzung: Andererseits „normalisiert“ mktime() auch die Felder in
der eingehenden struct tm.  Es ist ja zulässig, den 40. November
anzugeben, und bei der Rücckehr stehen dazu die korrekten Werte
drin (9. Dezember).  So dürfte ein eindeutig fehlerhaft angegebenes
tm_isdst wohl ebenfalls korrigiert werden: ist es gesetzt, aber für
die entsprechende Zeitzone ist zu diesem Zeitpunkt eindeutig keine
Sommerzeit aktiv, dann wird die Zeit umgerechnet, wie man sie hätte
angeben müssen.

Zumindest deute ich die Beschreibung(en) so.

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Sag das nicht.
> Wenn man automatisierte Fernwartung machen will, inklusive zb Abziehen
> von Log-Files übers Netzwerk, dann ist dieser Sommer/Winterzeitwechsel
> inklusive Zeitzonenberücksichtigung (wie spät ist es in Singapur, wenn
> wir hier 02:45 haben?) einfach nur ein Pain in the Ass. Hat mich auch
> ein paar mal gefuchst, bis ich das richtig hatte.

der IIS und Exchange verwenden fürs logging aus dem Grund auch UTC.

In Solchen Dinge kann man von MS noch etwas lernen, sie mussten schon 
immer etwas global denken.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> In Solchen Dinge kann man von MS noch etwas lernen, sie mussten schon
> immer etwas global denken.

So?  Glaub' ich nicht.  Beim blöden alten FAT-Filesystem wurde die
Zeit immer als lokale gespeichert, erstens mit den Mehrdeutigkeiten,
zweitens hätte eine über die Datumsgrenze geworfene Diskette auf der
anderen Seite ein Datum in der Zukunft gehabt.

Unix dagegen hat die Zeit schon immer in UTC geführt, schon seit 1970 …
Lediglich die Darstellung innerhalb der Applikation wurde dann auf
lokale Zeit gerechnet (im Ur-UNIX allerdings nur „amerikanisch“, also
nur auf deren fünf Zeitzonen bezogen).

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

> drin (9. Dezember).  So dürfte ein eindeutig fehlerhaft angegebenes
> tm_isdst wohl ebenfalls korrigiert werden: ist es gesetzt, aber für
> die entsprechende Zeitzone ist zu diesem Zeitpunkt eindeutig /keine/
> Sommerzeit aktiv, dann wird die Zeit umgerechnet, wie man sie hätte
> angeben müssen.

Da bin ich mir nicht wirklich sicher.
Denn dann müste mktime auch noch wissen, für welche Zeitzone die zeit 
gilt. Oder gilt dann immer die am System eingestellte?

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Peter II schrieb:
>> In Solchen Dinge kann man von MS noch etwas lernen, sie mussten schon
>> immer etwas global denken.
>
> So?  Glaub' ich nicht.  Beim blöden alten FAT-Filesystem wurde die
> Zeit immer als lokale gespeichert, erstens mit den Mehrdeutigkeiten,
> zweitens hätte eine über die Datumsgrenze geworfene Diskette auf der
> anderen Seite ein Datum in der Zukunft gehabt.

Sagen wir so: Sie haben im Lauf der Zeit dazugelernt.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Jörg Wunsch schrieb:
>
>> drin (9. Dezember).  So dürfte ein eindeutig fehlerhaft angegebenes
>> tm_isdst wohl ebenfalls korrigiert werden: ist es gesetzt, aber für
>> die entsprechende Zeitzone ist zu diesem Zeitpunkt eindeutig /keine/
>> Sommerzeit aktiv, dann wird die Zeit umgerechnet, wie man sie hätte
>> angeben müssen.
>
> Da bin ich mir nicht wirklich sicher.
> Denn dann müste mktime auch noch wissen, für welche Zeitzone die zeit
> gilt. Oder gilt dann immer die am System eingestellte?


Doku lesen hilft manchmal
1
Convert tm structure to time_t
2
Returns the value of type time_t that represents the local time described by the tm structure pointed by timeptr (which may be modified).
3
4
This function performs the reverse translation that localtime does.

mktime wendet also immer die lokale Zeitzone an.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Denn dann müste mktime auch noch wissen, für welche Zeitzone die zeit
> gilt. Oder gilt dann immer die am System eingestellte?

s/System/lokale Umgebung/

Ja.

Siehe oben verlinkte UNIX-Seite:

“Local timezone information shall be set as though mktime() called 
tzset().”

Oder im C-Standard:

“The mktime function converts the broken-down time, expressed as local 
time, in the structure pointed to by timeptr …”

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Sagen wir so: Sie haben im Lauf der Zeit dazugelernt.

Ja, dem würde ich zustimmen. :)

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

> Oder im C-Standard:
>
> “The mktime function converts the broken-down time, *expressed as local*
> time, in the structure pointed to by timeptr …”

Habs schon gesehen. Danke Jörg.

Das Witzige an der Sache: Welche Probleme da auf einen zukommen, merkt 
man erst, wenn man da mal durch muss.
Ist alles zu lösen, keine Frage. Ich kenn allerdings keinen, der da 
nicht mindestens einmal gestolpert ist. Ganz blöd wirds, wenn man dann 
auch noch Code erbt und der Original-Autor sich darüber keine Gedanken 
(sprich alles in UTC speichern und du kannst das wegen Kompatibilität 
auch nicht ändern!) gemacht hat.

: Bearbeitet durch User
von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Jörg Wunsch schrieb:
> In der Eingabe für mktime() ist das Flag nur an einer Stelle wichtig:
> ich habe eine struct tm, die auf den 25. Oktober 2015, 02:33 Uhr lautet.
> Je nachdem, ob nun tm_isdst gesetzt ist oder nicht, ist damit das
> Auftreten dieser Uhrzeit vor oder nach der Sommerzeitabschaltung
> gemeint.  Die Angabe der „Küchenzeit“ ist (im Gegensatz zu UTC) in
> diesem Falle nämlich nicht eindeutig.

Danke, wieder was gelernt! (Abgesehen davon dass mir der Begriff 
"Küchenzeit" gefällt :-)

Wobei das auch menschlich schwierig ist: ich als notorischer 
Frühaufsteher (manche sagen "senile Bettflucht" dazu) bin hin und wieder 
um diese zeit schon auf, und durchaus mal am 25. Oktober. Dann 
festzustellen, wie lange man jetzt eigentlich geschlafen hat, ist 
durchaus eine Herausforderung!

Trotzdem noch eine Sicherheitsfrage: Wenn ich am 25. Oktober nachmittag 
(also Winterzeit) einen Timestamp für 24. Oktober, 14:00 (also 
Sommerzeit) setze, was nehm ich dann (oder was nimmt die libc dann?) 
Anders gefragt: Gilt das DST-Flag für "jetzt" oder für die Zeit die ich 
verarbeite?

Peter II schrieb:
> In Solchen Dinge kann man von MS noch etwas lernen
Na, ganz sicher nicht... wenn dann hat MS (widerwillig) gelernt.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Michael Reinelt schrieb:

> Sommerzeit) setze, was nehm ich dann (oder was nimmt die libc dann?)
> Anders gefragt: Gilt das DST-Flag für "jetzt" oder für die Zeit die ich
> verarbeite?

Meinem Verständnis nach gilt das Flag in der struct tm so wie es ist. 
Also 'für die Zeit die du verarbeitest'.

'Jetzt' würde IMHO nicht viel Sinn machen. Denn das würde es enorm 
erschweren mit Timestamps zu arbeiten.


An dieser Stelle aber ein gross geschriebenes IMHO! Kann sein, dass ich 
da komplett falsch liege.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael Reinelt schrieb:
> Gilt das DST-Flag für "jetzt" oder für die Zeit die ich verarbeite?

Alles in der struct tm dort bezieht sich auf die Zeit, die damit
dargestellt werden soll.  Das einzige, was aus der aktuellen Umgebung
benutzt wird, ist die Zeitzoneninformation; man kann mit mktime()
also keine Konvertierung für eine andere Zeitzone vornehmen als die,
mit der die Applikation gerade läuft.

> (Abgesehen davon dass mir der Begriff "Küchenzeit" gefällt :-)

Funkamateur-Jargon, um von der (beim Funk sonst üblichen) UTC zu
unterscheiden.  Die Uhr im Shack läuft also auf UTC, die in der Küche
zeigt eine andere Zeit an. :)

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Jörg Wunsch schrieb:
> Alles in der struct tm dort bezieht sich auf die Zeit, die damit
> dargestellt werden soll.

Danke, hatte ich so vermutet (aber mir gehts da gleich wie Karl Heinz 
:-)

Jörg Wunsch schrieb:
> "Küchenzeit"
> Funkamateur-Jargon

Ach ja, die Prüfung wollte ich auch nochmal machen, bevor ich endgültig 
senil werde... (so many challenges, so little time, wie Robert Cray 
schon geklagt hat)

von Tom (Gast)


Lesenswert?

Amüsant aber halbwegs zum Thema passend 
https://www.youtube.com/watch?v=-5wpm-gesOY

von Philip K. (philip_k)


Lesenswert?

Irgendwie macht mir da Thema einen Knoten ins Gehirn. Wirklich schlauer 
bin ich immer noch nicht. Also versuch ichs mal mit der Beschreibung 
meines konkreten Anwendungsfalls.
Ich habe eine Log-Datei, die einen Haufen Analog- und Status-Samples 
enthält. Zu diesen Werten gehört u.a. ein Trigger-Zeitstempel, ein 
Trigger-Offset in Microsekunden (Abstand zwischen Trigger-Zeitpunkt und 
erstem Sample) und eine Sample-Rate. Diesen Datensatz konvertiere ich in 
ein anderes Format, dass anstelle des Offsets einen zusätzlichen 
Start-Zeitstempel enthält.
Ich mache momentan folgendes:
- Umrechnung des Microsekunden-Offsets in Sekunden + Rest(wird separat 
gespeichert)
- Befüllen eines tm-struct mit den Zeitdaten aus der Datei (Btw. ich 
habe an dieser Stelle keine Info, ob es sich um local- oder UTC-time 
handelt, weiß aber dass beide Fälle möglich sind). Dabei habe ich bisher 
tm_isdst = 1 gesetzt, ohne wirklich zu wissen ob das richtig ist.
- Umwandlung mit mktime() in ein time_t (Hierbei wird mit tm_isdst = 1 
von meinem tm eine Stunde abgezogen)
- Abziehen des Sekunden-Offset.
- Erzeugen eines neuen tm per localtime(). Dies ist dann der 
Start-Zeitstempel.

Da ich das Abziehen der Stunde nicht möchte folgere ich, dass in meine 
Fall tm_isdst = 0 gesetzt werden muss. Warum die Stunde aber abgezogen 
wird, hab ich noch immer nicht verstanden.

Außerdem frage ich mich:
- Ist meine Ausgangs-Zeitinformation ohne die Angabe local/UTC 
ungültig/unvollständig, oder kann mir das in dem Fall egal sein?
- Wenn die Ausgangs-Zeitinformation in UTC ist und ich wie oben 
beschreiben nach der Differenzbildung per localtime() zurück wandle, 
habe ich dann ein falsches Ergebnis? Vermutlich nicht, weil laut Doku 
mktime() und localtime() inverse Funktionen sind, oder?
- Was passiert, wenn der Start-Zeitpunk vor und der Trigger-Zeitpunkt 
nach einer Zeitumschaltung liegt?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Philip K. schrieb:

> Da ich das Abziehen der Stunde nicht möchte folgere ich, dass in meine
> Fall tm_isdst = 0 gesetzt werden muss.

Nein, das ist genauso falsch, wie das Setzen auf 1.

Du musst es auf -1 setzen, denn das heißt „ich weiß nicht, ob da
Sommerzeit war oder nicht“.  Dann muss mktime() es selbst rausfinden,
was bis auf die Doppeldeutigkeit am Tag des Zurückschaltens kein
Problem ist.

Nur, wenn du Zeitstempel innerhalb dieses Zeitfensters (1 h pro
Jahr) auswerten musst, müsstest du mktime() durch explizites Setzen
von tm_isdst auf 0 oder 1 auf die Sprünge helfen, welche der beiden
Möglichkeiten gemeint ist.  Vermutlich wird dir die dafür nötige
Information aber ohnehin nicht vorliegen. ;-)

> Außerdem frage ich mich:
> - Ist meine Ausgangs-Zeitinformation ohne die Angabe local/UTC
> ungültig/unvollständig, oder kann mir das in dem Fall egal sein?

Unvollständig.  Da mktime() von lokaler Zeit ausgeht, bekommst du
das erstmal so umgesetzt.  Für UTC müsstest du die Umgebungsvariable
zuvor passend setzen (bei Linux offenbar auf "Universal", bei
FreeBSD haben sie es wirklich "UTC" genannt; Setzen auf einen Wert,
für den es keine Definition gibt, müsste aber als Fallback auch zur
Interpretation als UTC führen).

> - Wenn die Ausgangs-Zeitinformation in UTC ist und ich wie oben
> beschreiben nach der Differenzbildung per localtime() zurück wandle,
> habe ich dann ein falsches Ergebnis?

Ja.

> - Was passiert, wenn der Start-Zeitpunk vor und der Trigger-Zeitpunkt
> nach einer Zeitumschaltung liegt?

Verstehe ich noch nicht ganz: du schreibst etwas von einem Offset
in Mikrosekunden.  Das ist doch dann immer eindeutig.  Sinnvollerweise
solltest du natürlich zuerst die Umrechnung in einen time_t machen,
und erst danach den Offset addieren (denn time_t ist eine monotone
Skala).

von Karl H. (kbuchegg)


Lesenswert?

Philip K. schrieb:
> Irgendwie macht mir da Thema einen Knoten ins Gehirn. Wirklich schlauer
> bin ich immer noch nicht. Also versuch ichs mal mit der Beschreibung
> meines konkreten Anwendungsfalls.
> Ich habe eine Log-Datei, die einen Haufen Analog- und Status-Samples
> enthält. Zu diesen Werten gehört u.a. ein Trigger-Zeitstempel,

Und genau da liegt die Frage.
Dieser Trigger Zeitstempel - wer hat den erstellt? Welche Zeit hat 
derjenige genommen? Macht der eine entsprechende Sommerzeit Korrektur 
oder nicht?

> ein anderes Format, dass anstelle des Offsets einen zusätzlichen
> Start-Zeitstempel enthält.

Und auch hier wieder die Frage:
Muss in diesem anderen Format Sommerzeit berücksichtigt sein oder nicht?


> - Befüllen eines tm-struct mit den Zeitdaten aus der Datei (Btw. ich
> habe an dieser Stelle keine Info, ob es sich um local- oder UTC-time
> handelt, weiß aber dass beide Fälle möglich sind). Dabei habe ich bisher
> tm_isdst = 1 gesetzt, ohne wirklich zu wissen ob das richtig ist.

Diese beiden Dinge beissen sich.
Um zu wissen, auf welchen Wert du tm_isdist zu setzen hast, musst du 
wissen ob die originalen Zeitstempel mit oder ohne Berücksichtigung der 
Sommerzeit gewonnen wurden.


> Da ich das Abziehen der Stunde nicht ...

Du redest dauernd von 'Abziehen von einer Stunde'.
Diese 1 Stunde Differenz ist nichts anders als die Korrektur für 
Sommerzeit. Hast du eine Uhr, die ein ganzes Jahr lang durchläuft ohne 
dass du die angreifst oder verstellst, dann hast du im Winter die 
Situation, dass diese Uhr mit der Uhr im Fernsehen übereinstimmt, im 
Sommer aber um 1 Stunde falsch geht in Bezug auf die Uhr im Fernsehen. 
Das ist genau diese 1 Stunde, die mit dem Flag berücksichtigt wird oder 
auch nicht. Es ist genau die 1 Stunde um die du deine Armbanduhr in 
jener bewussten Nacht im März bzw. Oktober vor bzw. zurückstellst.

: Bearbeitet durch User
von Philip K. (philip_k)


Lesenswert?

Jörg Wunsch schrieb:
> Du musst es auf -1 setzen, denn das heißt „ich weiß nicht, ob da
> Sommerzeit war oder nicht“.  Dann muss mktime() es selbst rausfinden,
> was bis auf die Doppeldeutigkeit am Tag des Zurückschaltens kein
> Problem ist.
Ok, liefert das gleiche Ergebnis wie wenn ich 0 setze.

Jörg Wunsch schrieb:
> Nur, wenn du Zeitstempel innerhalb dieses Zeitfensters (1 h pro
> Jahr) auswerten musst, müsstest du mktime() durch explizites Setzen
> von tm_isdst auf 0 oder 1 auf die Sprünge helfen, welche der beiden
> Möglichkeiten gemeint ist.
Jetzt habe ich zum ersten Mal den Sinn dieses Wertes verstanden :-)

Jörg Wunsch schrieb:
>> - Wenn die Ausgangs-Zeitinformation in UTC ist und ich wie oben
>> beschreiben nach der Differenzbildung per localtime() zurück wandle,
>> habe ich dann ein falsches Ergebnis?
>
> Ja.
Aber warum? Ich berechne ja nur eine Differenz zu einer gegebenen Zeit.
13:34:23 - 5 Sekunden ist 13:34:18, unabhängig von der Zeitzone.

Jörg Wunsch schrieb:
>> - Was passiert, wenn der Start-Zeitpunk vor und der Trigger-Zeitpunkt
>> nach einer Zeitumschaltung liegt?
> Verstehe ich noch nicht ganz: du schreibst etwas von einem Offset
> in Mikrosekunden.  Das ist doch dann immer eindeutig.
Die Anzahl der Microsekunden ist beliebig groß (64 Bit). Wenn der 
Trigger 1 Sekunde nach der Umstellung auf Winterzeit kommt, also um 
02:00:01 und der Offset 2 s beträgt, liegt der berechnete Startzeitpunkt 
bei 01:59:59. Tatsächlich war er aber bei 02:59:59 Sommerzeit. Wobei ich 
mich gerade wirklich Frage, ob das für meine Anwendung eine große Rolle 
spielt...

Karl Heinz schrieb:
> Und genau da liegt die Frage.
> Dieser Trigger Zeitstempel - wer hat den erstellt? Welche Zeit hat
> derjenige genommen? Macht der eine entsprechende Sommerzeit Korrektur
> oder nicht?
Erzeugt wird er von einer Embedded (Linux) CPU als UTC. Diese überträgt 
die Daten an ein Tool auf einem Windows PC, das die Daten in eine Datei 
speichert. Hier wird je nach User-Einstellung die UTC beibehalten oder 
in Lokalzeit gewandelt. Dabei wird auch die Sommer/Winterzeit 
berücksichtigt.
Mit dieser Datei wird mein Konvertierungs-Tool gespeist. Nach der 
Konvertierung sollte der Trigger-Zeitstempel identisch sein und der 
Start-Zeitstempel um den angegebenen Offset früher.

Wenn ich Dich richtig verstehe, geht die Funktion also von einer 
"durchlaufenden" Uhr als Quelle des Eingangswertes aus. Allerdings 
verhält es sich offenbar genau umgekehrt wie von Dir beschrieben:
Setze ich das tm auf 11/2/2015,15:31:00 steht nach dem Funktionsaufruf 
4/2/2015,14:31:00 drin, wenn ich 4/8/2015,14:31:00 setze, bleiben die 
Werte unverändert. Es wird also die Zeit im Winter korrigiert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Philip K. schrieb:
> Wenn ich Dich richtig verstehe, geht die Funktion also von einer
> "durchlaufenden" Uhr als Quelle des Eingangswertes aus.

Andersrum: time_t ist monoton durchlaufend, also das Ergebnis des
Aufrufs.

von Jay (Gast)


Lesenswert?

Philip K. schrieb:
> Aber warum? Ich berechne ja nur eine Differenz zu einer gegebenen Zeit.
> 13:34:23 - 5 Sekunden ist 13:34:18, unabhängig von der Zeitzone.

Bei diesem Beispiel. Allgemein ist das aber nicht so. Liegt im 
Zeitbereich gerade der Wechsel der Sommerzeit, dann kann das Ergebnis um 
eine Stunde falsch sein.

Es sind genau diese Sonderfälle, die einem den Hals brechen können und 
bei denen man schnell lernt, dass Sommerzeit einfach Scheiße ist.

von Philip K. (philip_k)


Lesenswert?

Jörg Wunsch schrieb:
>> Wenn ich Dich richtig verstehe, geht die Funktion also von einer
>> "durchlaufenden" Uhr als Quelle des Eingangswertes aus.
> Andersrum: time_t ist monoton durchlaufend, also das Ergebnis des
> Aufrufs.
Dann versteh ich immer noch nicht, wieso der Eingangswert verändert 
wird.

von Philip K. (philip_k)


Lesenswert?

Jay schrieb:
>...dass Sommerzeit einfach Scheiße ist.
So ist es. Auch im Alltag. Gab es nicht mal Pläne das wieder 
abzuschaffen, weil die erhoffte Wirkung eh ausblieb?

von Jay (Gast)


Lesenswert?

Philip K. schrieb:
> Jörg Wunsch schrieb:
>>> Wenn ich Dich richtig verstehe, geht die Funktion also von einer
>>> "durchlaufenden" Uhr als Quelle des Eingangswertes aus.
>> Andersrum: time_t ist monoton durchlaufend, also das Ergebnis des
>> Aufrufs.
> Dann versteh ich immer noch nicht, wieso der Eingangswert verändert
> wird.

Weil du eine Funktion verwendest (mktime()), die die lokale, sprich 
Küchenuhr-Zeit zurück auf time_t berechnet. Und diese verfluchte 
Küchenuhr-Zeit springt nun mal zu Beginn und Ende der Sommerzeit. Das 
muss mktime() ausgleichen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Philip K. schrieb:
> Dann versteh ich immer noch nicht, wieso der Eingangswert verändert
> wird.

Weil die Funktion mktime() so spezifiziert ist, dass sie die
Eingangswerte bei Rückkehr normalisiert.  Zitat C-Standard:
1
[...] On successful
2
completion, the values of the tm_wday and tm_yday components of the structure are
3
set appropriately, and the other components are set to represent the specified calendar
4
time, but with their values forced to the ranges indicated above; the final value of
5
tm_mday is not set until tm_mon and tm_year are determined.

Die Funktion ist so angelegt, dass man auch Werte außerhalb des
normal gültigen Wertebereiches reingeben darf.  Du kannst also mit
einem 33. Oktober in die Funktion hineingehen, es berechnet dir
daraus den zugehörigen time_t-Wert, und die struct tm wird bei der
Rückgabe so korrigiert, dass dann der 3. November drin steht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.