Minulla on taulukko muotoinen kalenteri, joka menee ylhäältä alaspäin.
Koodissani, $i = Muuttuja jonka arvo kasvaa kierros kierrokselta, tämä arvo viittaa meneillään olevaan päivämäärään.
Koodissani, $o = Muuttuja viittaa soluun, joka luodaan päivämäärien vierelle.
Varsinainen ongelmani, miten lasken päivämäärän joka viittaa pääsiäiseen. Loogista laskentatapaa en sille saa suollettua, joten olisiko jollain antaa ajatusta ja neuvoa laskentakaavasta. Alla olevan esimerkin mukaan lasken juhannuksen ja juhannusaaton. Tästäkin tavasta voi kertoa paremman tyylin, jos mieleen tulee. Testaukseni perusteella, tuon pitäisi mennä oikein, mutta silti.
// Juhannusaatto if(($i >= 19 && $i <= 26) && $kuukausi == 6 && (date('N', mktime(0, 0, 0, 6, $i, $vuosi)) == 5)) { if($o++ <= 1) { $background = "background:red; color:white;"; $selite = 'Juhannusaatto'; } } // Juhannuspäivä if(($i >= 20 && $i <= 26) && $kuukausi == 6 && (date('N', mktime(0, 0, 0, 6, $i, $vuosi)) == 6)) { $background = "background:red; color:white;"; $selite = 'Juhannuspäivä'; // Juhannus }
Tuolta löytyy esimerkiksi Gaussin ja Butcherin menetelmät pääsiäisen laskemineen sekä huomautuksia niiden soveltamisesta.
http://fi.wikipedia.org/wiki/
Varmaan jommassa kummassa juhannusaatto tai juhannuspäivä kaavassasi on virhe koska molemmissa $i <= 26. Itse laittaisin ehkä niin että toiselle on varsinainen kaava ja toinen riippuu siitä, jolloin mahdolliset virheet tarvitsisi korjata aina vain yhteen paikkaan.
Sen verran kaavat eroaa, että toinen katsoo milloin on aikavälille osuva launtai sekä milloin on perjantai. Juhannuspäivä osuu aina perjantaille. Toisin sanoen riittäisi yksi if-lauseke, jonka sisällä tarkistaisin tuon. En kupaakin erikseen, no aina ajattelee paremmin kun muut kyseenalaistavat :)
Kiitos. Tutustunpa tuohon pääsiäisen laskemiseen.
Kirjoitin joutessani funktion (Gaussin menetelmä) tätä varten.
<?php function easter_gauss($year, $arr){ $a = $year % 19; $b = $year % 4; $c = $year % 7; $d = (19 * $a + 24) % 30; $e = (2 * $b + 4 * $c + 6 * $d + 5) % 7; $h = 0; // Oletusarvoisesti pääsiäinen ei ole huhtikuussa // Pääsiäinen on maaliskuun (22 + d + e):s päivä. $day = 22 + $d + $e; // Jos $day on yli 31, pääsiäinen on huhtikuun (d + e - 9):s päivä. if($day > 31){ $h = 1; // Pääsiäinen on huhtikuussa $day = $d + $e - 9; // Lasketaan päivä // Jos $day on 26, pääsiäinen on aina viikkoa aiemmin. if($day == 26){ $day -= 7; } // samoin jos $day on 25 sekä $d = 28 ja $a yli 10, kuten vuosina 1954 ja 2049. elseif($day == 25 && $d=28 && $a>10){ $day -= 7; } } // Kuukausi $m = ($h == 0) ? '3' : '4'; // Palautetaan merkkijonona if($arr == 0)$easter = $day .".". $m; // Palautetaan taulukkona else{ $easter["d"] = $day; $easter["m"] = $m; } return $easter; } echo easter_gauss(2015, 0); // Palauttaa 5.4 ?>
Edit.
Tai voithan tehdä sen yksinkertaisemminkin...
Kappas, sehän olikin hankalampaa kuin oletinkaan.
manninen kirjoitti:
Kappas, sehän olikin hankalampaa kuin oletinkaan.
Kun ymmärtää periaatteen, niin sen jälkeen on helpompi lähteä muodostamaan ohjelmaa. Muutaman rivin verran tota funktioo saisi pienennettyä, kun ottaa pois ton string/array -palautus virityksen pois.
Tuo ei vielä kovin monimutkainen ole, ensiksi lasketaan muutama jakojäännös. Tämän jälkeen jos päivä (lasketaan 22+d+e) on enemmän kuin 31, niin päivä (lasketaan d+e-9) on huhtikuun puolella.
Lopuksi tarkastetaan pari ehtoa liittyen huhtikuun 25 ja 26 päiviin...
Butcherin menetelmä on hieman monimutkaisempi, varmaan siihenkin funktion teen, mikäli mielenkiinto riittää :D
Pentu kirjoitti:
Butcherin menetelmä on hieman monimutkaisempi, varmaan siihenkin funktion teen, mikäli mielenkiinto riittää :D
Mielestäni tuo on selkeämpi, kun ei tarvita IF-lausekkeita ja jokunen laskutoimitus rittää. Linkittämästäni artikkelista saadaan suoraan kopioitua toimiva REXX-toteutus:
/* easter.rex from Scientific American, Mar 2001 p82 */ parse arg vuosi . if vuosi = '' then vuosi = left( date( 'S' ), 4 ) a = vuosi // 19 b = vuosi % 100 c = vuosi // 100 d = b % 4 e = b // 4 g = ( ( 8 * b ) + 13 ) % 25 h = ( ( 19 * a ) + b - d - g + 15 ) // 30 m = ( a + 11 * h ) % 319 j = c % 4 k = c // 4 l = ( ( 2 * e ) + ( 2 * j ) - k - h + m + 32 ) // 7 n = ( h - m + l + 90 ) % 25 p = ( h - m + l + n + 19 ) // 32 kuukausi. = 'VIRHE' kuukausi.3 = 'maaliskuu' kuukausi.4 = 'huhtikuu' say kuukausi.n right(p, 2)',' vuosi
Paitsi että, ilmeisesti olet saekoittanut jakolaskun ja jakojäännöksen? Käänsin PHP:lle nuo laskut, ja vastaukseksi sain -4.-8 (2014).
Tuktittuani linkkiäsi tein oman funktion.
function easter_butcher($year){ // 1 $a = $year % 19; // 2 $b = floor($year / 100); $c = $year % 100; // 3 $d = floor($b / 4); $e = $b % 4; // 4 $g = floor((8 * $b + 13) / 25); // 5 $h = (19 * $a + $b - $d - $g + 15) % 30; // 6 $m = floor(($a + 11 * $h) / 319); // 7 $j = floor($c / 4); $k = $c % 4; // 8 $l = (2 * $e + 2 * $j - $k - $h + $m + 32) % 7; // 9 Kuukausi $n = floor(($h - $m + $l + 90) / 25); // 10 Päivän nro $p = ($h - $m + $l + $n + 19) % 32 ; return $p .":". $n; }
Pentu kirjoitti:
Paitsi että, ilmeisesti olet sekoittanut jakolaskun ja jakojäännöksen?
En ole sekoittanut operaattoreita.
REXX-ohjelmointikielessä:
jakolasku: /
integer jakolasku: %
jakojäännös: //
Jakojäännöshän eroaa useimpien ohjelmointikielten modulo-operaattorista siten, että tulos voi olla negatiivinen.
Aiemmin antamani koodi on täysin toimiva.
Ahaa, okei. Anteeksi tästä perättömästä syytöksestä siis ;) Tota en tiennytkään. Mulla ei tuosta REXXistä ole mitään kokemusta.. Ehkäpä siihenkin voisi tutustua.
Aihe on jo aika vanha, joten et voi enää vastata siihen.