Hallo Leute,
um ein at immer am Letzten eines Monats ausführen zu lassen gibt es ja die Funktion at_ultimo(). Schön wäre vielleicht eine weitere Funktion, damit ein at immer am (z.B) ersten Dienstag im Monat ausgeführt wird. Häufig werden ja Treffen immer am ersten und dritten Dienstag eines Monats zu einer festen Uhrzeit durchgeführt (kann natürlich auch jeder andere Wochentag sein ;) ). Man müsste also den Wochentag (1-7), 1-4 für ersten bis vierten Tag und die Uhrzeit übergeben. Eine Formel für Excel sieht so aus:
=A2-1-WOCHENTAG(A2-WT;3)+7*X
wobei A2 für das Datum des ersten Tags des aktuellen Monats, WT für den Wochentag (Montag=1) und X für den ersten bis vierten Tag steht.
Ich hatte mir Funktion at_ultimo() angesehen, habe aber mehr Fragen als Antworten :) . Sicher kann jemand mit mehr Ahnung das recht schnell umsetzen. Könnte ja für mehrere Anwender interessant sein.
Gruß
Frank
Hallo Frank,
es gibt in Fhem etwas für alles: https://forum.fhem.de/index.php?msg=542490
Grüße Jörg
Eine aehnliche Funktionalitaet ist im holiday Modul implementiert: https://fhem.de/commandref_modular.html#holiday
Kurz: man definiert eine .holiday Datei in /opt/fhem/FHEM (Beispiele siehe /opt/fhem/FHEM/holiday/*), man legt eine holiday Inastanz an mit passenden Namen (nicht ganz intuitiv, ist aber so), und wertet die yesterday/today/tomorrow Readings dieser Instanz in einem at aus.
Hallo Jörg,
ich wäre nie auf die Idee gekommen, nach "Alarmclock" zu suchen :) . Werde ich mal probieren. Danke!
Man könnte das wahrscheinlich auch über die cron-library machen, die es inzwischen in FHEM gibt.
Müsste man vermutlich in die 99_myUtils.pm bauen.
Oder irgendjemand erbarmt sich irgendwann, das at-Modul so zu erweitern, dass es auch Zeitangaben im Format eines crontab-Eintrags verarbeitet.
(oder baut - noch besser - gleich ein neues Modul 91_cron.pm als Alternative zu at)
Für den "ersten" bestimmten Wochentag eines Monats würde man das so bauen:
10 3 1-7 * *
und müsste dann im Ausführungsteil einfach nur noch prüfen, ob der gewünschte $wday für z.B. Mittwoch erreicht ist.
Zitat von: betateilchen am 16 Februar 2024, 15:08:21Man könnte das wahrscheinlich auch über die cron-library machen, die es inzwischen in FHEM gibt.
Die cronlib kann das sogar eleganter weil sie einen erweiterten syntax implementiert. Die lib wird aktuell von JsonMod und (soweit ich weiß) einem Modul von JoWiemann verwendet. Ein 90_cron-pm habe ich geplant, falls jemand dort einspringen will: sehr gerne und ich unterstütze.
Anlaufstelle zum Einlesen des erweiterten syntax sind die Tests: https://svn.fhem.de/fhem/trunk/fhem/t/FHEM/90_Cron/10_Cronlib.t
Der erste Dienstag eines Monats kann so:
0 0 * * 2#F
0 0 * * 2#1
0 0 * * Tue#F
0 0 * * Tue#1
Letzter:
0 0 * * 2#L
0 0 * * 2#-1
oder
0 0 * * Tue#L
0 0 * * Tue#-1
Vorletzter:
0 0 * * 2#-2
btw: Freitag der 13:
0 0 13 * &5
usw...
Hallo Leute,
Alarmclock hat leider nicht (immer) funktioniert. Deshalb habe ich mich doch daran gesetzt, diese Funktion umzusetzen. Hier mein Ergebnis:
########################################
#
# Berechnung des Datums des
# x.ten Wochentags im Monat
#
# x=1-4 x.ter Wochentag im Monat
# x=9 letzter Wochentag im Monat
# w=1-7 Wochentag, 1=Montag
# h,m,s Uhrzeit Stunde, Minute, Sekunde
#
sub at_xwday($$$$$) {
my ($x,$w,$h,$m,$s) = @_;
my $ziel_tag = 0;
# akt. Datum und Uhrzeit in Variablen aufteilen
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
# bei Neuberechnung einen Monat addieren
my $add = $data{AT_RECOMPUTE} ? 1 : 0;
$mon = $mon + $add;
my ($nm, $ny) = ($mon == 12) ? (0,$year+1) : ($mon,$year);
# Letztes Vorkommen des Wochentags berechnen?
if ($x == 9) {
# Berechnen des letzten Tags des Monats
# ersten Tag des Folgemonats als timestamp
my ($xm, $xy) = ($mon == 11) ? (0,$year+1) : ($mon+1,$year);
my $nt = mktime(0, 0, 0, 1, $xm, $xy);
# letzter Tag des aktuellen Monats = erster Tag des Folgemonats minus ein Tag
my ($letzter_tag_des_monats, $letzter_wochentag) = (localtime($nt - DAYSECONDS))[3,6];
# Prüfen, ob der letzte Wochentag im Monat mit dem gewünschten Wochentag übereinstimmt
$ziel_tag = $letzter_tag_des_monats;
if ($letzter_wochentag > $w) {
# Falls der letzte Wochentag später im Monat ist, subtrahiere die Differenz
my $differenz = $letzter_wochentag - $w;
$ziel_tag -= $differenz;
} elsif ($letzter_wochentag < $w) {
# Falls der letzte Wochentag früher im Monat ist, subtrahiere 7 plus die Differenz
my $differenz = $w - $letzter_wochentag;
$ziel_tag -= (7 - $differenz);
}
} else {
# Berechne den Tag des ersten Vorkommens des Wochentags im Monat
my $erster_tag = 1;
my $erster_tag_des_monats = (localtime(mktime(0,0,0,$erster_tag,$nm,$ny)))[6];
my $erstes_vorkommen = ($w - $erster_tag_des_monats + 7) % 7 + 1;
# Berechne den Tag des x.ten Vorkommens des Wochentags im Monat
$ziel_tag = $erstes_vorkommen + 7 * ($x - 1);
# Überprüfe, ob das Datum im gültigen Bereich liegt
if ($ziel_tag > 31 || $ziel_tag < 1) {
return "Ungültiges Datum";
}
}
return mktime($s,$m,$h,$ziel_tag,$nm,$ny);
}
Die ersten Tests liefen erfolgreich. "Letzter Wochentag" stimmt in diesem Monat. Am 28. kann ich berichten, ob die Neuberechnung ebenfalls funktioniert. ;D Ihr könnt ja mal drüber schauen, ob es noch etwas zu optimieren gibt und die Funktion bei Bedarf gerne in das at-Modul einfügen.
"Letzter Wochentag im Monat" wurde für April auch korrekt berechnet. Sollte also funktionieren :)
Hallo F_Klee, entschuldige die (einfache) Frage, ich bin recht neu in dem Thema unterwegs. Wie nutze ich jetzt diese Funktion, wie definiere ich konkret ein AT? Deinen Code habe ich erfolgreich in meiner 99_myUtils.pm gespeichert. Ich möchte ein wiederholendes AT an jedem ersten Wochentag im Monat um 7:00 Uhr haben. Kannst du mir bitte dafür eine Beispieldefinition nennen? Danke und viele Grüße, Lutz
Hallo Lutz,
kein Grund sich zu entschuldigen. Ich bin alles andere als ein Experte und schreibe auch gerne Anleitungen, bei denen Experten gar nicht glauben können, dass man so etwas erklären muss. Ich habe das Ganze im Wiki veröffentlicht. (https://wiki.fhem.de/wiki/AT_kleine_Helferlein) Aufgrund deines Posts habe ich den Artikel um die Definitionen erweitert. Ich hoffe, du kommst klar.
Gruß
Frank
Hallo Frank, jetzt habe ich es verstanden mit den zu übergebenden Parametern. Mein Beispiel: ich lasse uns monatlich am ersten Montag im Monat um 6:40 Uhr eine Nachricht via Telegram- BOT schicken, dass das Kind einen neuen Fahrschein braucht. -->
*{at_xwday(1,1,6,40,0)} {\ fhem("set [Name des Telegram- BOT] message \@-[Token des Telegram- BOT] Achtung, neuer Monat, Fahrschein wechseln!")}
Aber kommenden Monat gilt der neue Fahrschein ab Donnerstag, 02.05., ist das mit dem ersten Werktag im Monat überhaupt machbar?
Der erste Wochentag und der erste Werktag im Monat sind ja etwas ganz anderes. Hier müsste der Algorithmus prüfen, ob der erste Tag im Monat ein Sonntag ist und muss dann einen Tag hinzu addieren. Schwierig sind dabei die Feiertage, speziell die beweglichen. Feiertage, die immer auf das selbe Datum fallen, könnte man ja in ein Array packen. Sind aber nicht sehr viele, die relevant sind.
Hallo Frank, stimmt, dann werde ich das erstmal mit at_ultimo zum letzten Tag des Monats gegen Abend machen, das ist ja auch offiziell der Ablauf des Tickets. Ich denke aber, dass ich deinen Code nochmal nutzen werde, der bleibt jedenfalls in meiner my_Utils drin, danke nochmals! Gruß, Lutz