Forum: Compiler & IDEs Algorithnus für Sommerzeitberechnung gesucht


von UBoot-Stocki (Gast)


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

von Roland P. (pram)


Lesenswert?

Schau dir mal den JavascriptCode von der Seite an:

http://www.ez-calculators.com/daylight-saving-times-dates.htm

insbesondere die Funktion whatdates.

Gruß
Roland

von Unbekannter (Gast)


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.


von Herr M. (herrmueller)


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

von Florian (Gast)


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.

von UBoot-Stocki (Gast)


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

von Florian (Gast)


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.

von Peter D. (peda)


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:
1
if( day - wday >= 25 && (wday || hour >= 2) ){ // after last Sunday 2:00
2
    if( month == 10 )        // October -> Winter
3
      return;
4
  }else{          // before last Sunday 2:00
5
    if( month == 3 )        // March -> Winter
6
      return;
7
  }


Peter

von UBoot-Stocki (Gast)


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


von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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

von UBoot-Stocki (Gast)


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

von Karl H. (kbuchegg)


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.

von Florian (Gast)


Lesenswert?

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

Oder Tabelle nehmen.

von Peter D. (peda)


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:
1
;------------------------------------------------------------------------   
2
;
3
.equ    FD = 0          ;offset weekday
4
5
;****************************** calculation weekday *********************
6
get_wday:
7
        mov     zl, month               ;Month (1..12)
8
        ldi     zh, 0
9
        subi    zl, low(-(2 * _cwd5 - 1))
10
        sbci    zh, high(-(2 * _cwd5 - 1))
11
        lpm                             ;get 1. day of month
12
13
        mov     a0, year
14
        cpi     month, 3                ;start calculation with march
15
        brcc    _cwd1
16
        dec     a0                      ;use last year for jan. & feb.
17
_cwd1:  mov     a1, a0
18
        lsr     a1
19
        lsr     a1
20
        add     a0, a1                  ;* 1.25
21
        add     a0, r0                  ;+ 1. day of month
22
        add     a0, day                 ;+ day
23
_cwd2:  subi    a0, 7
24
        brcc    _cwd2
25
        subi    a0, -7                  ;a0 = a0 % 7
26
        mov     weekday, a0             ;0 = So, 1 = Mo, ... , 6 = Sa
27
        ret
28
_cwd5:  .db     FD, FD+3, FD+2, FD+5, FD, FD+3, FD+5, FD+1, FD+4, FD+6, FD+2,
29
FD+4
30
;-----------------------------------------------------------------------


Peter

von UBoot-Stocki (Gast)


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

von Peter D. (peda)


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

von Christoph db1uq K. (christoph_kessler)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.