Immer diese Zeitprobleme Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Immer diese Zeitprobleme

11 Jul 2023, 21:03

Good day everyone!

Code: Select all

FormatTime, Start_Calc, HH24MISS, HHmmss    ; nur damit klappt das Rechnen
FormatTime, Start_Show, HH24MISS, HH:mm:ss  ; aber so soll es in der MsgBox dastehen

sleep 3000

FormatTime, Stop_Calc, HH24MISS, HHmmss     ; dito, siehe oben
FormatTime, Stop_Show, HH24MISS, HH:mm:ss   ; dito, siehe oben

Time_Calc := Stop_Calc - Start_Calc
MsgBox % Time_Calc  ; Kontrolle: die Rechnung mit Time_Calc stimmt!

FormatTime, Time_Show, %Time_Calc%, HH:mm:ss  ; aber das funktioniert nicht:
MsgBox %Start_Show%`tStartzeit`n%Stop_Show%`tStopzeit`n--------------------`n%Time_Show%`tDauer

Bei "Dauer" sollte "00:00:03" dastehen.
Oder "01:23:56" - je nach Wert bei sleep.

Was ist das Problem?

Grüße, Stroker-007
User avatar
flyingDman
Posts: 2832
Joined: 29 Sep 2013, 19:01

Re: Immer diese Zeitprobleme

11 Jul 2023, 23:52

Es ist besser, a_tickcount zu verwenden. Erstens erhalten Sie dadurch eine höhere Präzision. Zweitens ist es einfacher.

Code: Select all

start := A_TickCount
sleep, 3000
stop  := A_TickCount

MsgBox, % sec2hhmmss(round((stop-start)/1000))

sec2hhmmss(secs) 
	{
	hours := substr("0" secs//3600,-1)
	tmstmp := 16010101000000
	tmstmp += secs, s
	FormatTime, hhmmss, % tmstmp, % hours ":mm:ss"
	Return hhmmss
	}
14.3 & 1.3.7
just me
Posts: 9530
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Immer diese Zeitprobleme  Topic is solved

12 Jul 2023, 02:21

Moin @Stroker-007,

für das Rechnen mit Datum-Zeit-Angaben gibt es ein besonderes Format. Das wird bei EnvAdd und EnvSub konkret beschrieben. Um 'auf der sicheren Seite' zu sein, brauchst Du immer das YYYYMMDDHH24MISS-Format. Dieses Format wird auch als Eingabewert für FormatTime benötigt. Dabei kannst Du Teile auf der rechten Seite weglassen. Sie werden durch Standardwerte ersetzt.

Die Differenz zwischen den Datum-Zeit-Werten kannst Du nur in Zeiteinheiten wie Sekunden, Minuten, usw. berechnen. Wenn Du eine Dauerangabe wie "HH:MM:SS" haben willst, musst Du die selbst berechnen. Bei einer Differez in Sekunden kannst Du dafür eine Funktion wie die von flyingDman nutzen.

Code: Select all

Start := A_Now ; mit aktuellem Datum-Zeit-Wert starten
SLeep, 3000
Sekunden := A_Now - Start, S
MsgBox, Sekunden: %Sekunden% ; kann auch mal 2 sein
Sekunden := 4000 ; zur Veranschaulichung
MsgBox, % SekundenAlsDauer(Sekunden)

SekundenAlsDauer(S) {
   ; Std := S // 3600
   ; Min := Mod(S, 3600) // 60
   ; Sek := Mod(S, 60) 
   Return Format("{:02}:{:02}:{:02}", S // 3600, Mod(S, 3600) // 60, Mod(S, 60))
}
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Immer diese Zeitprobleme

12 Jul 2023, 19:44

Vielen Dank für die Anregungen, die jede für sich top funktionieren.

Habe etliche Stunden damit experimentiert, mit - für mich - eher bescheidenen Ergebnissen, weil ich wesentlichew Aspekte davon nicht verstehe:

bei flyingDman:
Alles was unten im Funktionsblock steht. Ist jetzt für mich aber insofern nicht so relevant, weil es nur im Sekundenbereich spielt, und weil ich es mangels Verständnis nicht in einen globalen Bereich ändern kann.

bei just me:
Die letzte Zeile "Format(..." im Funktionsblock, obwohl darüber so wunderbar kommentiert. Aber sie funktioniert für meinen Zweck dieser Anfrage.

Kommt noch dazu, daß ich auf der Hilfeseite "Format()" samt und sonders nur Bahnhof verstehe. Mit "FormatTime" komm ich schon eher zurecht und habe auch bisher schon einiges damit gemacht, aber damit läßt sich ja anscheinend nicht gut rechnen. Auch mit der wechselseitigen Werte-Übergabe zw. Hauptzeile und Funktionsblock (ganz allgemein) habe ich noch logische Probleme, was das ganze nicht erleichtert: Hilfeseite "Funktionen" - die Einführung geht grade mal so, dann steig ich mehr und mehr aus...

Das Ergebnis für mein Beispiel heißt jetzt also so:

Code: Select all

 
FormatTime, Start_Calc, HH24MISS, HHmmss    ; nur damit klappt das Rechnen
FormatTime, Start_Show, HH24MISS, HH:mm:ss  ; aber so soll es in der MsgBox dastehen

sleep 3000

FormatTime, Stop_Calc, HH24MISS, HHmmss     ; dito, siehe oben
FormatTime, Stop_Show, HH24MISS, HH:mm:ss   ; dito, siehe oben

Time_Calc := Stop_Calc - Start_Calc
;Time_Calc := 54321  ; Test für die Formatierung: paßt.

; frei nach just me:
Time_Show := Format("{:02}:{:02}:{:02}", Time_Calc // 3600, Mod(Time_Calc, 3600) // 60, Mod(Time_Calc, 60))

MsgBox %Start_Show%`tStartzeit`n%Stop_Show%`tStopzeit`n--------------------`n%Time_Show%`tDauer  ; paßt - Danke!

Ein Versuch, der zwar in Teilen und Varianten, aber nie komplett funktioniert:

Code: Select all

Start := A_Now
sleep 3000
Stop := A_Now
Time := Stop - Start

FormatTime, StartForm, Start, HH:mm:ss
FormatTime, StopForm, Stop, HH:mm:ss
; oder:
;StartForm := Format("{:02}:{:02}:{:02}", Start // 3600, Mod(Start, 3600) // 60, Mod(Start, 60))
;StopForm := Format("{:02}:{:02}:{:02}", Stop // 3600, Mod(Stop, 3600) // 60, Mod(Stop, 60))

TimeForm := Format("{:02}:{:02}:{:02}", Time // 3600, Mod(Time, 3600) // 60, Mod(Time, 60))

MsgBox %StartForm%`tStartzeit`n%StopForm%`tStopzeit`n--------------------`n%TimeForm%`tDauer  ; ach nööö...

Das ist jetzt mein Status auf die Schnelle, um euch eine ehrliche Antwort zu geben. Wenn ich mich - in Ruhe - länger mit diesen mathematisch-formelhaften Geschichten beschäftige, könnte wahrscheinlich durchaus das ein oder andere zu mir durchsickern. Da brauch ich jetzt einfach ein bißchen... ;-)

Grüße, Stroker-007
just me
Posts: 9530
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Immer diese Zeitprobleme

13 Jul 2023, 04:30

Moin @Stroker-007,

ein Problem liegt hier:

Code: Select all

Time := Stop - Start
Man kann mit Zeitstempeln so nicht rechnen, weil Zeiten nicht wirklich im Dezimalsystem abgebildet werden. Eine Minute hat 60 statt 100 Sekunden, eine Stunde hat 60 statt 100 Minuten, usw.
(Man kann damit aber auch nicht so rechnen, wie ich es in meinem Beispiel gemacht habe, Schande über mich! :oops:)

Nur wenn Du innerhalb einer Minute bleibst, geht das gut:

Code: Select all

Start := 20230713111300
Ende := 20230713111303 ; +3 Sekunden
MsgBox, % Ende - Start ; ergibt 3
Sobald sich aber Minute, Stunde, Tag oder Monat ändern, klappt das nicht mehr:

Code: Select all

Start := 20230713111359
Ende := 20230713111402 ; +3 Sekunden
MsgBox, % Ende - Start ; ergibt 43
Deshalb muss man zu Rechnen mit Zeitstempeln eigene Routinen entwickeln oder das eingebaute Ende -= Start, S benutzen:

Code: Select all

Start := 20230713111359
Ende := 20230713111402
Ende -= Start, S ; Ende enthält danach die Zeitdifferenz in Sekunden
MsgBox, %Ende% ; ergibt 3
Probier das mal, just me

(Zum Thema Format() könnte ich auch versuchen, es etwas genauer zu erklären)
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Immer diese Zeitprobleme

14 Jul 2023, 07:33

Back to the roots and step by step:

Code: Select all

Start := 20230714125725  ; Einen solchen Wert liefert beispielsweise "A_Now".
Stop := 20230714130442   ; Das sind per Hand gerechnet 437 Sekunden Differenz. 

; Jetzt sind wir sehr gespannt, ob AHK das auch kann.
; Dazu verwenden wir EnvSub bzw. sein Ausdrucks-Pedant:

Time := Stop
EnvSub, Time, %Start%, s
MsgBox %Start% - %Stop% - %Time%

; Bravissimo!

; Und nun kommt "FormatTime" ins Spiel, um seine Stärken auszufahren:

FormatTime, ShowTime, %Time%, hh:mm:ss
MsgBox % ShowTime

; knackig daneben, wo ich doch so genau gelesen und so logisch gedacht habe...

; Das aber geht:

FormatTime, ShowStart, %Start%, hh:mm:ss
MsgBox % ShowStart  ; wenigstens etwas... 


Ich zitiere jetzt aus FormatTime, Abschnitt "YYYYMMDD..."
"Ansonsten können Sie den kompletten oder beginnenden Teil eines Zeitstempels im YYYYMMDDHH24MISS-Format angeben."

"437" ist für FormatTime offensichtlich "kein" beginnender Teil eines Zeitstempels.
Ein Versuch, dieser Forderung mit einem für FormatTime vertrauteren Muster, nämlich 6-stellig wie hh:mm:ss, nachzukommen, scheitert ebenfalls:

Code: Select all

Timex := "000" 437
MsgBox % Timex  ; gut so!

FormatTime, ShowTime, %Timex%, hh:mm:ss
MsgBox % ShowTime  ; nix wars

Die Gretchenfrage lautet also:

Wie kann man eine Zahl wie 437, als eine definierte Zeitangabe von 437 Sekunden, in einen "kompletten oder beginnenden Teil eines Zeitstempels im YYYYMMDDHH24MISS-Format" umwandeln? Noch genauer: Was muß anstelle von "000" (siehe oben) davor gesetzt werden, um der Formulierung Genüge zu tun?

Wirkt irgendwie bereits kabarettistisch, die Frage so formulieren zu müssen.
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Immer diese Zeitprobleme

14 Jul 2023, 22:09

Jetzt hab ich mich nochmal mit der Angelegenheit befaßt und es scheint was rübergewachsen zu sein:

Code: Select all

Zahl := 53606  ; wird hiermit zu Anzahl Sekunden erklärt
hh := Floor(Zahl / 3600)           
mm := Floor(Mod(Zahl, 3600) / 60)
ss := Mod(Zahl, 60)
MsgBox % hh ":" mm ":" ss
; oder:
MsgBox % Floor(Zahl/3600) ":" Floor(Mod(Zahl,3600)/60) ":" Mod(Zahl,60)
; paßt.

Sodann durfte ich feststellen, daß das dasselbe ist, was just me mit Format realisiert hast, wobei bei Format durch die "Formatierung" (haha) Floor eingespaart wird. Insofern habe ich jetzt auch einen Zugang zum Verständnis von Format gefunden. Vielen Dank!

Zu allem Überfluß dann noch die Entdeckung von Beispiel #3 bei FormatTime: "Wandelt eine bestimmte Anzahl von Sekunden in Stunden, Minuten und Sekunden um (hh:mm:ss-Format)." - was ich bis dato aber immer überlesen habe, weil ich nur immer gleich auf die Skripte schau. Und das dort ist wieder mal so typisch funktions-verklausuliert, was zu verstehen ich bestenfalls nach dem "Urlaub" angehe :think:

Meine eingangs gestellte Aufgabe könnte nun so formuliert werden:

Code: Select all

Start := A_Now
sleep 3000
Stop := A_Now
Time := Stop
Time -= %Start%, s

FormatTime, ShowStart, %Start%, hh:mm:ss
FormatTime, ShowStop, %Stop%, hh:mm:ss
ShowTime := Floor(Time/3600) ":" Floor(Mod(Time,3600)/60) ":" Mod(Time,60)

MsgBox %ShowStart%`tStartzeit`n%ShowStop%`tStopzeit`n--------------------`n%ShowTime%`tDauer

Hat aber noch 2 Schönheitsfehler:

1. Meine Berechnung mit den Mathe-Funktionen schreibt keine führenden Nullen. In diesem Beispiel mit den 3 Sek heißt es dann eben nur "0:0:3". Nach meiner Lesart der Mathe-Seite gibt es dort keine Funktion für das Erzwingen von führenden Nullen. Insofern ist die Methode über Format letztlich doch die Bessere, weshalb sich just me dafür nicht unbedingt rügen bräuchte, sach ich mal.

2. Bei A-Now steht zu lesen: "Die interne Variable A_Now enthält die aktuelle Ortszeit im YYYYMMDDHH24MISS-Format." Ich seh aber nur das 12er-Format im pm-Zeitraum. Am Rechner kanns nicht liegen, der zeigt das 24er. Erklärung?

Auf der Suche nach einer perfekten Standard-Formulierung taugt auch das Beispiel #3 bei FormatTime nur bedingt, weil es zumindest bei meinen Tests ebenfalls keine führenden Nullen kennt.

Das Problem bei meinem angestrebten MsgBox-Ergebnis ist wohl auch, daß es 2 Bereiche zur gleichen Zeit will, was "in der Natur" so eher selten vorkommen dürfte: Entweder man will den aktuellen Zeitpunkt in gewohnter Lesart darstellen, oder man will eine Zeitdifferenz zw. 2 Ereignissen messen oder stoppen, wobei es dann i.d.R. egal ist, um welche Uhrzeit das stattgefunden hat.
just me
Posts: 9530
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Immer diese Zeitprobleme

15 Jul 2023, 03:39

Moin @Stroker-007,

Stroker-007 wrote: 2. Bei A-Now steht zu lesen: "Die interne Variable A_Now enthält die aktuelle Ortszeit im YYYYMMDDHH24MISS-Format." Ich seh aber nur das 12er-Format im pm-Zeitraum. Am Rechner kanns nicht liegen, der zeigt das 24er. Erklärung?
FormatTime ist eine der wenigen AHK-Anweisungen, bei denen (zumindest in Teilen) Groß/Klein-Schreibung wichtig ist. Um die Stunde zweistellig im 24-Stunden-Format zu erhalten, musst Du das Format für die Stunden groß schreiben: HH.
:arrow: Zeitformate (Groß-/Kleinschreibung-sensitiv)

Stroker-007 wrote: 1. Meine Berechnung mit den Mathe-Funktionen schreibt keine führenden Nullen. In diesem Beispiel mit den 3 Sek heißt es dann eben nur "0:0:3". Nach meiner Lesart der Mathe-Seite gibt es dort keine Funktion für das Erzwingen von führenden Nullen.
Stimmt! Bevor es die Format() Funktion gab, hat man die Sache meistens so gelöst:

Code: Select all

; dynamisch:
Zahl := 3
MsgBox, % SubStr("0" . Zahl, -1) ; hier muss man sicher sein, dass Zahl nicht mehr als zwei Stellen haben kann
; statisch
Zahl := 3
If StrLen(Zahl) = 1
	Zahl := "0" . Zahl
MsgBox, %Zahl%
; oder
Zahl := 3
If (Zahl < 10)
	Zahl := "0" . Zahl
MsgBox, %Zahl%
Mit der Format() Fuktion wurde das dann einfacher. Im ersten Parameter (FormatZkette) kann man Platzhalter mit Formatierungsangaben einsetzen, in die die Werte aus den folgenden Parametern übernommen werden.
Ein Platzhalter wird immer durch geschweifte Klammern begrenzt: {}.
Der öffnenden Klammer folgt der Index des nachfolgenden Parameters, dessen Wert übernommen werden soll. Das braucht man nur dann, wenn die Reihenfolge bei der Ersetzung von der Reihenfolge der Parameter abweichen soll.
Index und Formatangaben werden durch einen Doppelpunkt : getrennt.
Die Formatangabe ist im gegebenen Beispiel für alle Parameter 02, d.h., der Wert soll mindestens zweistellig ausgegeben werden (2). Wenn erforderlich, sollen ihm dafür Nullen (0) vorangestellt werden.
Für 3 Parameter, die durch einen Doppelpunkt getrennt werden sollen, ergibt sich damit die FormatZkette: "{:02}:{:02}:{:02}"

Stroker-007 wrote: ..., weshalb sich just me dafür nicht unbedingt rügen bräuchte, sach ich mal.
Doch, muss ich. Meine Selbstkritik bezog sich ja nicht auf die Formatfunktion, sondern auf:

Code: Select all

Sekunden := A_Now - Start, S

Und zum Schluss:

Code: Select all

hh := Floor(Zahl / 3600) ; Gleitkommarechnung
; entspricht
hh := Zahl // 3600 ; Ganzzahlrechnung         
Dabei können die allermeisten Rechner mit Ganzzahlen schneller rechnen. Es wäre für die Verständlichkeit wahrscheinlich besser gewesen, wenn ich die Funktion SekundenAlsDauer() doch in ihrer ursprünglichen Form eingestellt hätte:

Code: Select all

SekundenAlsDauer(S) {
   Std := S // 3600
   Min := Mod(S, 3600) // 60
   Sek := Mod(S, 60) 
   Return Format("{:02}:{:02}:{:02}", Std, Min, Sek)
}

Angesichts der Wetterlage an Dich und alle anderen: Keep cool!
Stroker-007
Posts: 135
Joined: 28 Jan 2021, 17:09
Location: Germany

Re: Immer diese Zeitprobleme

16 Jul 2023, 22:50

Das Wochenende ist überstanden. Ich lebe noch, grad mal so....... :yawn:

Hallo @just me,

daß FormatTime groß-/klein-schreibe-sensitiv ist, wußte ich, hab ich hier aber übersehen, und die Schuld dann A-Now zugeschoben.
Entschuldige mich hiermit respektvoll bei diesem Befehl :angel:.
Alles weitere hast Du vorbildlich erklärt und konnte es dann nochmal perfekt in der Hilfe nachvollziehen.

Die finale Fassung für dieses Grundmuster zu Berechnung und Darstellung von Zeiten, und in Anlehnung an mein eingangs formuliertes Beispiel, heißt jetzt demnach:

Code: Select all

; Beispiel als Formel zu Berechnung und Darstellung von Zeiteinheiten

Start := A_Now
sleep 7000
Stop := A_Now
Time := Stop
Time -= %Start%, s

;Time := 4085  ; zu Testzwecken

FormatTime, ShowStart, %Start%, HH:mm:ss
FormatTime, ShowStop, %Stop%, HH:mm:ss
ShowTime := Format("{:02}:{:02}:{:02}", (Time//3600), (Mod(Time,3600)//60), Mod(Time,60))

MsgBox %ShowStart%`tStartzeit`n%ShowStop%`tStopzeit`n--------------------`n%ShowTime%`tDauer

; oder wer´s so lieber mag ;-) :

MsgBox % ShowStart "`tStartzeit`n" ShowStop "`tStopzeit`n--------------------`n" ShowTime "`tDauer"

; Meine Devise: je mehr Normaltext eine Ausgabe hat, desto schreib- und lese-bekömmlicher ist legacy. Wie Schweinsbraten mit Schnaps.
; "Lesetext als " Ausdruck "ist dann wie Schokopudding - sauer eingelegt."

Möge das Skript dem ein oder anderen (Jungspund, wie ich) bei diversen Vorhaben nützlich sein.
Meinen bisweilen etwas kabarettistischen Stil bitte ich nachzusehen :shifty: .

Stroker-007

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 27 guests