www.mikrocontroller.net

Forum: Compiler & IDEs Algorithnus für Sommerzeitberechnung gesucht


Autor: UBoot-Stocki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich suche den ganzen Tag schon nach einer Lösung für eine 
Sommerzeitumschaltung eines Weckers, den ich im Moment baue.

Es gibt hier im Forum zwei Codebeispiele, die das implementiert haben 
was ich suche. Allerdings verstehe ich die Code-Schnipsel nicht
Die Zeile: if( day - wday >= 25 && (wday || hour >= 2) ist m.E. nicht 
eindeutig. Es gibt doch mehrere Daten im März für die die Bedingung day 
- wday >= 25 zutrifft ???

Link: (Beitrag "Berechnung Datum + Uhrzeit + Sommerzeit")

Mein Problem:

Die Sommerzeitumschaltung findet am letzten Sonntag im März um 2 Uhr 
Morgens statt. Zurück wird am letzten Sonntag im Oktober gewschaltet.

Soweit die Aufgabenstellung...

Klar ist, dass ich über einen Algorithmus den Wochentag zu meinem 
(aktuell zu testenden) Datum berechnen muss. Diese Aufgabe ist für mich 
lösbar, wobei ich im Moment an einer Implementierung arbeite.

Was dann kommt ist mir nicht ganz klar: Vielleicht hat da mal jemand 
einen Tipp:

Es reicht ja nicht zu testen ob der aktuelle Tag im März ein Sonntag 
ist. Es könnte ja noch ein weiterer nachfolgen aleerdings will ich jetzt 
nicht absteigend vom 31.März an in einer Schleife testen ob der Tag ein 
Sonntag ist ...

Wer hat eine Idee wie es nach der Wochentagsberechnung weiter geht?

Ist irgendwio ein Algorithmus beschrieben ?

Gruß

Andreas

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir mal den JavascriptCode von der Seite an:

http://www.ez-calculators.com/daylight-saving-time...

insbesondere die Funktion whatdates.

Gruß
Roland

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es reicht ja nicht zu testen ob der aktuelle Tag im März ein Sonntag
> ist. Es könnte ja noch ein weiterer nachfolgen aleerdings will ich
> jetzt nicht absteigend vom 31.März an in einer Schleife testen ob
> der Tag ein Sonntag ist ...

Überleg doch mal:

  25.3. = Sonntag
  26.3. = Montag
  27.3. = Dienstag
  28.3. = Mittwoch
  29.3. = Donnerstag
  30.3. = Freitag
  31.3. = Samstag

Also: Ist es März und ist es ein Sonntag und ist es der 25. Tag oder 
später im Monat, dann ist das definitiv der letzte Sonntag im März.


Autor: Herr Mueller (herrmueller)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du den Wochentag vom 31.März berechnest ( 0= So....6= Sa), brauchst 
Du nur "31.März - Wochentag" rechnen, dann hast Du das Datum des 
vorherigen Sonntags.

gruss christian

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die obige Formel zeigt an, ob Sommerzeit ist oder nicht (der Oktober 
fehlt dann noch).

wday ist 0 für Sonntag

Der März hat in der Regel 31 Tage.

Die Umstellung kann also frühestens am 25. und spätestens am 31. 
stattfinden.

25 So 0
26 Mo 1
27 Di 2
28 Mi 3
29 Do 4
30 Fr 5
31 Sa 6


Wenn der 25. ein Sonntag ist, ist wday 0 und day - wday = 25. Für alle 
anderen Tage ist wday größer und deshalb muss auch day größer sein, 
damit der obige Algorithmus greift.

( wday || hour >= 2 ) ist dann war, wenn es entweder nicht Sonntag ist 
(also mit dem vorangegangenen Teil jeder Tag nach der Zeitumstellung) 
oder sonntags ab 2 Uhr.

Hier ist meiner Meinung nach noch ein Fehler zu suchen. Für jeden 
Sonntag nach der Zeitumstellung (kann natürlich nicht mehr im März 
liegen) ist leider erst ab 2 Uhr Sommerzeit nach diesem Algorithmus. Da 
aber sowieso noch der Teil mit März fehlt und wohl auch noch der 
Oktober-Teil (habe jetzt Deinen Link nicht angeschaut), muss da noch ein 
wenig gebastelt werden.

Ansonsten passt es soweit.

Normalerweise sollte tm_isdt des structs time_t gefüllt sein. Da wäre 
eigentlich alles drin. Das hängt aber leider von der Implementation ab.

Autor: UBoot-Stocki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Jetzt ist es klar - hätte eigentlich schon früher draufkommen können ...

ich prüfe also ob der aktuelle Tag ein Sonntag ist. Wenn das der Fall 
ist, prüfe ich dann ob das Datum (im März)  >= 25 ist. Wenn das der Fall 
ist, prüfe ich ob es schon 2 Uhr ist. wenn Ja, wird die Uhr vorgestellt

Gruß und Danke

Andreas

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein. Du prüfst direkt auf den letzten Sonntag ob der aktuelle Tag 
später >= dem letzen Sonntag ist. Das Ergebnis ist auch 'true' für z.B. 
den Montag danach.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Florian wrote:

> ( wday || hour >= 2 ) ist dann war, wenn es entweder nicht Sonntag ist
> (also mit dem vorangegangenen Teil jeder Tag nach der Zeitumstellung)
> oder sonntags ab 2 Uhr.
>
> Hier ist meiner Meinung nach noch ein Fehler zu suchen. Für jeden
> Sonntag nach der Zeitumstellung (kann natürlich nicht mehr im März
> liegen) ist leider erst ab 2 Uhr Sommerzeit nach diesem Algorithmus.


Und deshalb wird nur im März returned, wenn es vor 2.00 Uhr ist:
if( day - wday >= 25 && (wday || hour >= 2) ){ // after last Sunday 2:00
    if( month == 10 )        // October -> Winter
      return;
  }else{          // before last Sunday 2:00
    if( month == 3 )        // March -> Winter
      return;
  }


Peter

Autor: UBoot-Stocki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

jetzt bin ich verwirrt ...

"Nein. Du prüfst direkt auf den letzten Sonntag ob der aktuelle Tag
später >= dem letzen Sonntag ist. Das Ergebnis ist auch 'true' für z.B.
den Montag danach."

Ich bin jetzt mal der Mega8:

1.) eben war es 23:59:59. Ein paar Interrups später ist es 00:00:00 und 
damit beginnt ein neuer Tag.
2) Ich erhöhe meinen Tageszähler um eins. es ist jetzt der 25. März. Den 
Tag kenne ich nicht, da ich ihn nicht ausgerechnet habe.
3.) Da das Datum >= 25 ist, ermittle ich den aktuellen Wochentag. Nehmen 
wir an, es ist Dienstag. Dann brauche ich nichts weiter zu machen.

Viele Millarden Taktzyklen später ...

2) Ich erhöhe meinen Tageszähler um eins. es ist jetzt der 30. März. Den 
Tag kenne ich nicht, da ich ihn nicht ausgerechnet habe.
3.) Da das Datum >= 25 ist, ermittle ich den aktuellen Wochentag. Es ist 
Sonntag. Das Merke ich mir jetzt, da ich um 2 Uhr die 
Sommerzeitverstellung machen muss

Jetzt bin ich wieder Andreas:

Warum gefällt Euch diese Vorgehensweise nicht ???

Gruß

Andreas


Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie geht das mit der Vollmondberechnung? Muß ich da die Gaußsche 
Osterformel benutzen?

Autor: UBoot-Stocki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

frage mich gerade ob ich während des normalen Betriebs überhaupt eine 
Wochentag-Ermittlungs-Funktion benötige. Der Wochentag kann ja genauso 
wie das Datum etc. mitgezählt werden. Man würde dann den Wochentag über 
die Uhr/Datum-Funktion eingeben (Oder EINMALIG berechnet werden) und 
bräuchte keine Aufwändigen Mod- und Divisions-Funktionen ???

Im Sinne der Programmiereffizienz wäre das doch die beste Lösung ???

Gruß

Andreas

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich sag mal so:
Dein Wecker wird doch eine Änderung am GUI nur jede
Sekunde machen (wenn überhaupt).
Der µC hat dazwischen massig Zeit ein paar
"Aufwändigen Mod- und Divisions-Funktionen"
auszuführen.

'Programmiereffizienz' ist nicht alles. Es geht
auch darum, was du deinem Benutzer alles zumuten
willst.

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bezüglich Mond:
http://avila.star-shine.ch/astro/berechnungen.html

Oder Tabelle nehmen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UBoot-Stocki wrote:

> frage mich gerade ob ich während des normalen Betriebs überhaupt eine
> Wochentag-Ermittlungs-Funktion benötige. Der Wochentag kann ja genauso
> wie das Datum etc. mitgezählt werden. Man würde dann den Wochentag über
> die Uhr/Datum-Funktion eingeben (Oder EINMALIG berechnet werden) und
> bräuchte keine Aufwändigen Mod- und Divisions-Funktionen ???
>
> Im Sinne der Programmiereffizienz wäre das doch die beste Lösung ???

Die Berechnung ist überhaupt nicht aufwendig und ne Division braucht man 
auch nicht.
Warum also nicht dem Benutzer die Arbeit abnehmen.

Hier mal mein Code:
;------------------------------------------------------------------------   
;
.equ    FD = 0          ;offset weekday

;****************************** calculation weekday *********************
get_wday:
        mov     zl, month               ;Month (1..12)
        ldi     zh, 0
        subi    zl, low(-(2 * _cwd5 - 1))
        sbci    zh, high(-(2 * _cwd5 - 1))
        lpm                             ;get 1. day of month

        mov     a0, year
        cpi     month, 3                ;start calculation with march
        brcc    _cwd1
        dec     a0                      ;use last year for jan. & feb.
_cwd1:  mov     a1, a0
        lsr     a1
        lsr     a1
        add     a0, a1                  ;* 1.25
        add     a0, r0                  ;+ 1. day of month
        add     a0, day                 ;+ day
_cwd2:  subi    a0, 7
        brcc    _cwd2
        subi    a0, -7                  ;a0 = a0 % 7
        mov     weekday, a0             ;0 = So, 1 = Mo, ... , 6 = Sa
        ret
_cwd5:  .db     FD, FD+3, FD+2, FD+5, FD, FD+3, FD+5, FD+1, FD+4, FD+6, FD+2,
FD+4
;-----------------------------------------------------------------------


Peter

Autor: UBoot-Stocki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Will ja nicht "rumquengeln" aber ich könnte ja mit der mod/div-Funktion 
einmalig (z.B. im Eingabedialog) den Wochentag zum eingegebenen Datum 
berechnen lassen und dann weiterzählen.
Damit würde diese Funktion genau einmal aufgerufen. Ist doch einfacher 
und schneller... ?

Die Argumente, die Ihr bisher hattet waren:

Der µC hat dazwischen massig Zeit ein paar "Aufwändigen Mod- und 
Divisions-Funktionen" auszuführen. -> Macht vielleicht nichts aus aber 
wenns elleganter geht ?

'Programmiereffizienz' ist nicht alles. Es geht auch darum, was du 
deinem Benutzer alles zumuten willst. -> Es wäre ja kein Unterschied zur 
Lösung mit permanenten Funktionsaufrufen

@Peter: Was macht dieser Code? Was sind das für Werte auf die mit lpm 
zugegriffen wird? Hast Du zufällig eine Beschreibung des Algorithmus den 
Du da verwendest? Ich habe bisher nur Monsterformeln mit div und mod 
gefunden....

Gruß

andreas

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UBoot-Stocki wrote:

> @Peter: Was macht dieser Code?

Er zählt pro Jahr um 1,25 Tage weiter, also 1-2-3-5 usw.
Das Jahr zähle ich 2-stellig 00..99

> Was sind das für Werte auf die mit lpm
> zugegriffen wird?

Der Wochentag des 1. jedes Monats.


Und der Trick, mit dem 1.3. anzufangen, umgeht die Sonderbehandlung des 
Schalttags.


Peter

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Florian für den Link (auch wenn meine Frage etwas vom Thema 
abweicht).
Man nimmt also einfach eine ausreichend breite Fließkommazahl. Die 
Gaußsche Osterformel soll auch irgendwann in 8000 Jahren danebengehen, 
das ist nur eine Näherung.
Mein 8€-DCF77-Wecker vom Supermarkt kann die Mondphase anzeigen, also 
kann das nicht so kompliziert sein.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.