2. Tipps und Tricks Teil 2 ab 2.2.28 (zurück zu Teil 2 Anfang , Teil 2 Uhr, zu Teil_1 , zu Startseite )
(zurück zu Teil 2 Uhr ) ccBasic DOW, Sommerzeit bestimmen, usw.
(zurück zu Datum_berechnen
allgemein )
Datum berechnen
Fortsetzung für Steuerungsgeräte (13.03.2008, Stand: 19.12.2016)
DOW Tag-Nummer in der Woche
Jahrestag Tag-Nummer im Jahr
Wochennummer im Jahr, Kalenderwoche
Osterdatum berechnen für Steuerungsgeräte mit Basic z.B. c-control
in
Assembler für PIC
Bewegliche Feiertage Rosenmontag, Karfreitag, Himmelfahrt, Pfingsten, Fronleichnam,
Muttertag,
Advent, Datum Sommerzeit, Buß- und Bettag mit
Osterdatum berechnen
Steuern mit Feiertagsbit für Heizung, Rollladen und Kirchenglocken
Unterprogramme für feste und bewegliche Feiertage
Weiter zu Tipps und Tricks Teil 3
Zeittakte mit Uhrzeit und TIMER, Wartezeit,
(Schaltuhr siehe Softwarebausteine)
Weiter zu Tipps und Tricks Teil 4
Überschreitung von 32767 beim Rechnen, Begrenzen
Zählen bis 65535 im word, Zahl 0 bis 65535, Anzeigen mit 1 bis 2 Kommastellen
Zahlen
über 65535 Zähler, Addition,
Multiplikation, Division
2.2.28) Einfache Berechnung des Wochentages für 2000 bis 2099
Die erforderliche Konstante KM je Monat wird im Programm einfach mit einem Befehl aus einer Tabelle geholt.
Beispiel mit ccBasic: Den heutigen Wochentag (DOW) bestimmen:
LOOKTAB Konstante, month, KM ' Die Variable KM enthält nun den Wert aus der Tabelle
DOW = ((5 * year + KM) / 4 + day ) MOD 7 ' Tag 0 bis 6 (year 2-stellig für Jahr 2000 bis 2099)
Die Tabelle am Ende des Programms mit Namen Konstante lautet:
TABLE Konstante 0 23 7 8 20 0 12 20 4 16 24 8 16 TABEND
Statt KM
kann natürlich eine temporäre Variable z.B. wert3 benutzt werden.
Andere
Methoden siehe Datum_berechnen
allgemein
2.2.29)
Tag-Nummer im Jahr berechnen, Jahrestag für Steuerungsgeräte in Basic z.B.
c-control
(1) Tagnummer bestimmen mit Programmzeilen (1901 bis 2099)
In diesem Programmteil wird der Jahrestag (Tag-Nr.) aus Day, Month und year berechnet.
Dabei wird der 29.2. für Schaltjahre
berücksichtigt.
define TagNr word ' define wert12 word , define wert3 byte
TagNr =
(month - 1) * 31 + day
' je nach
Monat wird korrigiert
if month
> 2 then TagNr = TagNr –3
if month
> 2 AND year MOD 4 = 0
then TagNr = TagNr + 1 ' Schaltjahr 29.2.
if month
> 4 then TagNr = TagNr – 1
if month
> 6 then TagNr = TagNr – 1
if month
> 9 then TagNr = TagNr – 1
if month >
11 then TagNr = TagNr – 1
Nun liegt die Tag-Nummer 1 bis 365 (366) des aktuellen Jahres im word TagNr
Man kann auch die temporäre Variable wert12 anstelle TagNr anwenden um Variable zu sparen.
(2)
Tagnummer mit Formel errechnen für Programme z.B.
Basic (1901 bis 2099)
TagNr = Day + 30 *(Month –1) + Month * 9 / 16 + (Month >2)*(2 + (year MOD 4 = 0))
Erläuterungen: Der Klammerwert (Month >2) ist im Januar und Februar = 0 und ab März = –1.
(year MOD 4 = 0) ist in Schaltjahren = –1 ansonsten = 0. Dadurch wird nach dem Februar mit –2 bzw. –1 korrigiert.
Bei einigen Programmiersprachen und Tabellenkalkulation bedeutet „wahr“ = +1, dann sind obige + durch – zu ersetzen.
year darf auch 2-stellig 00 bis 99 anstelle 1901 bis 2099 sein, weil eine Zahl durch 4 teilbar ist, wenn die letzten 2 Dezimalstellen durch 4 teilbar sind.
Kürzere Formel zur Berechnung der Tagnummer
TagNr
= Tag + 489 * Monat / 16 – 30 + (Month >2)*(2 + (year MOD 4 = 0))
Alternativer Weg zur Berechnung der Tagnummer
TagNr = Tag
+ 489 * Monat / 16 – 30
if
month > 2 = 0 then TagNr = TagNr – 2 ' Korrektur ab März wegen
Februar
if
month > 2 AND year MOD 4 = 0 then
TagNr = TagNr + 1 ' Schaltjahr 29.2.
Tagnummer in Datum umformen siehe Datum_berechnen
allgemein
(3)
Zeiger für Datenspeicherung ( =Adresse)
Falls Daten z.B. Energieverbrauch je Tag nur für ein halbes Jahr gespeichert werden sollen:
Zeiger =
TagNr MOD 184 ' 1 bis 183 und nochmals für
184 bis 366 ( 0 bis 182)
Für diesen Zeiger (kleiner 255) reicht auch ein Byte z.B. wert3 (temporäres Byte):
wert3 =
TagNr MOD 184 ' 1 bis 183 und nochmals für 184 bis 366 ( 0 bis 182)
2.2.30) Wochen-Nummer berechnen für Steuerungsgeräte in Basic z.B.
c-control
Möchte man Betriebsstunden oder Energieverbrauch wöchentlich erfassen und je Woche speichern, dann benötigt man die Wochen-Nr.
Die Berechnung erfolgt mit der Tag-Nummer des Jahres, dessen Berechnung aus dem Datum siehe oben.
Das folgende Programm gibt die Kalenderwoche von Montag bis Sonntag aus.
Die europäische Norm wird
eingehalten. Achtung, Woche 1 ist die Woche, in
welcher der 4. Januar liegt.
Am Anfang und Ende des Jahres werden die richtigen Wochennummern bestimmt.
Zum Beispiel liegt der 31.12.2008 in Woche 1 des Jahres 2009.
2009 hat 53 Wochen und die ersten Tage 2010 liegen in Woche 53.
Eingänge des Programmbausteins sind Tag-Nr des Jahres in Variable wert12
und year (zweistellig) 01 bis 99 für 2001 bis 2099 in Variable wert3 bzw. 4-stellig 1901 bis 2099
Ausgang (Ergebnis) ist die Wochen-Nr. in Variable wert3 mit zugehörigem Jahr in wert4.
Hier wurden temporäre Variablen verwendet, die in anderen Programmteilen wieder belegt werden können.
wert12 =
TagNr '
des Jahres 1 bis 365 bzw. 366
wert4 =
year '
Jahr zweistellig bzw. 4-stellig je nach
Unterprogramm
gosub
WochenNr ' Berechnung der Wochennummer
if wert3 = 0
then goto WoNull ' à Woche vom 31.12. des Vorjahres
if wert3 =
53 then goto WoPruef ' à Woche vom 1.1. des Folgejahres prüfen
goto ende ' Fertig,
Wochennummer liegt in Variable wert3
#WoPruef ' Woche vom 1.1. des Folgejahres prüfen
wert12 = 1
wert4 = year
+1
gosub
WochenNr
if wert3 = 1
then goto ende ' à Fertig, Woche 1 des
Folgejahres statt 53
wert3 = 53 ' Woche 53 ist
richtig
wert4 =
wert4 –1
' Jahr rücksetzen
goto ende
#WoNull ' gültig
ist Woche vom 31.12. bzw. 30.12. des Vorjahres
wert12
= 365 '
Jahrestag 365 = 31. bzw. 30.12.
wert4 = year
–1
gosub
WochenNr ' (Korrektur der Wochennummer)
goto ende ' Fertig,
Wochennummer 52 bzw. 53 liegt in Variable wert3
' Unterprogramm, Grundformel zur Bestimmung der Wochennummer 2000 bis 2099
#WochenNr
' Eingänge:
year 2-stellig (wert3) und Jahrestag (wert12)
' WoNr =
((( 5* year + 7) /4) Rest von Division durch 7 + TagNr +3) / 7
wert3 = (((
5 * wert4 + 7) / 4) MOD 7 + wert12 +3) / 7
return ' à Ausgang: Wochennummer (wert3)
#ende
print “ Woche: “;wert3; ;“ zu Jahr “;wert4;“ “ ' Wochennummer mit zugehörigem Jahr
Wenn am Anfang des Jahres Woche 52 oder 53 gilt, dann zeigt das zugehörige Jahr wert4 das Vorjahr.
Wenn am Ende des Jahres Woche 1 gilt, dann ist das zugehörige Jahr wert4 das Folgejahr.
Bei 4-stelliger Jahreszahl (1901 bis 2099) gilt im Unterprogramm folgende Formel
WoNr = ((( 5 * wert4 + 3) / 4) MOD 7 +
wert12 +3) / 7
2.2.31) Ostern (Tag und Monat) berechnen für Steuerungsgeräte in Basic oder
Assembler
Die Berechnung der beweglichen Feiertage wird z.B. für das
automatische Läuten der Kirchenglocken benötigt.
define Wert1 byte '3 Zwischenspeicher 1 (zu wert12)
define Wert2 byte '4 Zwischenspeicher 2 (zu wert12)
define Wert12 word [2] '= Byte 3,4 Zwischenspeicher
define Wert3 byte ' Zwischenspeicher 3
(1) Jahr
(year) 2-stellig für 2000 bis 2099
wert3 = (204 – (year + 5) MOD 19*11) MOD 30 ' (year 2-stellig für 2000 bis 2099)
wert3
= 120 + wert3 – wert3 / 27 ' mit Ergänzung
für Jahre 2049 und 2076
wert2 = (1+ wert3 + year * 5 / 4 ) MOD 7
wert3 = wert3 – wert2 ' wert3 ist Bezug für alle anderen beweglichen Feiertage
wert1
= 1+ wert3 MOD 31 ' Ostersonntag
(Datum Tag)
wert2 = wert3 / 31 '
Ostermonat (Monat)
print
"Ostern
ist am ";wert1;".";wert2;" " 'Anzeige des Datums
if day = wert1 and month = wert2 then print “Frohe Ostern” 'Vergleich mit aktuellem Datum
(2) Jahr
(year) 4-stellig für 1900 bis 2099 bzw. 2199
wert3
= (204 – Jahr MOD 19*11) MOD 30 ' Jahr 4-stellig
wert3
= 120 + wert3 – wert3 / 27 ' mit Ergänzung für Jahre 2049 und 2076
wert2
= (wert3 + Jahr * 5 / 4) MOD 7 '
gültig bis 2099
(Erweiterung bis 2199 siehe unten)
wert3 = wert3 – wert2 ' wert3 ist Osterkennzahl, Bezug für alle beweglichen
Feiertage
wert1
= 1+ wert3 MOD 31 ' Ostersonntag
(Datum Tag)
wert2 = wert3 / 31 '
Ostermonat (Monat)
Erweiterung
für Jahre 1900 bis 2199 anstelle obiger Zeile
wert2 = (wert3 + Jahr * 5 / 4 – Jahr / 2100 ) MOD 7 '
mit Ergänzung gültig bis 2199
(3) Jahr
(year) 2-stellig für 2000 bis 2099 mit Tabellenzugriff
A = year MOD 19 '
Zugriff auf Tabellenposition A = 0 bis 18 (year 2-
LookTAB
OstermondT2, A, B
' Die Variable B enthält nun den Wert Märztag (incl.
C = (B + year + year /4) MOD 7 ' Wochentag Ostermond
E = B – C + 111
' E Osterkennzahl
(Easter index), Bezugswert für alle
K = B – C + 109 '
K Karfreitagskennzahl. Nur für Karfreitag!
T = 1+ E MOD 31 ' Ostersonntag (Datum
Tag)
M = E / 31 ' Ostermonat (Monat)
T = 1+ K MOD 31 '
Karfreitag (Datum Tag)
M = K / 31 ' dazu der Monat
Beispiel einer Anwendung für Auswertung mit aktuellem Datum für Karfreitag
If day = (1 + K MOD 31) AND month = K / 31 then Musik nicht zulässig
37 27 16 35 24 13 32 21
10 29 18 36 26 15 33 22
11 30 19
TABEND
(4) Programm in Assembler für Microchip Controller PIC 16F628A
Siehe Assemblerprogramm_ Karfreitag
2.2.32) Bewegliche
Feiertage (Tag und Monat) berechnen
Rosenmontag, Aschermittwoch, Karfreitag, Ostermontag, Himmelfahrt, Pfingsten und Fronleichnam sind ebenfalls bewegliche Feiertage, denn sie sind an das Osterdatum gekoppelt. Die Unterprogramme gosub und Erläuterungen findet man weiter unten.
gosub Ostern ' Datum Ostern (Osterkennzahl
wert3) berechnen
wert12 = – 48
'
Rosenmontag liegt 48 Tage vor Ostersonntag
gosub Tage_zu_Ostern
' Unterprogramm setzt Tag und Monat in wert1 und wert2
print "Rosenmontag ist am ";wert1;".";wert2;" " 'Anzeige des Datums
if day = wert1 and month = wert2 then print
“Helau”
Die anderen Feiertage können folgen ohne gosub Ostern, sofern die Osterkennzahl im byte wert3 nicht verändert wird.
In den temporären Speicher wert3 hat gosub Ostern die Osterkennzahl gesetzt, die von gosub Tage_zu_Ostern ausgewertet wird.
wert12 = 39 : gosub Tage_zu_Ostern 'Himmelfahrt liegt 39 Tage nach Ostern
if day = wert1 and month =
wert2 then print “Vatertag”
2.2.33) Buß- und Bettag mit Osterdatum bestimmen
Der Buß- und Bettag ist auch ein beweglicher Feiertag. Er bezieht sich zwar auf das feste Datum Weihnachten, aber er liegt immer auf einem Mittwoch (16. bis 22. November). Weil der 24.12. und der 30.4. immer auf dem gleichen Wochentag liegen, hatte ich die Idee, mit meiner Osterformel das Datum vom Buß- und Bettag zu berechnen.
Gosub
Ostern ' Datum Ostern (Osterkennzahl wert3) berechnen (z.B. Jahr 1900 bis
2199)
wert1 = 16 + wert3 MOD 7 '
Datum Tag für Buß- und Bettag
wert2 = 11 'November
if
day = wert1 and month = wert2 then print “heute ist Buß- und Bettag”
2.2.34) Muttertag, Sommerzeit und Advent mit
Osterdatum berechnen
Das Datum aller Tage, die Bezug zum Wochentag haben, können ebenfalls mit meiner obigen Osterformel bestimmt werden. Die Osterkennzahl stellt ja einen Bezug von Sonntag und Datum im jeweiligen Jahr her (gosub Ostern). Daraus wird mit MOD 7 (Rest nach Division = 0 bis 6) der Abstand in Wochentagen berechnet und zum frühest möglichen Datumstag addiert.
Der frühest mögliche Tag beim Muttertag ist der 8. Mai und bei der Sommerzeit der 25. März bzw. 25. Oktober.
Gosub
Ostern ' Datum Ostern (Osterkennzahl wert3) berechnen (z.B. Jahr 1900 bis
2199)
wert1 = 8 + wert3 MOD 7 '
Datum Tag für Muttertag, Sonderfall wegen Pfingsten siehe Datum_berechnen
allgemein
Print “Muttertag
ist am “;wert1;”.
Mai “
wert1 = 18 + wert3 MOD 7 ' Datum Tag für 4. Advent im Dezember
wert1 = 11 + wert3 MOD 7 ' Datum Tag für 3. Advent im Dezember
wert1 = 4 + wert3 MOD 7 ' Datum Tag für 2. Advent im Dezember
wert1 = 1+ (26 + wert3 MOD 7 ) MOD 30 ' Datum Tag für 1. Advent im Dezember / November
wert2 = 12 – Tag / 27 ' Datum Monat jeweils Tag des Advents (Dezember / November)
print
“ 1. Advent
ist am “;wert1;“.“;wert2;“. ”
Bei der
Sommerzeit sind zusätzlich Konstante notwendig, weil Monate nicht ein
Vielfaches von Wochen sind.
Wert1
= 25+ (wert3 + 2 ) MOD 7 '
Datum Tag für Beginn Sommerzeit (Konstante = 2)
Wert2
= 25+ (wert3 + 5 ) MOD 7 '
Datum Tag für Ende Sommerzeit (Konstante = 5)
print
“Sommerzeit
ab “;wert1;“ März bis “;wert2;“ Oktober ”
siehe auch Sommerzeit-Bit in Teil
2 Uhr
2.2.35) Steuern
mit Feiertagsbit
Mit einem Feiertagsbit können Heizung und Rollladen z.B. später gestartet werden. Nach jedem gosub liegt außerdem das Datum des jeweiligen Feiertags als Tag (in wert1) und Monat (in wert2) und kann z.B. mit print ausgegeben werden.
'Deutsche
Feiertage (unterschiedlich je nach Bundesland) und alle Sonntage (alternativ
ohne Sonntage)
Andere Feiertage z.B. Bettag
der Schweiz können wie der deutsche Buß- und Bettag mit der Osterkennzahl
eingefügt werden.
Feiertagsbit = (DOW = 0) ' (Feiertagsbit = OFF ist die Alternative ohne Sonntage)
'Feste Feiertage vorgegeben im Format Monat Tag (mmdd)
wert12 = 101 : gosub Feiertag 'Neujahr 1.1.
wert12 = 501 : gosub Feiertag '1. Mai
wert12 = 1003 : gosub Feiertag 'Tag der dt. Einheit
wert12 = 1225 : gosub Feiertag '25. Dezember
wert12 = 1226 : gosub Feiertag '26. Dezember
'An Ostern gekoppelte Feiertage (hilfsweise bei Buß- und Bettag)
gosub Ostern 'Datum Ostern (Osterkennzahl wert3) berechnen
gosub Buss_Bet_Tag ' Buß- und Bettag Datum berechnen
wert12 = –48 : gosub Tage_zu_Ostern 'Rosenmontag (minus 48
Tage)
wert12 = –47 : gosub Tage_zu_Ostern 'Karnevaldienstag
wert12 = –46 : gosub Tage_zu_Ostern 'Aschermittwoch
wert12 = –2 : gosub Tage_zu_Ostern 'Karfreitag
wert12 = 1 : gosub Tage_zu_Ostern 'Ostermontag
wert12 = 39 : gosub Tage_zu_Ostern 'Himmelfahrt (39 Tage)
wert12 = 49 : gosub Tage_zu_Ostern 'Pfingstsonntag (49 Tage)
wert12 = 50 : gosub Tage_zu_Ostern 'Pfingstmontag (50 Tage)
wert12 = 60 : gosub Tage_zu_Ostern 'Fronleichnam (60 Tage)
Hier kann weiteres Hauptprogramm des Anwenders folgen.
goto Loop
2.2.36) Unterprogramme
feste und bewegliche Feiertage
'------- Unterprogramme----------------------------------------
#Feiertag 'mit festem Datum mmdd in Variabler wert12
wert3 = wert12 / 100 'Monat
wert1 = wert12 MOD 100 'Tag
wert2 = wert3 'Monat
' Return ' falls ohne Vergleich z.B. Ausgabe des Datums mit print
goto Feiertagsdatum ' Vergleich mit heute
#Ostern 'Ostersonntag (year 2-stellig für 2000 bis 2099)
wert3 = (204 – (year
+ 5) MOD 19*11) MOD 30
wert3
= 120 + wert3 -
wert3 / 27 ' mit Ergänzung
für Jahre 2049 und 2076
wert2
= (1+ wert3 + year * 5 / 4 ) MOD 7
wert3 = wert3 – wert2 ' Osterkennzahl wert3 ist Bezug für alle anderen beweglichen Feiertage
wert1 = 1+ wert3 MOD 31 'Ostersonntag
wert2 = wert3 / 31 'Ostermonat
' Return ' falls ohne Vergleich z.B. Ausgabe des Datums mit print
goto Feiertagsdatum ' Vergleich mit heute
#Tage_zu_Ostern 'an Ostern (wert3) gekoppelte Feiertage
' Erläuterungen:
'+
wert2 / 154 ist Korrektur für fehlenden 31.4. für
Feiertage nach 1. Mai.
'+(wert2 < 93)*(3+ (year MOD 4=0 ) – (Jahr =2100)) ist
Korrektur für Karnevalstage im Februar (-2 bzw. –3Tage).
Dabei darf year 2-stellig oder 4-stellig sein. – (Jahr =2100 wird bei 2-stellig weg gelassen.
' Der Klammerwert (wert2 < 93) ist im Januar und Februar = –1 und ab März = 0.
' (year
MOD 4 = 0) ist in Schaltjahren = –1
ansonsten = 0.
' (Jahr =2100) ist im genannten Jahr
= –1 ansonsten = 0.
wert2
= wert3 + wert12 'Ostersamstag + Abstand Feiertag (wert12)
wert2
= wert2 + wert2 / 154 + (wert2 < 93)*(3+ (year MOD 4 = 0) –
(Jahr
=2100)) 'mit Ergänzung Karnevalstage
wert1
= 1+ wert2 MOD 31 ' Datum Tag
wert2 = wert2 / 31 ' Datum Monat
' Return ' falls ohne Vergleich z.B. Ausgabe des Datums mit print
goto Feiertagsdatum ' Vergleich mit heute
#Buss_Bet_Tag 'Eingang: wert3 von gosub Ostern
wert1 = 16 + wert3 MOD 7 ' Datum Tag für Buß- und Bettag
wert2 = 11 ' November
' Return ' falls ohne Vergleich z.B. Ausgabe des Datums mit print
#Feiertagsdatum
' Vergleich mit heute
if day = wert1 and month = wert2 then Feiertagsbit =
ON
Return
weitere
Berechnungen zum Datum bei Datum_berechnen
allgemein
------------------------------------------------ ENDE Tipps und Tricks Teil 2 ------------ nach_oben
--------------------- weiter zu
Teil 3 Teil 4 zurück zu
Tipps und Tricks Teil_1 Startseite