[GELÖST] FHEM: falsch, Perl-Online-Editor: richtig - Warum?

Begonnen von DocCyber, 25 März 2024, 19:08:58

Vorheriges Thema - Nächstes Thema

DocCyber

Hallo zusammen,

ich würde gern des letzten Tag eines Monats ermitteln, habe hierfür ein Stück Code gefunden und leicht modifiziert.
FHEM liefert mir für März ein falsches Ergebnis, nämlich den 30. als letzten Tag.
Der identische Code in Perl-Online-Editor liefert aber das korrekte Ergebnis (31.)
Kann mir jemand erklären, wieso das so ist? Offenbar habe ich etwas falsch gemacht, oder?

FHEM Kommandozeile:
{my $ult = ultimo(0);; return $ult;;}bzw.
{my $ult = ultimo(1);; return $ult;;}
sub ultimo($) {
  #use Time::Local;
  use POSIX qw(strftime);
  my $workday = shift;  # 0: Letzter Tag des Monats | 1: letzter Werktag des Monats
  my ($_year, $_month) = split(/\./, `date +%y.%m`);
  chomp($_year, $_month);
  # Letzter Tag des Monats:
  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];
  # Letzter Werktag des Monats:
  if ($workday) {
    my $_day = strftime "%a", localtime($_next_month - 86400);
    if ($_day eq 'Sat') { $_last_day--; }
    if ($_day eq 'Sun') { for (1..2) { $_last_day--; } }
  }

  return "$_last_day.$_month.$_year";
}
Behandle die Menschen so, als wären sie, was sie sein sollten. Dadurch hilfst du ihnen zu werden, was sie sein können. (Goethe)


RPi-3 mit HM-CFG-LAN und jede Menge HM Komponenten.

Christoph Morrison

Der letzte Tag ist doch der 31, also zieht dein Programm einen Tag ab und kommt beim 30. raus. Der Unterschied könnte aus den locales kommen, bei denen Sat und Sun vielleicht was anderes ist als Sat und Sun, z.B. Sa und So (german locale) - siehe auch CAVEAT %A, %a, %B, %b, and friends

Du machst dir das ingesamt aber sehr kompliziert.

Aus Time::Piece:
$t->month_last_day      # 28-31
Deinen Abzug für's Wochenende kannst du dann wie gehabt dran bauen, $t->wday ist dein Freund, besser als auf Strings zu prüfen.

btw: Bei einer Zeitumstellung haut das mit 86400 nicht mehr unbedingt hin.

Otto123

Hi,

keine Antwort auf Deine Frage, aber - es gibt die Funktion at_ultimo in FHEM die tut das was Du suchst. Beispiel:
{localtime(at_ultimo)}Mit strftime() kannst Du weiter formatieren.

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

yersinia

Zitat von: Christoph Morrison am 25 März 2024, 22:00:08Du machst dir das ingesamt aber sehr kompliziert.

Aus Time::Piece:
$t->month_last_day      # 28-31
Auch DateTime kann Anzahl der Tage des Monats (indirekt dadurch auch den Letzten)
$dt->month_lengthund prüfen ob ein Datum der letzte Tag des Monats ist:
$dt->is_last_day_of_month :)
viele Grüße, yersinia
----
FHEM 6.3 (SVN) on RPi 4B with RasPi OS Bullseye (perl 5.32.1) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl

betateilchen

Wie wäre es eigentlich mit einem sinnvollen Threadtitel?


-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

DocCyber

#5
Zitat von: Christoph Morrison am 25 März 2024, 22:00:08Du machst dir das ingesamt aber sehr kompliziert.
Nur weil $t->month_last_day einen einfachen Auruf darstellt, ist es nicht weniger kompliziert, denn schließlich steht Time::Piece dahinter.

Aber darum soll es hier nicht gehen.
Zitat von: Christoph Morrison am 25 März 2024, 22:00:08Der letzte Tag ist doch der 31, also zieht dein Programm einen Tag ab und kommt beim 30. raus
Wie gesagt: Das selbe Programm arbeitet korrekt, wenn ich den Code im Perl-Online-Editor laufen lasse.
Ich würde gern wissen, warum der letzte Tag in Fhem mit diesem Code nicht korrekt berechnet  wird.
Behandle die Menschen so, als wären sie, was sie sein sollten. Dadurch hilfst du ihnen zu werden, was sie sein können. (Goethe)


RPi-3 mit HM-CFG-LAN und jede Menge HM Komponenten.

DocCyber

Zitat von: betateilchen am 26 März 2024, 08:54:44Wie wäre es eigentlich mit einem sinnvollen Threadtitel?
Ich finde, der Titel trifft das Problem auf den Punkt.
Hättest du bei einem anderen Titel (Vorschlag?) denn eine Lösung für die Fragestellung?
Behandle die Menschen so, als wären sie, was sie sein sollten. Dadurch hilfst du ihnen zu werden, was sie sein können. (Goethe)


RPi-3 mit HM-CFG-LAN und jede Menge HM Komponenten.

betateilchen

#7
Zitat von: DocCyber am 26 März 2024, 10:18:59Ich finde, der Titel trifft das Problem auf den Punkt.

Ich finde, der Titel ist eine Katastrophe,

ZitatFHEM: falsch, Perl-Online-Editor: richtig - Warum?

weil er keinerlei Hinweis darauf gibt, um welches Thema es eigentlich geht: Du willst den letzten Tag eines Monats ermitteln und bist dabei auf ein Problem gestoßen.

Zitat von: DocCyber am 26 März 2024, 10:18:59Hättest du bei einem anderen Titel (Vorschlag?) denn eine Lösung für die Fragestellung?

Die einzig sinnvolle Lösung hat doch Otto schon gegeben, warum soll ich die wiederholen?
Benutze die Funktion, die FHEM von Haus aus mitbringt, um ultimo zu berechnen, denn genau dafür wurde diese Funktion ja eingebaut.
Und ob der Tag ein Werktag oder ein Sonn-/Feiertag ist, bekommst Du dann per holiday-Abfrage (ebenfalls FHEM Standard) heraus.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: DocCyber am 26 März 2024, 10:16:20Wie gesagt: Das selbe Programm arbeitet korrekt, wenn ich den Code im Perl-Online-Editor laufen lasse.
Ich würde gern wissen, warum der letzte Tag in Fhem mit diesem Code nicht korrekt berechnet  wird.

Weil Dein FHEM vermutlich nicht mit der locale C.UTF-8 läuft, im Gegensatz zum Online Editor. Und in Deutschland ist am 31.03.24 Zeitumstellung, was eine manuelle Berechnung zusätzlich kompliziert macht. Aber auch darauf wurdest Du ja schon hingewiesen.

Zitat von: Christoph Morrison am 25 März 2024, 22:00:08btw: Bei einer Zeitumstellung haut das mit 86400 nicht mehr unbedingt hin.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Otto123

#9
Da Du nicht auf die Lösung des Problems sondern auf deine Frage beharrst (was ich ok finde, wir sind ja in der Perl für User Ecke):
Unter dem Aspekt und da ich auch immer gerne dazu lerne, habe ich mal etwas rumprobiert.
Ich finde den Code zu heterogen :)
Was macht ein online Editor mit dieser Zeile (Systemkommando oder sehe ich das falsch?)?
  my ($_year, $_month) = split(/\./, `date +%y.%m`);warum nicht Perl?
my ($_year, $_month) = split(/\./, strftime("%y.%m",localtime(time)) );Du ziehst mit einem ganzen Tag am Tag der Zeitumstellung einfach zuviel ab!? (Aber ob das so simple ist glaube ich nicht.)
Dein Code rechnet nur im März falsch.

Kann man mit der Zeile in FHEM "erspielen"
{strftime ("%d.%m.%Y",localtime (timelocal(0, 0, 0, 1, 3, 24) - 1) )}
Der Online Editor steht eventuell in Indien? Zumindest der den ich gefunden habe. -> IST
Dort gibt es keine Sommerzeit
use POSIX;
print strftime("%Z", localtime()), "\n";

Edit ok - jetzt gesehen: Deiner macht UTC - auch ohne Sommerzeit ;)

Im übrigen arbeitet Dein Code korrekt wenn Du nicht die lokale Zeit nimmst sondern auf UTC gehst:
timelocal -> timegm
localtime -> gmtime

{strftime ("%d.%m.%Y", gmtime (timegm(0, 0, 0, 1, 3, 24) - 86400) )}
Ob das die richtige Lösung deiner Fragestellung ist weiß ich allerdings nicht.

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

DocCyber

Zitat von: betateilchen am 26 März 2024, 11:10:01Die einzig sinnvolle Lösung hat doch Otto schon gegeben, warum soll ich die wiederholen?
Weil es hier primär um die Antwort meiner konkreten Fragestellung geht, und nicht um eine (andere) Lösung - sei sie auch noch so gut.

Wenn Probleme solcher Art auftreten, versuche ich, den Grund dafür zu verstehen. Dabei gibt es einen Lerneffekt.
Eine andere Lösung ist an sich ja toll, weicht aber dem genannten Problem aus.
Behandle die Menschen so, als wären sie, was sie sein sollten. Dadurch hilfst du ihnen zu werden, was sie sein können. (Goethe)


RPi-3 mit HM-CFG-LAN und jede Menge HM Komponenten.

DocCyber

Zitat von: betateilchen am 26 März 2024, 11:19:20Weil Dein FHEM vermutlich nicht mit der locale C.UTF-8 läuft, im Gegensatz zum Online Editor

Das könnte eine echte Antwort auf meine Frage sein - danke  :)
Behandle die Menschen so, als wären sie, was sie sein sollten. Dadurch hilfst du ihnen zu werden, was sie sein können. (Goethe)


RPi-3 mit HM-CFG-LAN und jede Menge HM Komponenten.

Christoph Morrison

Zitat von: yersinia am 26 März 2024, 07:30:13Auch DateTime

Der Nachteil an DateTime ist, dass es kein Core-Module ist und ggf. erst installiert werden muss - wäre sonst auch mein Vorschlag gewesen. Time::Piece dagegen ist eines.

Christoph Morrison

Zitat von: DocCyber am 26 März 2024, 10:16:20Nur weil $t->month_last_day einen einfachen Auruf darstellt, ist es nicht weniger kompliziert, denn schließlich steht Time::Piece dahinter.

Doch, weil Time::Piece eh installiert ist und garantiert von besserer Codequalität als dein Versuch (shell exec für's Datum?!). Wäre deine Codequalität so gut, hättest du a) gewusst, warum %a und ein Stringvergleich nicht unproblematisch sind und b) hättest gleich Time::Piece oder ein anderes Modul gewählt. NIH-Syndrom und so.

ZitatWie gesagt: Das selbe Programm arbeitet korrekt, wenn ich den Code im Perl-Online-Editor laufen lasse.
Ich würde gern wissen, warum der letzte Tag in Fhem mit diesem Code nicht korrekt berechnet  wird.

Darauf hatte ich dir auch eine Antwort gegeben. Du hast sie nur nicht verstanden oder gar nicht erst gelesen. Ansonsten raten wir alle nur, weil wir auch nicht wissen, welche Locale dein FHEM nutzt.

btw: Dein Threadtitel, und da muss ich betateilchen zustimmen, ist keine gute Wahl. Vor allem: Du gehst davon aus, dass wir "Perl Online Editor" kennen, als ob das irgendeine offizielle oder wenigstens quasi offizielle Sache wäre. Um mal hier den Habeck zu machen: FHEM macht nichts falsch, es liefert nur nicht, was du erwartest (und ich bin nicht unbedingt als Nicht-Kritiker von FHEM bekannt ...).

Otto123

#14
ich meine, die locale ist hier nicht die Ursache.
{setlocale(LC_CTYPE, "C.UTF-8");; ultimo(0)}Liefert das gleiche Ergebnis.
Der vom TE erwähnte Perl Online Editor (er hat ihn ja nachträglich verlinkt) arbeitet mit "C.UTF-8"
Liege ich mit meiner Erklärung bzw. mit dem Beleg, dass die Vermutung von Christoph bez. Zeit Umstellung die richtige ist, so falsch?
Ich meine, die Rechnerei für die hier gestellte Aufgabe kann man besser mit UTC bzw. GMT durchführen. Es geht ja um den letzten Tag und nicht die letzte Sekunde des Monats?

at_ultimo liefert übrigens die letzte Minute des Monats, egal ob "C.UTF-8" oder "de_DE.UTF-8" ;)
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