Letzten Werktag im Monat für at ermitteln

Begonnen von KraxelHuber, 13 Januar 2019, 22:01:32

Vorheriges Thema - Nächstes Thema

KraxelHuber

Ich würde mir gerne immer am letzten Werktag im Monat zu einer bestimmten Uhrzeit (z.B. 09.00h) über ein at-Device eine Telegram Message zusenden lassen. Wie spezifiziere ich den "letzten Werktag im Monat"?

KernSani

RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

KraxelHuber

Zitat von: KernSani am 13 Januar 2019, 22:15:59
Google fragen:
https://www.perlmonks.org/bare/?node_id=198986

OK, habe die Funktion in meine 99_myUtils.pm integriert und sie lässt sich als Perl Befehl in FHEM aufrufen. Wenn ich das richtig sehe, ist das Resultat der Funkion jedoch ein String. Das at Device braucht doch sicherlich einen Datumswert, oder? Wie passt das nun zusammen und wie integriere ich die Funktion nun in das at-Device?

Hier ist noch mal die Funktion in leicht abgeänderter Form.

sub calcLastBusDay {
    use Time::Local;
    use POSIX qw(strftime);

    my ($_year, $_month) = split(/\./, `date +%Y.%m`);
    chomp($_year, $_month);

    # Calculate the last day of the month.
    my $_next_year = ($_month == 12) ? $_year + 1 : $_year;
    my $_next_month = timelocal(0, 0, 0, 1, $_month % 12, $_next_year);
    my $_last_day = (localtime($_next_month - 86400))[3];

    # Make sure it is a business day.
    my $_day = strftime "%a", localtime($_next_month - 86400);
    if ($_day eq 'Sat') { $_last_day--; }
    if ($_day eq 'Sun') { for (1..2) { $_last_day--; } }

    return "$_year-$_last_day-$_month";
}

Otto123

Laut Doku
Zitatdefine <name> at [<timespec>|<datespec>] <command>
...
<datespec> is either ISO8601 (YYYY-MM-DDTHH:MM:SS) or number of seconds since 1970.
Also ein String im richtigen Format wäre ok.

Da at die Funktion beim define und dann (wahrscheinlich) bei/nach jedem Lauf ausführt - Muss die Funktion immer den nächsten Termin liefern.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

KraxelHuber

Zitat von: Otto123 am 14 Januar 2019, 15:50:06
Laut DokuAlso ein String im richtigen Format wäre ok.

Da at die Funktion beim define und dann (wahrscheinlich) bei/nach jedem Lauf ausführt - Muss die Funktion immer den nächsten Termin liefern.

Gruß Otto

Wenn ich heute die {calcLastBusDay} in der FHEM Befehlszeile aufrufe, kommt als Ergebnis 2019-01-31 zurück. Das ist auch das korrekte Ergebnis, da dies der letzte Werktag im Monat ist. Mir ist jetzt leider noch nicht ganz klar, wie die Syntax in der Definition des at-Devices aussehen muss. Ich muss die Funktion ja mittels Perl Code aufrufen und anscheinend direkt auch die Uhrzeit anhängen, um auf das ISO8601 Format zu kommen. Ein konkreter Hinweis würde mir hier wahrscheinlich diese letzte Frage beantworten.

Danke ;-)

Otto123

#5
Ich habe es so auch nicht gemacht.  :D
Das Datum sieht doch schon mal gut aus.
Aber Du sagst: zu einer bestimmten Uhrzeit (z.B. 09.00h)

Also häng doch dort einfach noch die Zeit dran? -> 2019-01-31T09:00

und dann einfach per *{AufrufDerSub} in die at Definition.

Ganz unten sind Beispiele -> https://de.wikipedia.org/wiki/ISO_8601

Gruß Otto

Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Frank_Huber

define TEST at *{calcLastBusDay} 09:00 set bla on
liefert
the function "calcLastBusDay" must return a timespec and not 2019-31-01

KraxelHuber

Zitat von: Frank_Huber am 14 Januar 2019, 16:11:36
define TEST at *{calcLastBusDay} 09:00 set bla on
liefert
the function "calcLastBusDay" must return a timespec and not 2019-31-01

Genau das wollte ich gerade auch anmerken. Es macht auch keinen Unterschied, ob ich die Uhrzeit noch in der Funktion dran hänge. Sie liefert einen String und das kann anscheinend durch das at-Device nicht korrekt verarbeitet werden.

Hier meine geänderte Funktion:

sub calcLastBusDay {
    use Time::Local;
    use POSIX qw(strftime);

    my ($_year, $_month) = split(/\./, `date +%Y.%m`);
    chomp($_year, $_month);

    # Calculate the last day of the month.
    my $_next_year = ($_month == 12) ? $_year + 1 : $_year;
    my $_next_month = timelocal(0, 0, 0, 1, $_month % 12, $_next_year);
    my $_last_day = (localtime($_next_month - 86400))[3];

    # Make sure it is a business day.
    my $_day = strftime "%a", localtime($_next_month - 86400);
    if ($_day eq 'Sat') { $_last_day--; }
    if ($_day eq 'Sun') { for (1..2) { $_last_day--; } }

    return "$_year-$_last_day-$_month"."T09:00:00";
}


Ich bin in Perl wirklich nicht bewandert. Wie ist die Funktion also abzuändern, damit sie einen konformen Datumswert zurück liefert?

Frank_Huber

jahr-monat-tag muss es sein.

Du hast jetzt jahr-tag-monat

Frank_Huber


Frank_Huber

versuch mal
defmod TEST DOIF ($ymd ge "{calcLastBusDay}" and [09:00]) (set bla on)

."T09:00" aber wieder aus der myutils entfernen

KraxelHuber

Zitat von: Frank_Huber am 14 Januar 2019, 16:40:34
versuch mal
defmod TEST DOIF ($ymd ge "{calcLastBusDay}" and [09:00]) (set bla on)

."T09:00" aber wieder aus der myutils entfernen

OK, das DOIF lässt sich so auf jeden Fall erstellen. Wird hier denn jetzt jeden Tag um 09:00 Uhr geprüft, ob der aktuelle Tag >= Ergebnis aus calcLastBusDay ist? Was genau steht denn in $ymd drin? Ist das ein String oder ein Datumswert? Wie kann ich mir den Inhalt dieser Variable direkt anzeigen lassen?

Otto123

Was funktioniert (trial&error)
defmod a_test3 at 2019-01-31T09:00:00 {}

Die verschiedenen Fehler besagen u.a. das es nicht mit * und + geht

Also kann man es nur einmalig anlegen. Ginge dann auch in der Sub und man ruft diese einfach einmal im Monat auf.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Frank_Huber

Otto, mit der Sub geht wohl nicht.
Siehe den verlinkten Thread.

Kraxel,
$ymd ist nichts anderes als yyyy-mm-dd.
Also das was die sub ausspuckt.


Gesendet von meinem Doogee S60 mit Tapatalk


KraxelHuber

Zitat von: Frank_Huber am 14 Januar 2019, 21:17:31
$ymd ist nichts anderes als yyyy-mm-dd.

Ja, schon klar. Die Frage ist aber, ob es ein String oder wirklich ein Datumswert ist? D.h. funktioniert der Vergleich im DoIF wirklich, da die SUB ja einen String zurück liefert? Daher auch die Frage, wie ich mir den aktuellen Inhalt dieser Variable in FHEM unmittelbar anzeigen lassen kann.

Otto123

#15
Zitat von: Frank_Huber am 14 Januar 2019, 21:17:31
Otto, mit der Sub geht wohl nicht.
Ich lese das in der Doku so (und hab es auch getestet): für datespec kann man keine Perlfunction aufrufen, das geht nur für timespec.

Aber man kann ja den Datumsstring berechnen und dann sofort mit der Variablen das define an FHEM schicken.

So:

Einfach in der letzten Zeile der Sub das at definieren und dann einfach einmal im Monat die Sub aufrufen.
sub calcLastBusDay {
    use Time::Local;
    use POSIX qw(strftime);

    my ($_year, $_month) = split(/\./, `date +%Y.%m`);
    chomp($_year, $_month);

    # Calculate the last day of the month.
    my $_next_year = ($_month == 12) ? $_year + 1 : $_year;
    my $_next_month = timelocal(0, 0, 0, 1, $_month % 12, $_next_year);
    my $_last_day = (localtime($_next_month - 86400))[3];

    # Make sure it is a business day.
    my $_day = strftime "%a", localtime($_next_month - 86400);
    if ($_day eq 'Sat') { $_last_day--; }
    if ($_day eq 'Sun') { for (1..2) { $_last_day--; } };
    my $ddddd = "$_year-$_month-$_last_day"."T09:00:00";
    fhem("defmod a_test3 at $ddddd {}");
    # return $ddddd;
}


Getestet und funktioniert  8)

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Damian

Zitat von: KraxelHuber am 14 Januar 2019, 21:36:09
Ja, schon klar. Die Frage ist aber, ob es ein String oder wirklich ein Datumswert ist? D.h. funktioniert der Vergleich im DoIF wirklich, da die SUB ja einen String zurück liefert? Daher auch die Frage, wie ich mir den aktuellen Inhalt dieser Variable in FHEM unmittelbar anzeigen lassen kann.

wenn calcLastBusDay einen String liefert im Format yyyy-mm-dd, dann kann man den Vergleich wie folgt realisieren:


defmod TEST DOIF ($ymd eq calcLastBusDay() and [09:00]) (set bla on)


eq steht für Gleichheit von Strings.


Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

KraxelHuber

Zitat von: Damian am 14 Januar 2019, 21:43:00
wenn calcLastBusDay einen String liefert im Format yyyy-mm-dd, dann kann man den Vergleich wie folgt realisieren:


defmod TEST DOIF ($ymd eq calcLastBusDay() and [09:00]) (set bla on)


eq steht für Gleichheit von Strings.

Danke für die Aufklärung. Das sollte dann also funktionieren.  :D

KraxelHuber

Zitat von: Otto123 am 14 Januar 2019, 21:41:36
Einfach in der letzten Zeile der Sub das at definieren und dann einfach einmal im Monat die Sub aufrufen.

Gruß Otto

Otto, wenn ich einmal im Monat daran denke, die SUB auszuführen, dann brauche ich die SUB eigentlich erst gar nicht, weil sie ja dafür zuständig ist, mir einmal im Monat eine Erinnerung für eine andere Aufgabe zu schicken. D.h. wenn ich also daran denke, dann könnte ich die andere Aufgabe auch direkt erledigen. ;D

Ich brauche also eine Lösung, die ich nicht manuell anfassen muss. Das DoIF liefert anscheinend diese Lösung.

Trotzdem besten Dank für deine Hilfe!!

Frank_Huber

#19
Danke Damian, da war ich ja auf dem richtigen Weg.

Otto, sorry dann hatte ich es missverstanden.
Den define im sub sollte gehen, klar. [emoji6]
Mir persönlich würde aber die doif Varianten am besten gefallen.

Gesendet von meinem Telekom Puls mit Tapatalk

Otto123

#20
Zitat von: KraxelHuber am 14 Januar 2019, 21:54:49
Otto, wenn ich einmal im Monat daran denke, die SUB auszuführen, dann brauche ich die SUB eigentlich erst gar nicht, weil sie ja dafür zuständig ist, mir einmal im Monat eine Erinnerung für eine andere Aufgabe zu schicken. D.h. wenn ich also daran denke, dann könnte ich die andere Aufgabe auch direkt erledigen. ;D
Na dafür gibt es doch FHEM! Ich habe ja nicht gesagt du sollst es manuell machen.
Ich habe nicht konkret drüber nachgedacht, aber vielleicht gibt es doch eh schon eine Aufgabe bei Dir die zyklisch ausgeführt wird.

Das at an sich kann ja zum Schluss nochmal die SUB aufrufen, nachdem es die Nachricht an Dich geschickt hat.

Und nochmal der Hinweis: Die SUB in #2 und #7 ist falsch. Sie liefert das falsche Datumsformat!!!

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

KraxelHuber

Zitat von: Otto123 am 14 Januar 2019, 22:05:28

Und nochmal der Hinweis: Die SUB in #2 und #7 ist falsch. Sie liefert das falsche Datumsformat!!!


Danke für den Hinweis. Ich habe den Fehler korrigiert.