FHEM Forum

FHEM - Hausautomations-Systeme => Unterstützende Dienste => Thema gestartet von: nccfast am 28 Juni 2015, 13:07:56

Titel: fhem und Datum älter als 1970
Beitrag von: nccfast am 28 Juni 2015, 13:07:56
Hallo,
ich habe einen Geburtstagskalender eingebunden. Darin sind auch Personen , die vor 1970 geboren sind. Ein solcher Geburtstag ist eine jährlich wiederkehrender  Eintrag im Kalender. Das Modul 57_Calendar.pm berechnet daraus die nächste Startzeit (also den Geburtstag im Jahr 2015, wenn er dieses Jahr noch nicht war oder halt für 2016, wenn er bereits stattfand). Dabei verwendet die Funktion sub tm die fhem Funktion fhemTimeLocal aus der fhem.pl. Diese wiederum ruft dann  fhemTimeGm auf.
Es sollen die Skunden (epoch) seit Thu Jan  1 01:00:00 1970 berechnet werden. Und dazu notwendig ist auch die Berechnung, wieviel Schaltjahre es bis zu dem gegebene Datum gibt.
Implementiert ist:

  my $leapyears= int(($year-1969)/4) - int(($year-1901)/100) + int(($year-1601)/400);

Diese Formel liefert aber eine falsche Anzahl von Schaltjahren für Daten, die vor 1970 sind.

ich hab mal folgendes mit Erfolg ausprobiert:

   
    my $leapyears_date = ( int(($year-1)/4) - int(($year-1)/100) + int(($year-1)/400) ); # Schaltjahre seit 01.01.01 00:00:00 bis $year
    my $leapyears_1970 =  ( int((1970-1)/4) - int((1970-1)/100) + int((1970-1)/400) );  # Schaltjahre seit 01.01.01 00:00:00 bis 1970
    my $leapyears = $leapyears_date - $leapyears_1970; # Schaltjahre seit 1970 (positiv, wenn größer 1970 - negativ, wenn kleiner 1970)


Habs mal tabellarisch dargestellt. Die alte Formel verrechnet sich um 1 Schaltjahr.


Jahr   Anzahl Schaltjahre
     
      alte       neue
     Formel     Formel
1946 -5         -6
1947 -5         -6
1948 -5         -6
1949 -5         -5
1950 -4         -5
1951 -4         -5
1952 -4         -5
1953 -4         -4
1954 -3         -4
1955 -3         -4
1956 -3         -4
1957 -3         -3
1958 -2         -3
1959 -2         -3
1960 -2         -3
1961 -2         -2
1962 -1         -2
1963 -1         -2
1964 -1         -2
1965 -1         -1
1966 0          -1
1967 0          -1
1968 0          -1
1969 0          0
1970 0          0
1971 0          0
1972 0          0
1973 1          1
1974 1          1
1975 1          1
1976 1          1
1977 2          2
1978 2          2
1979 2          2
1980 2          2


Das Kalendermodul macht z.B. while($self->{end} < $t and $self->advanceToNextOccurance()) { ; }. Darin wir auch tm() verwendet, und zwar viele male.
Daraus folgen ergebliche Abweichungen vom richtigen geburtstag.

Könnte diese Korrektur der Schlatjahre in die offizielle fhem.pl aufgenommen werden?

Titel: Antw:fhem und Datum älter als 1970
Beitrag von: Dr. Boris Neubert am 28 Juni 2015, 13:59:53
Hallo,

genau das Problem (Schaltjahre i.V.m. wiederkehrenden Terminen, deren Serie vor 1970 beginnt) hatten wir schon mal erörtert.

http://forum.fhem.de/index.php/topic,25881.msg196767.html#msg196767 (http://forum.fhem.de/index.php/topic,25881.msg196767.html#msg196767)

Mangels Interesse der damals Beteiligten verlief die Lösung im Sande. Daher Danke für Deine Initiative und den Patch. Das aktuelle Problem kommt vom int ().

Eine effiziente Version sollte m.E. aufgenommen werden.

Grüße
Boris
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: smurfix am 28 Juni 2015, 14:31:00
ZitatDas aktuelle Problem kommt vom int
Genauer gesagt: du willst immer nach unten runden, nicht zur Null hin. Folglich:
if (x<0) x=-int(-x); else x=int(x)
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: rudolfkoenig am 28 Juni 2015, 17:06:03
Habs eingecheckt.


Per Definition liefert die Funktion fhemTimeGm die Anzahl der Sekunden seit 1970 fuer einen gegebene Dateum/Uhrzeit. zurueck. Ich verstehe noch nicht, warum man diese Funktion mit einem Jahr < 1970 aufrufen will.
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: nccfast am 28 Juni 2015, 18:11:58
Das mit den  leapyears ist aber nicht geändert in fhem.pl. Habs eben upgedatet.
Warum man diese Funktion mit einem Jahr < 1970 aufrufen will? Da mnusst du den ersten Beitrag lesen. (Stichworte Geburtstagskalender, Personen die vor 1970 geboren sind)


Nochmal zum Code:

my $leapyears_1970 =  ( int((1970-1)/4) - int((1970-1)/100) + int((1970-1)/400) );
$leapyears_1970 wäre eine Konstante, nämlich 477, und müsste nicht jedesmal berechnet werden.

Man hätte also nur noch:

my $leapyears = ( int(($year-1)/4) - int(($year-1)/100) + int(($year-1)/400) ) - 477;


smurfix's weg wäre:

  my $leapyears= floor(($year-1969)/4) - floor(($year-1901)/100) + floor(($year-1601)/400); 


Gibts eine floor Funktion in perl?

floor ist aber evtl. aufwendiger als int und minus, meine ich.
Was meinen die perl experten?
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: rudolfkoenig am 28 Juni 2015, 18:58:07
ZitatWas meinen die perl experten?

Das Dateien fuer update nur einmal am Tag, kurz vor 8 bereitgestellt werden.
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: nccfast am 28 Juni 2015, 19:17:07
@rudolfkoenig

Eigentlich meinte ich, was die Experten zu floor für eine meinung haben. Und welche methode man nun implementiert.

Aber ich denke du weisst das und möchtest nur ein wenig lustig sein. Und dich vielleicht drüber sarkastisch lustig machen, dass ich nicht wusste, dass Dateien fuer update nur einmal am Tag, kurz vor 8 (in der Früh?) bereitgestellt werden.

Schade.
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: Dr. Boris Neubert am 28 Juni 2015, 19:45:22
Zitat von: rudolfkoenig am 28 Juni 2015, 17:06:03
Habs eingecheckt.

$leapyears_1970 ist 477 (wenn ich mich nicht verrechnet habe). Ich hoffe, dass der Compiler so schlau ist, dass zu verstehen.

Bist Du sicher, dass das auch unter MacOS funktioniert? M.E. muss man die Anzahl der Schaltjahre seit dem Jahr 0 bis zur Epoche abziehen: 1970 bei Unix und 1904 bei MacOS.

Grüße
Boris
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: rudolfkoenig am 28 Juni 2015, 19:53:55
Eigentlich wollte ich wissen, wieso man die Sekunden fuer < 1970 braucht, Antwort habe ich darauf aber keins bekommen (natuerlich habe ich vorher alles gelesen), und ich dachte, aneinander vorbeireden ist in dieser Diskussion gewollt.

@Boris: $^O eq "MacOS" ist Geschichte, ich glaube nicht, dass jemand FHEM damit verwendet, und wenn, dann ist das mir auch egal. Unter OSX kommt:
perl -e 'print $^O'
darwin
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: Dr. Boris Neubert am 28 Juni 2015, 20:12:11
Zitat von: rudolfkoenig am 28 Juni 2015, 19:53:55
Eigentlich wollte ich wissen, wieso man die Sekunden fuer < 1970 braucht, Antwort habe ich darauf aber keins bekommen (natuerlich habe ich vorher alles gelesen), und ich dachte, aneinander vorbeireden ist in dieser Diskussion gewollt.

Mein Calendar-Modul berechnet den nächsten Termin in einer Terminserie, indem vom Starttermin aus das Intervall solange draufgerechnet wird, bis zum ersten Mal bei einem Termin in der Zukunft angekommen wird. Ich habe einen kurzen Blick in den Code geworfen und sehe gerade nicht, wie die Schaltjahresproblematik da rein spielt. Aber sie besteht.

Jahre vor 1970 kommen dabei ins Spiel, wenn man Serientermine mit Starttermin vor 1970 einstellt. Bei Geburtstagen kann das der Fall sein. Das ist kein besonders cleverer Use Case, wie ich schon in dem weiter oben von mir referenzierten Posting angemerkt hatte. Aber wenn sich die Problematik so leicht lösen lässt, finde ich es gut, dass wir sie implementiert haben.

Zitat
@Boris: $^O eq "MacOS" ist Geschichte, ich glaube nicht, dass jemand FHEM damit verwendet, und wenn, dann ist das mir auch egal. Unter OSX kommt:
perl -e 'print $^O'
darwin


Wie fremd mir doch die Mac-Welt ist...

Viele Grüße
Boris
Titel: Antw:fhem und Datum älter als 1970
Beitrag von: rudolfkoenig am 28 Juni 2015, 20:58:22
OSX ist ein BSD Derivat, mit ein paar grafischen Bibliotheken und Programmen oben drauf, Nachfolger von NeXTStep. Das was vor OS X da war (MacOS <= 9, aka $^O eq "MacOS") kenne ich auch nicht, es ist aber auch seit 15 Jahren irrelevant.