
A mellékelt példaprogram megnyitása előtt a MoonPhase.pas-ban lévő komponenst telepítenie kell a Delphi alá. Ehhez válassza a Component - Install Component menüpontot.
Mielőtt belekezdenénk a számításokba, szükségünk lesz két konstans értékre. Az egyik a Holdciklus ideje. Ez a számítások szerint 29,53058867 nap. Ezen kívül szükségünk lesz az egy nap alatt eltelt milliszekundumok számára is, ami 24*60*60*1000-rel egyenlő.
A számítás lényege a következő: veszünk egy kiindulási dátumot, amelytől kezdve számíthatjuk az eltelt Holdciklusokat. Ebben az esetben ez 2003. január 2-a, 21 óra 23 perc lesz. Ekkor biztosan Újhold állapotában volt a Hold. Persze választhatunk bármely időpontot, a lényeg az, hogy Újhold legyen az adott napon. Ezután kiszámoljuk a mai dátum és a kiindulási dátum között eltelt milliszekundumokat, majd elosztjuk a Holdciklus milliszekundumban kifejezett értékével, ezután pedig, hogy %-os értéket kapjunk, megszorozzuk 100-al a kapott értéket. Az eredményt addig csökkentjük, míg 100 alatti számot nem kapunk. Ekkor megkapjuk az ÚjHold óta eltelt időt százalékban. A kiindulási és az aktuális dátum közti különbséget a DateDifference függvény szolgáltatja. Mivel a dátumok TDateTime formátumúak, kettébontjuk azokat dátum és idő részre.
function TMoonPhase.DateDifference: double;
var Hour, Min, Sec, Msec: Word;
CurrentDate, CurrentTime: TDateTime;
BaseDate, BaseTime: TDateTime;
DateDiff, TimeDiffMs, DateTimeDiffMs: double;
CurrentTimeMs, BaseTimeMs: double;
begin
A DateDiff változóban tároljuk a két dátum között eltelt napok számát.
CurrentDate:=Date;
BaseDate:=EncodeDate(2003, 01, 02);
DateDiff:=CurrentDate-BaseDate;
A TimeDiff változóban a két idő közötti milliszekundumok száma kerül eltárolásra.
CurrentTime:=Time;
BaseTime:=EncodeTime(21,23,0,0);
DecodeTime(CurrentTime, Hour, Min, Sec, Msec);
CurrentTimeMs:=Hour*60*60*1000+Min*60*100+Sec*1000+Msec;
DecodeTime(BaseTime,Hour, Min, Sec, Msec);
BaseTimeMs:=Hour*60*60*1000+Min*60*100+Sec*1000+Msec;
TimeDiffMs:=CurrentTimeMs-BaseTimeMs;
A függvény visszatérési értéke végül az eltelt napok számának milliszekundumban kifejezett értékének és a két idő között eltelt milliszekundumok számának összege lesz.
DateTimeDiffMs:=DateDiff*msPerDay+TimeDiffMs;
Result:=DateTimeDiffMs;
end;
A fenti függvény által szolgáltatott értéket arra fogjuk felhasználni, hogy kiszámítsuk, hány % telt már el a Holdciklusból. Mindezt a MoonPhasePercent függvény valósítja meg.
function TMoonPhase.MoonPhasePercent: double;
var diff,phase: double;
begin
diff:=DateDifference;
if (diff<0) then diff:=-1*diff;
phase:= diff/(MoonCycle * msPerDay)*100;
A phase változóban kapott értéket mindaddig csökkentjük, míg az 100 alatti nem lesz. A kapott szám lesz az eltelt Holdciklus %-os értéke.
while(phase>100) do
begin
phase:=phase-100;
end;
Result:=phase;
end;
A kapott értéket megvizsgálva megállapíthatjuk, hogy a Hold mely fázisában jár éppen. A MoonPhaseName függvénnyel valósítjuk meg mindezt, mely a Holdfázis nevével tér vissza.
function TMoonPhase.MoonPhaseName(phase: double): string;
var phasename: string;
begin
if(phase >= 0) and (phase <= 2.49) then
phaseName:='Újhold';
if(phase >= 2.5) and (phase <= 22.49) then
phaseName:='Növekvő Hold';
if(phase >= 22.5) and (phase <= 27.49) then
phaseName:='Első negyed - Félhold';
...
Result:=phaseName;
end;
Végül készítünk egy Execute függvényt, melyet meghívva a programunkból, a komponens published property-jeiben visszakapjuk a megfelelő információkat. A függvény felépítése a következő:
procedure TMoonPhase.Execute;
var
phasepercent,fullness,daysTillNew,daysTillFull:double;
phaseName:string;
newDate,fullDate:TDateTime;
begin
A phasePercent változóban eltároljuk, hogy a Holdciklus idejéből hány százalék telt el eddig. Ez megegyezik az utolsó Újhold óta eltelt idő százalékos arányával. Mindehhez meghívjuk a MoonPhasePercent nevű függvényt, mely kiszámítja ezt az értéket és visszaadja eredményként.
phasePercent:=MoonPhasePercent;
A phaseName sztring típusú változónak átadjuk a MoonPhaseName függvény által szolgáltatott értéket, mely az aktuális Holdfázist számítja ki a paraméterként kapott phasePercent értékéből, majd annak nevét adja vissza.
phaseName:=MoonPhaseName(phasePercent);
A következőkben kiszámítjuk, hogy a Hold hány százaléka látható, attól függően, hogy a Telihold előtti vagy utáni állapotban van a Holdciklus.
if (phasePercent<= 50.0) then
fullness:=phasePercent*2
else
fullness:=(100-phasePercent)*2;
Azt, hogy hány nap múlva fogja a Hold az Újhold, illetve a Telihold állapotát elérni, a következő képletekkel számíthatjuk ki.
daysTillNew:=(1-phasePercent/100)*MoonCycle;
daysTillFull:=(1-fullness/100)*MoonCycle;
A fenti állapotok dátumát is kiszámíthatjuk, ha az aktuális dátumhoz hozzáadjuk a két változóban kapott értékeket.
newDate := Now + daysTillNew;
fullDate := Now + daysTillFull;
Végül átadjuk a komponens published property-jeinek a kapott értékeket.
FPhaseName:=phaseName;
FPhasePercent:=RoundValue(phasePercent,2);
FFullness:=RoundValue(fullness,2);
FDaysTillNew:=RoundValue(daysTillNew,2);
FDaysTillFull:=RoundValue(daysTillFull,2);
FNextNewDate:=newDate;
FNextFullDate:=fullDate;
end;
A mellékelt példaprogramban meghívjuk a fenti függvényt, majd a kapott értékeket kiíratjuk. Azt, hogy éppen milyen fázisban jár a Hold, egy képpel meg is jelenítjük. Meg kell jegyezni, hogy a következő Újhold és Telihold dátuma a kerekítésekből adódóan csak közelítő jelleggel szolgáltat információt. Ügyeljünk arra, hogy a program helyes futtatásához számítógépünk területi beállításainál a dátumnak éééé.hh.nn formátumúnak kell lennie, azaz nem tartalmazhat szóközöket, ugyanis a Delphi ezt a formátumot használja.