Zeitangaben, rechnen mit: Unterschied zwischen den Versionen
Trelle (Diskussion | Beiträge) |
TomLee (Diskussion | Beiträge) K (Formatierung angepasst) |
||
(23 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
Mit leicht lesbaren Zeitangaben, wie ''07:30'', ''23.05.2017, 09:20'' usw. kann in FHEM nicht ohne Weiteres gerechnet werden, da es sich um Zeichenketten handelt und nicht um Zahlen. | Mit leicht lesbaren Zeitangaben, wie ''07:30'', ''23.05.2017, 09:20'' usw. kann in FHEM nicht ohne Weiteres gerechnet werden, da es sich um Zeichenketten handelt und nicht um Zahlen. | ||
== Verfahren zum Rechnen mit Zeitangaben, die als Zeichenkette vorliegen == | == Verfahren zum Rechnen mit Zeitangaben, die als Zeichenkette vorliegen == | ||
Die Berechnung erfolgt in Perl. | Die Berechnung erfolgt in Perl. Das Verfahren besteht aus drei Schritten: | ||
Das Verfahren besteht aus drei Schritten: | |||
* Umwandeln der Zeichenketten in eine Zahl, z.B. Sekunden. | * Umwandeln der Zeichenketten in eine Zahl, z.B. Sekunden. | ||
* Berechen einer Zeit als Zahl. | * Berechen einer Zeit als Zahl. | ||
Zeile 10: | Zeile 8: | ||
=== Umwandeln eine Zeichenkette in eine Zahl === | === Umwandeln eine Zeichenkette in eine Zahl === | ||
{{Randnotiz|RNTyp=Info|RNText= Hinweis! | |||
* Die von <code>timelocal</code> erwartete Monatsangabe sind Ganzzahlwerte von 0 bis 11 für Januar bis Dezember.}} | |||
Hier hängt das Verfahren von der Struktur der Zeichenkette ab. | Hier hängt das Verfahren von der Struktur der Zeichenkette ab. | ||
Perl und FHEM stellen Funktionen zur Umwandlung bereit. | Perl und FHEM stellen Funktionen zur Umwandlung bereit. | ||
* <code>time</code> liefert die aktuelle Zeit in Sekunden | * <code>time</code> liefert die aktuelle Zeit in Sekunden <ref>http://perldoc.perl.org/functions/time.html</ref> | ||
* <code>time_str2num("YYYY-MM-DD HH:MM:SS")</code> wandelt einen FHEM-Zeitstempel in Sekunden um | * <code>time_str2num("YYYY-MM-DD HH:MM:SS")</code> wandelt einen FHEM-Zeitstempel in Sekunden um <ref>{{Link2CmdRef|Lang=de|Anker=perl}}</ref> | ||
* <code>timelocal(<Sekunden>, <Minuten>, <Stunden>, <Tag des Monats>, <Monat>, <Jahr>)</code> wandelt einen Satz von Zeitelementen (Sekunden, Minuten, Stunden usw.) in Sekunden um | * <code>timelocal(<Sekunden>, <Minuten>, <Stunden>, <Tag des Monats>, <Monat>, <Jahr>)</code> wandelt einen Satz von Zeitelementen (Sekunden, Minuten, Stunden usw.) in Sekunden um <ref>http://perldoc.perl.org/Time/Local.html</ref> | ||
* <code>Sekunden + Minuten * 60 + Stunden * 60 * 60 + Tage * 24 * 60 * 60</code> berechnen eines Summanden oder Subtrahenden aus Sekunden, Minuten, Stunden und Tagen. | * <code>Sekunden + Minuten * 60 + Stunden * 60 * 60 + Tage * 24 * 60 * 60</code> berechnen eines Summanden oder Subtrahenden aus Sekunden, Minuten, Stunden und Tagen. | ||
==== Beispiel: Zeitstempel eines Readings in Sekunden umwandeln ==== | ==== Beispiel: Zeitstempel eines Readings in Sekunden umwandeln ==== | ||
time_str2num(ReadingsTimestamp(<devicename>, <reading>,<defaultvalue>)) | time_str2num(ReadingsTimestamp(<devicename>, <reading>,<defaultvalue>)) | ||
==== Konstanten innerhalb FHEM ==== | |||
FHEM stellt einige Konstanten<ref>{{Link2Forum|Topic=96959|Msg=901268|LinkText=Forum-Thread}}</ref> bereit, um das Rechnen mit Zeiten zu erleichtern, ''DAYSECONDS'', ''HOURSECONDS'', und ''MINUTESECONDS''. Obiger Code kann also auch so geschrieben werden: | |||
Sekunden + Minuten * MINUTESECONDS + Stunden * HOURSECONDS + Tage * DAYSECONDS | |||
=== | === Umwandeln einer Zahl in eine Zeichenkette === | ||
{{Randnotiz|RNTyp=Info|RNText= Hinweis! | |||
* Die von <code>localtime</code> zurückgegebene Monatsangabe liegt im Bereich der Ganzzahlwerte 0 bis 11 für Januar bis Dezember. | |||
* Werden keine Parameter angegeben, bezieht sich die Ausgabe auf den aktuellen Zeitpunkt.}} | |||
Zur Umwandlung seien die folgenden Perl-Funktionen genannt: | |||
* <code>"HH:MM, DD.MM.YY" =~ /(\d\d).(\d\d)..(\d\d).(\d\d).(\d\d)/</code> extrahiert HH,MM,DD,MM und YY aus der Zeichenkette HH:MM, DD.MM.YY, die ein Datum in der angegebenen Form enthält. \d steht für eine Ziffer, der Punkt für ein beliebiges Zeichen, die () schreiben den Treffer in spezielle Variablen in der Reihenfolge ihrer Anordnung HH in $1, MM in $2, DD in $3 usw. | |||
* <code>(Sekunden, Minuten, Stunden, Tag des Monats, Monat, Jahr, Nummer des Wochentages, Tag des Jahres, Sommerzeitkennzeichen) = localtime(Zeit in Sekunden)</code> gibt die einzelnen Zeitelemente zurück <ref>http://perldoc.perl.org/functions/localtime.html</ref> | |||
* <code>POSIX::strftime(<Format>,<Array mit Zeitelementen>)</code>, wandelt ein Array aus Zeitelementen, wie es <code>localtime</code> liefert in eine formatierte Zeichenkette um. <Format> wird mit Hilfe bestimmter Formatierungszeichen (%a für den Wochentagnamen, %d für den Tag des Monats usw. <ref>http://search.cpan.org/~dexter/POSIX-strftime-GNU-0.02/lib/POSIX/strftime/GNU.pm</ref>) festgelegt. | |||
=== | ==== Beispiel: Wochentag zu Datum ==== | ||
Zum heutigen Datum | |||
<syntaxhighlight lang="perl"> | |||
{return strftime("%A",localtime)} | |||
</syntaxhighlight> | |||
Zu einem vorgegebenen Datum<syntaxhighlight lang="perl"> | |||
{ | |||
my ($d,$m,$y) = split(/\./,"06.09.2021"); | |||
$m-=1; | |||
return strftime("%A",localtime(timelocal('0','0','0',$d,$m,$y))); | |||
} | |||
</syntaxhighlight> | |||
=== Berechnungsbeispiele === | |||
Allen Berechnungen zu Grunde liegt die Vorgehensweise in absoluten Sekunden bezogen auf einen Referenzzeitpunkt zu rechnen. Damit umgeht man jeden Wechsel Stunden/Tage/Monate/Jahre. | |||
Die einzeiligen Beispiele sollten im Eingabefeld von FHEMWEB ausführbar sein. | |||
==== Addition zu einem Zeitstempel ==== | |||
Gegeben sei ein [[Readings|Reading]] ''motion'' des [[Gerät|Gerätes]] ''BM1'' mit einem Zeitstempel ''2017-08-11 14:17:13''. Es sollen 2 Stunden und 12 Minuten addiert werden und das Ergebnis als HH:MM dargestellt werden. | |||
<syntaxhighlight lang="perl">{POSIX::strftime("%H:%M",localtime(time_str2num(ReadingsTimestamp("BM1","motion","2000-01-01 00:00:00"))+2*60*60+12*60))}</syntaxhighlight> | |||
Schrittweise: | |||
<syntaxhighlight lang="perl">{ | |||
my $timestamp = ReadingsTimestamp("BM1","motion","2000-01-01 00:00:00"); | |||
my $seconds = time_str2num($timestamp)+2*60*60+12*60; | |||
my $result = POSIX::strftime("%H:%M",localtime($seconds)); | |||
return $result; | |||
}</syntaxhighlight> | |||
==== Addition zum aktuellen Zeitpunkt ==== | |||
Zur aktuellen Zeit sollen 30 Minuten addiert und das Ergebnis als HH:MM:SS dargestellt werden. | |||
<syntaxhighlight lang="perl">{POSIX::strftime("%H:%M:%S",localtime(time+30*60))}</syntaxhighlight> | |||
==== Subtraktion vom aktuellen Zeitpunkt ==== | |||
Zur aktuellen Zeit sollen 45 Minuten subtrahiert und das Ergebnis als HH:MM:SS dargestellt werden. | |||
<syntaxhighlight lang="perl">{POSIX::strftime("%H:%M:%S",localtime(time-45*60))}</syntaxhighlight> | |||
==== Kalendertage von heute bis zu einem Datum ==== | |||
Zu einem bestimmten Kalendertag soll die Differenz in ganzen Tagen bestimmt werden.<syntaxhighlight lang="perl"> | |||
{(time_str2num('2021-04-30') - time_str2num(strftime '%F',localtime))/86400} | |||
</syntaxhighlight>Das Zieldatum kann z.B. ein Termin aus dem Kalender sein: | |||
:<code>fhem('get AbfallKalender events timeFormat:"%F" format:custom="$T1" limit:from=0,count=1')</code> | |||
=== Weitere Funktionen zur Zeitumwandlung === | === Weitere Funktionen zur Zeitumwandlung === | ||
* [[DevelopmentModuleAPI#Time_.2F_Timestamp|Time/Timestamp]] | * [[DevelopmentModuleAPI#Time_.2F_Timestamp|Time/Timestamp]] | ||
== Links == | |||
<references /> | |||
[[Kategorie:HOWTOS]] | [[Kategorie:HOWTOS]] |
Aktuelle Version vom 22. Dezember 2022, 13:18 Uhr
Mit leicht lesbaren Zeitangaben, wie 07:30, 23.05.2017, 09:20 usw. kann in FHEM nicht ohne Weiteres gerechnet werden, da es sich um Zeichenketten handelt und nicht um Zahlen.
Verfahren zum Rechnen mit Zeitangaben, die als Zeichenkette vorliegen
Die Berechnung erfolgt in Perl. Das Verfahren besteht aus drei Schritten:
- Umwandeln der Zeichenketten in eine Zahl, z.B. Sekunden.
- Berechen einer Zeit als Zahl.
- Umwandeln der Zahl in eine Zeichenkette (Formatierung)
Umwandeln eine Zeichenkette in eine Zahl
- Die von
timelocal
erwartete Monatsangabe sind Ganzzahlwerte von 0 bis 11 für Januar bis Dezember.
Hier hängt das Verfahren von der Struktur der Zeichenkette ab.
Perl und FHEM stellen Funktionen zur Umwandlung bereit.
time
liefert die aktuelle Zeit in Sekunden [1]time_str2num("YYYY-MM-DD HH:MM:SS")
wandelt einen FHEM-Zeitstempel in Sekunden um [2]timelocal(<Sekunden>, <Minuten>, <Stunden>, <Tag des Monats>, <Monat>, <Jahr>)
wandelt einen Satz von Zeitelementen (Sekunden, Minuten, Stunden usw.) in Sekunden um [3]Sekunden + Minuten * 60 + Stunden * 60 * 60 + Tage * 24 * 60 * 60
berechnen eines Summanden oder Subtrahenden aus Sekunden, Minuten, Stunden und Tagen.
Beispiel: Zeitstempel eines Readings in Sekunden umwandeln
time_str2num(ReadingsTimestamp(<devicename>, <reading>,<defaultvalue>))
Konstanten innerhalb FHEM
FHEM stellt einige Konstanten[4] bereit, um das Rechnen mit Zeiten zu erleichtern, DAYSECONDS, HOURSECONDS, und MINUTESECONDS. Obiger Code kann also auch so geschrieben werden:
Sekunden + Minuten * MINUTESECONDS + Stunden * HOURSECONDS + Tage * DAYSECONDS
Umwandeln einer Zahl in eine Zeichenkette
- Die von
localtime
zurückgegebene Monatsangabe liegt im Bereich der Ganzzahlwerte 0 bis 11 für Januar bis Dezember. - Werden keine Parameter angegeben, bezieht sich die Ausgabe auf den aktuellen Zeitpunkt.
Zur Umwandlung seien die folgenden Perl-Funktionen genannt:
"HH:MM, DD.MM.YY" =~ /(\d\d).(\d\d)..(\d\d).(\d\d).(\d\d)/
extrahiert HH,MM,DD,MM und YY aus der Zeichenkette HH:MM, DD.MM.YY, die ein Datum in der angegebenen Form enthält. \d steht für eine Ziffer, der Punkt für ein beliebiges Zeichen, die () schreiben den Treffer in spezielle Variablen in der Reihenfolge ihrer Anordnung HH in $1, MM in $2, DD in $3 usw.(Sekunden, Minuten, Stunden, Tag des Monats, Monat, Jahr, Nummer des Wochentages, Tag des Jahres, Sommerzeitkennzeichen) = localtime(Zeit in Sekunden)
gibt die einzelnen Zeitelemente zurück [5]POSIX::strftime(<Format>,<Array mit Zeitelementen>)
, wandelt ein Array aus Zeitelementen, wie eslocaltime
liefert in eine formatierte Zeichenkette um. <Format> wird mit Hilfe bestimmter Formatierungszeichen (%a für den Wochentagnamen, %d für den Tag des Monats usw. [6]) festgelegt.
Beispiel: Wochentag zu Datum
Zum heutigen Datum
{return strftime("%A",localtime)}
Zu einem vorgegebenen Datum
{
my ($d,$m,$y) = split(/\./,"06.09.2021");
$m-=1;
return strftime("%A",localtime(timelocal('0','0','0',$d,$m,$y)));
}
Berechnungsbeispiele
Allen Berechnungen zu Grunde liegt die Vorgehensweise in absoluten Sekunden bezogen auf einen Referenzzeitpunkt zu rechnen. Damit umgeht man jeden Wechsel Stunden/Tage/Monate/Jahre.
Die einzeiligen Beispiele sollten im Eingabefeld von FHEMWEB ausführbar sein.
Addition zu einem Zeitstempel
Gegeben sei ein Reading motion des Gerätes BM1 mit einem Zeitstempel 2017-08-11 14:17:13. Es sollen 2 Stunden und 12 Minuten addiert werden und das Ergebnis als HH:MM dargestellt werden.
{POSIX::strftime("%H:%M",localtime(time_str2num(ReadingsTimestamp("BM1","motion","2000-01-01 00:00:00"))+2*60*60+12*60))}
Schrittweise:
{
my $timestamp = ReadingsTimestamp("BM1","motion","2000-01-01 00:00:00");
my $seconds = time_str2num($timestamp)+2*60*60+12*60;
my $result = POSIX::strftime("%H:%M",localtime($seconds));
return $result;
}
Addition zum aktuellen Zeitpunkt
Zur aktuellen Zeit sollen 30 Minuten addiert und das Ergebnis als HH:MM:SS dargestellt werden.
{POSIX::strftime("%H:%M:%S",localtime(time+30*60))}
Subtraktion vom aktuellen Zeitpunkt
Zur aktuellen Zeit sollen 45 Minuten subtrahiert und das Ergebnis als HH:MM:SS dargestellt werden.
{POSIX::strftime("%H:%M:%S",localtime(time-45*60))}
Kalendertage von heute bis zu einem Datum
Zu einem bestimmten Kalendertag soll die Differenz in ganzen Tagen bestimmt werden.
{(time_str2num('2021-04-30') - time_str2num(strftime '%F',localtime))/86400}
Das Zieldatum kann z.B. ein Termin aus dem Kalender sein:
fhem('get AbfallKalender events timeFormat:"%F" format:custom="$T1" limit:from=0,count=1')