Szükségem volt egy óra programhoz arra, hogy a dátum alapján kitalálja magának a program a hét napját, és ne kelljen azt is beállítani, mint a legtöbb buta digitális órán. Azt, hogy miképpen kell ezt megcsinálni, gyorsan találtam ötletet a neten. Még program forrást is találtam, de hibás volt. Igy némi gondolkodás után sikerült megíni magamnak.
Az alap ötlet kézenfekvő! Ha meghatározzuk, hogy hány nap telt el a 0. év január 1.-e óta, akkor a napok számát kell csak héttel osztani és a maradék megmondja, hogy hányadik napja van a hétnek. Pl. ha a mai napon (mikor ezeket a sorokat írom 2022.04.16. van), 17730 nap telt el a 0. év első napja óta. Azonban ezt nem is olyan egyszerű kiszámolni, mivel egy év nem mindig 365 nap, ráadásul a hónapok sem azonos napokból állnak. A legnagyobb gond a szökőévek figyelembevételével van. Nevezetesen minden 4-el osztható év szökőév. Kivéve, ha az adott év éppen 100-al osztható, mert akkor nem szökőév mégsem! Kivéve, ha 400-al osztható mert akkor meg mégis szökőév. Azért ilyen furcsa a szökőév meghatározása, mert a föld a nap körül 365 nap 5 óra 48 perc 46 másodperc tesz egy kört. Ez majdnem pontosan 365 és negyed nap, de egy kicsit kevesebb, ezért kell 100 évente egy szünet a szökőévekben. Viszont ez sem elegendően pontos korrekció , ezért kell 400 évente mégis egy szökőév. Elődjeink csak így tudták megoldani, hogy évszázadok alatt ne csússzon el az évszakok kezdete. Gergely pápa idejében már 8 nap eltérés keletkezett, amit az akkori mezőgazdaság észrevett, és ez kényszerítette ki a naptárreformot 1582-ben.
Szóval a feladat egyszerű, bárki meg tudná írni, így nekem is sikerült. Csak az idő megy el vele! Remélem valaki még rajtam kívül fel tudja használni.
A programot az UnoArduSim szimulátorban írtam meg. Ennek a szimulátornak van néhány butasága, pl. a Serial.println() függvénybe a zárójelekbe nem lehet saját függvényt beírni, ezért először változókba kell tölteni az értékeket és azt küldeni a sorosportra. A datum_hetnapja() függvényem elején csináltam néhány ellenőrzést, ami a megadott dátumot ellenőrzi. Pl. nem lehet a hónap 0. Sajnos a hónapok napjainak a számát ellenőrző programsorban az if()-ben olyan sok feltétel lett, amit a szimulátor már nem tud kezelni, ezért azt is ki kellett kommentezni. Valós Arduino-ba töltve azonban működik.
A kommentek alapján remélem követhető a működés. Nagy ötletek nincsenek a megvalósításban.Pl. az aktuális év eltelt napjainak a számát egy tömbben tárolt adatokból nyerem ki, ahol minden egyes hónap kumulált napszámait tárolom. Azaz a hónap megadásával visszakapom, hogy hány nap telik el abban a hónapban január 1 óta. Természetesen itt is figyelni kell, mert ha az aktuális év szökőév és a dátum nagyobb, mint február, akkor még egyet a napokhoz kell adni, mert szökőéveben február nem 28, hanem 29 napos. Szóval bamba feltételrendszer az egész megoldás.
Nem igazán tudtam értelmezni magamtól a kezdő napot, és hogy az milyen napja volt akkor a hétnek. A net teljesen összezavart. A szabályok ismeretében úgy tekintettem, hogy krisztus születésének éve 0. év január 1-el és vasárnappal kezdődik. Ennek megfelelően Krisztus 0.12.24.-én született hétfőn. Ezt persze csak az én programom adta vissza, mint eredményt. Valójában Krisztus időszámításunk előtt 4 vagy 6-ban születhetett, és nem is decemberben. Az akkori Juliánus naptár szerinti napforduló esett december 24-re, így ezt a napot tekintik születésnapjának. A napforduló viszont tudjuk, hogy a Gergely naptár szerint december 21.-én van. Még szerencse, hogy nem ezen infók alapján állítottam be a program 0. napját, hanem a jelenből számoltam vissza!
byte a;
bool b;
void setup()
{
Serial.begin(9600);
b = datum_hetnapja(2022, 4, 16); //2022.04.16 szombat (6)
Serial.println(b);
b = datum_hetnapja(2022, 11, 3); //2122.11.13 csütörtök (4)
Serial.println(b);
a = szokoev(2022); //nem szökőév
Serial.println(a);
a = szokoev(2024); //szökőév
Serial.println(a);
}
void loop()
{
}
byte datum_hetnapja(int ev, byte ho, byte nap)
/*******************************************************************************
* Ez a függvény paraméterként várja egy dátumból az évet, hónapot és napot. *
* Eredményként visszaadja a megadott dátum melyik napja a hétnek. A hét napja *
* 1től 7-ig megadott érték, az 1 a hétfő, 7 a vasárnap. *
*******************************************************************************/
{
// if (ho<1) { return 0;} //hónap napjainak száma nem lehet 0
// if (ho!=1 & ho!=3 & ho!=5 & ho!=7 & ho!=8 & ho!=10 & ho!=12 & nap>31) { return 0;}; //több napot adtunk meg a hónapnak, mint amennyi napja van
// if (ho!=4 & ho!=6 & ho!=9 & ho!=11 & nap>30) { return 0;} //több napot adtunk meg a hónapnak, mint amennyi napja van
// if (ho==2) { //ha február van, ellenőrizni kell a szökőév szerinti napokat is
// if (szokoev(ev)) { //megmondja, hogy az adott év szökőév-e, mert ha igen, akkor a február 29 napos
// if (nap>29) { return 0;}} //szökőév, és több napot adtunk meg
// else {
// if (nap>28) { return 0;}} //nem szökőév, és több napot adtunk meg
// }
int ho_napjai[]={0,31,59,90,120,151,181,212,243,273,304,334,365}; //Az évből eltelet hónapok napjainak száma halmozva havonként nem szökőévben
long elmult_nap=ev*365; //Eddig ennyi napja volt az elmúlt éveknek a szökőévek figyelembevétele nélkül
int elmult_szokonap=0; //Ebbe a változóba számoljuk ki majd a szökőévekből adódó plusz napok számát
int szn4=(ev-1)/4; //Minden negyedik év szökőév (kivéve minden 100. év, de azt később levonjuk)
//az aktuális évet nem szabad beleszámolni, mert az majd az aktuális év napjaiban benne lesz
int szn100=(ev-1)/100; //minden 100. év nem szökőév, ezt majd levonjuk, kivéve minden 400. év, azt meg mindjárt hozzáadjuk
int szn400=(ev-1)/400; //Minden 400. év mégiscsak szökőév
elmult_szokonap=szn4-szn100+szn400; //így megkaptuk a szökőévekből adódó plusz napokat
long akt_ev_nap=ho_napjai[ho-1]+nap; //Az eddig eltelt hónapok napjainak száma kiderül a tömbből, plusz hozzáadjuk az aktuális hónap napjait, ahol épp járunk
//Ha az adott év szökőév, és már elmúlt február, akkor még egyet hozzá kell majd adni, mert a tömb egy nem szökőévre készült.
long akt_ev_szokonap=0;
if (ho>2) {
if (szokoev(ev)) {
akt_ev_szokonap++; // ha az aktuális éveben már elmúlt február, és az év szökőév, akkor még egy napot hozzá kell adni
}
}
long napok=elmult_nap+elmult_szokonap+akt_ev_nap+akt_ev_szokonap; //és ezzel megkaptuk Jézus szülteésének napja óta eltelt napok számát
if (napok%7==0) {
return 7; //ha pont vasárnap van, akkor maradék nélkülosztható 7-el, ezért ilyenkor 7-et adunk vissza
}
else {
return napok%7; //a maradék az adott hétben eltelt napok száma (hétfő az 1)
}
}
bool szokoev(int ev) {
/************************************************************************************
* Ez a függvény paraméterként várja az évet (pl. 2022) és visszaadja bool értékben *
* hogy a paraméterben megadott év szökőév, vagy sem. *
************************************************************************************/
if (ev==0) {
return false; //a 0.évet nem vesszük szökőévne
}
bool szoko_ev=false;
if (ev%4==0) { //ha néggyel osztva nem ad maradékot, akkor szökőév
szoko_ev=true;
if (ev%100==0) { //ha 100-al osztva nem ad maradékot, akkor nem szökőév
szoko_ev=false;
if (ev%400==0) {
szoko_ev=true; //ha 400-al osztva nam ad maradékot, akkor mégis szökőév
}
}
}
return szoko_ev;
}Készítettem egy olyan programot is, ami automatikusan átállítja az órát a téli és nyári óraállítás időpontjában egy órával előre illetve vissza. Bagatell dolognak tűnik, de nem az, ha az óránk épp elemről működik, és csak az óraállítás után kapcsoljuk be valamikor!