Zum Inhalt springen

Anzeige alle Geburtstage in den nächsten n Tagen ...


-Snackers-

Empfohlene Beiträge

Hallo zusammen.

Da ich immer alle Geburtstage vergesse und eine Aversion gegen den Gebrauch von umständlicher Kalendersoftware habe, habe ich mir überlegt, eine Online Lösung mit PHP / MYSQL zu basteln, die mich ggf. einige Tage vorher per Mail erinnert, das jemand meiner Kontakte Geburtstag hat.

Meine Geburtstage sind als DATE in der DB gespeichert mit dem realen Geburtsjahr (Bsp.: 1965-02-23), jetzt würde ich mir gerne alle Geburtstage der nächsten 7 Tage selecten. Mit nem Unix-Timestamp habe ich es versucht, da werden allerdings die Geburtstage vor dem Jahr 1970 natürlich nicht berücksichtigt. Eine weitere Problematik sind Monats- und Jahreswechsel. Wenn zum Beispiel jemand am 01.01.2006 Geburtstag hat und wir haben aktuell den 31.12.2005, dann wird je nach Implementation der 01.01.2006 nicht als Geburtstag der nächsten 7 Tage aufgeführt.

Bei meinem Problem sind ja in erster Linie nur die Monate und Tage des Datums interessant. Ich habe unterschiedliche Versuche mit der DATE_FORMAT - Funktion probiert, die allerdings kein DATE-Format zurückgibt und somit eine weitere Datumsberechnung nicht möglich macht.

Ferner sehe ich die Möglichkeit, die jeweiligen Monate und Tage als PHP-Variablen zu speichern und die weitere Berechnung PHP zu überlassen, aber aufgrund des Overheads, der dabei entsteht und der Fülle an Zeit- und Datums-Funktionen, die MYSQL liefert, sehne ich mich natürlich nach einer Lösung rein auf MYSQL-Ebene ...

Ich würde mich daher sehr freuen, wenn sich einige von Euch die Zeit nehmen könnten, mal über mein Problem nachzudenken und jegliche Idee, jeden Tipp oder jedes Beispiel, das mir auf die Sprünge helfen könnte, zu posten. Vielleicht stehe ich auch einfach nur total auf den schlauch, aber an diesem Problem beisse ich mir jetzt schon etwas länger die Zähne aus. Auch Google, Mysql-Referenz und andere Quellen geben leider nicht viel her (Oder ich muss noch mal nen Suchmaschinen-Crashkurs besuchen :eek )

Vielen Dank im Voraus für jegliche Hilfe

Gruß

-snack-

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich denke das hilft Dir weiter:

MySQL Referenz ADDDATE()

 


SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);


Als erstes Argument das heutige Datum mit CURRDATE() auslesen und im 2. Argument aus der 31 ne 7 gemacht.

Ist das nicht vieleicht einwenig unglücklich mit php gelöst? Ich mein jeden Tag auf diese Website gehen damit der überhaupt Mal das Statement ausführt?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ist das nicht vieleicht einwenig unglücklich mit php gelöst? Ich mein jeden Tag auf diese Website gehen damit der überhaupt Mal das Statement ausführt?

och php ist eine ganz normale scriptsprache, wie perl und ähnliches. Ein php-script lässt sich also auch mit einer passenden SheBang-Zeile unter Linux einfach ausführen. Der cron macht dann den Rest. Auch unter Windows ist das natürlich kein Problem, hier fällt dann halt die SheBang-Zeile, obwohl ein Konstrukt der Art "#!d:\programme\perl\perl.exe" auch mal witzig wär. Dann muss man halt dem Taskeintrag noch den Interpreter mit unterjubeln.

Das php eigentlich für die dynamische Webseitengestaltung entstanden ist und auch hauptsächlich nur dafür benutzt wird ist dabei erstmal egal ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich denke das hilft Dir weiter:

MySQL Referenz ADDDATE()

 


SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);


Als erstes Argument das heutige Datum mit CURRDATE() auslesen und im 2. Argument aus der 31 ne 7 gemacht.

Ist das nicht vieleicht einwenig unglücklich mit php gelöst? Ich mein jeden Tag auf diese Website gehen damit der überhaupt Mal das Statement ausführt?

Danke, für Deine Antwort, aber das ist es nicht. Vllt hab ich mich auch nicht genau genug ausgedrückt.

Nehmen wir an ich hab eine Tabelle mit Personennamen und Geburtstagen ... in etwa so:

Aktuelles Datum ist der 05.10.2005 (2005-10-05)

+-----------+--------------------+

|Person |Geb |

+-----------+--------------------+

|Hans |1965-05-23 |

|Willi |1981-10-10 |

|Richard |1975-02-12 |

|Klaus | 1983-06-05 |

+-----------+--------------------+

Demnach hätte also lediglich Willi in den nächsten 7 Tagen Geburtstag ...

Mir bringt jetzt die ADDDATE-Funktion mit dem aktuellen Datum + 7 Tage nichts, da ein Vergleich zwischen diesem und einem der Geburtstage in der Tabelle aufgrund der Jahreszahlen immer etwas ergeben würde, was nicht gewünscht ist.

Bsp:

Wenn ich Willis Geburtstag (1981-10-10) mit dem angenommenen aktuellen Datum (2005-10-05) vergleichen würde, dann käme ich zu einer Differenz von 24 Jahren und 5 Tagen. Ich benötige jedoch nur die Differenz von 5 Tagen und das am besten mit berücksichtigtem Jahres- und Monatswechsel.

Gruß

snack

Link zu diesem Kommentar
Auf anderen Seiten teilen

wie wäre es mit etwas in der Art:

Du berechnest den Tag im Jahr ungefähr so:


$monate = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31);

if ( (($aktjahr%4 == 0) and ($aktjahr%100 != 0)) or ($aktjahr%400 == 0)) {
//Schaltjahr
$monate[1] = 29;
}

for ($i=0; $i<$aktmonat-1; $i++) {
$dayofyear += $monate[$i];
}
$dayofyear += $akttag;
[/PHP]

dann vergleichst du beide Daten.

Wenn nun die Differenz

$tag_im_jahr_des_geburtstages - $tag_im_jahr_des_aktuellen_tages

entweder kleiner als 8 oder kleiner als -358 oder -359 (jenachdem ob das aktuelle jahr ein schaltjahr ist oder nicht)

dann hat die betreffenden person in den nächsten sieben Tagen Geburtstag

Link zu diesem Kommentar
Auf anderen Seiten teilen

achja nochwas:

Du speicherst das Geburtsdatum als String in der Form 2005-12-06?

Warum nicht für Jahr, Monat und Tag ein einzelnes Feld nehmen. Dann brauchst du nachher keinen String zerstückeln.

Negativ.

Nicht als String sondern als DATE --> ist ein MYSQL-Datentyp.

Die Aufteilung des Datums in seine atomaren Bestandteile habe ich auch schon überlegt, würde ich aber nur ungern machen, weil mir das "unsauber" erscheint. Suche halt nach einer Lösung, es mit dem DATE-Datentyp zu machen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

wie wäre es mit etwas in der Art:

Du berechnest den Tag im Jahr ungefähr so:


$monate = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31);

if ( (($aktjahr%4 == 0) and ($aktjahr%100 != 0)) or ($aktjahr%400 == 0)) {
//Schaltjahr
$monate[1] = 29;
}

for ($i=0; $i<$aktmonat-1; $i++) {
$dayofyear += $monate[$i];
}
$dayofyear += $akttag;
[/PHP]

dann vergleichst du beide Daten.

Wenn nun die Differenz

$tag_im_jahr_des_geburtstages - $tag_im_jahr_des_aktuellen_tages

entweder kleiner als 8 oder kleiner als -358 oder -359 (jenachdem ob das aktuelle jahr ein schaltjahr ist oder nicht)

dann hat die betreffenden person in den nächsten sieben Tagen Geburtstag

Das hört sich allerdings eigentlich ganz gut an. Werde es gegen Mittag mal ausprobieren und melde mich dann nochmal.

Vielen Dank :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mach es doch viel einfach so:


SELECT * FROM Personen P WHERE DAYOFYEAR(GebTag) BETWEEN

 DAYOFYEAR(CURRENT_DATE) AND DAYOFYEAR(CURRENT_DATE+7)

DAYOFYEAR liefert den Tag innerhalb eines Jahres zurück also eine Zahl zw. 1 und 366.

Ey, WOW, auch ein fettes THX an Dich! Das funktioniert auch. Und produziert nebenbei nicht so viel Overhead wie meine jetztige Implementierung!

Ich bin beeindruckt.

Wie gesagt, ich schau mal, wie das mit dem Jahreswechsel ist...bis gleich

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie gesagt, ich schau mal, wie das mit dem Jahreswechsel ist...

Der Jahreswechsel ist ein Problem... mit der Lösung geht es aber:


SELECT * FROM Personen WHERE

DATEDIFF(CURRENT_DATE+7, 

MAKEDATE(YEAR(CURRENT_DATE), DAYOFYEAR(GebTag))) 

BETWEEN 0 AND 7

Erklärung: Zuerst einmal wird der Geb.Tag ins aktuelle Jahr verlegt(MAKEDATE) und dann die Differenz von heute + 7 Tage und dem Geb.Tag gebildet. Alles was zw. 0 und 7 ist, ist ein korrektes Ergebnis.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Jahreswechsel ist ein Problem... mit der Lösung geht es aber:


SELECT * FROM Personen WHERE

DATEDIFF(CURRENT_DATE+7, 

MAKEDATE(YEAR(CURRENT_DATE), DAYOFYEAR(GebTag))) 

BETWEEN 0 AND 7

Erklärung: Zuerst einmal wird der Geb.Tag ins aktuelle Jahr verlegt(MAKEDATE) und dann die Differenz von heute + 7 Tage und dem Geb.Tag gebildet. Alles was zw. 0 und 7 ist, ist ein korrektes Ergebnis.

Sorry, aber ich muss leider mit MYSQL 4.0.25 vorliebnehmen.

In der Version gibt es DATEDIFF und MAKEDATE leider noch nicht. :(:(:(

Ich habe meinen Provider schon deswegen terrorisiert, aber die haben bis jetzt immer noch nicht geupt :(:(:(

Aber auf jeden Fall trotzdem vielen Dank. Woher kennst Dich denn mit sql so aus? Wenn ich fragen darf?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sorry, aber ich muss leider mit MYSQL 4.0.25 vorliebnehmen.

In der Version gibt es DATEDIFF und MAKEDATE leider noch nicht. :(:(:(

Ich habe meinen Provider schon deswegen terrorisiert, aber die haben bis jetzt immer noch nicht geupt :(:(:(

hehe, da kann ich den provider aber irgendwie verstehen, denn meines wissen ist grade im timestamp-bereich irgendeine Änderung in 4.1 gewesen, die so ziemlich jedes Script aus den Angeln hebt. Was meinst du, wie die Kunden ihn dann terrorisieren würden.

Da würde ich an der Stelle des Providers auch gleich auf MySQL 5 warten :D

Woher kennst Dich denn mit sql so aus? Wenn ich fragen darf?

Das würd mich auch interessieren. Hast du eventuell gute Empfehlungen aus dem Bereich Bücher und ähnliches, oder hast du dir das MySQL Manual mal von vorn bis hinten durchgelesen, oder einfach nur jeden Tag damit zu tun?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi,

schau wie alt er heute ist und wie alt in 7 Tage, unterscheidet sich das Alter hatte er Geburtstag.


select name from person where FLOOR((to_days(NOW()) - to_days(gebdate))/365.25) <> 

FLOOR((to_days(date_add(now(), INTERVAL 7 day)) - to_days(gebdate))/365.25)

Gruß Jaraz

Das Alter berechnen ist so nicht exakt. (Schaltjahre, 1900 und 2000 Wechsel)

Kannste mal hier schauen: http://dev.mysql.com/doc/mysql/en/date-calculations.html

Link zu diesem Kommentar
Auf anderen Seiten teilen

hehe, da kann ich den provider aber irgendwie verstehen, denn meines wissen ist grade im timestamp-bereich irgendeine Änderung in 4.1 gewesen, die so ziemlich jedes Script aus den Angeln hebt. Was meinst du, wie die Kunden ihn dann terrorisieren würden.

Da würde ich an der Stelle des Providers auch gleich auf MySQL 5 warten :D

Sicher, wenn sich schon zig Kunden auf den Servern tummeln, dann ist das sicher nicht mal eben so gemacht. Hab ich ja auch Verständnis für. (Auch wenn mir am Telefon drei sehr kompetente Mitarbeiter bestätigt haben, dass das Trouble Ticket unterwegs ist und ich mein Update innerhalb einer Woche bekomme ... :uli Da war ich dann echt mal gespannt... *gg*)

Hi,

schau wie alt er heute ist und wie alt in 7 Tage, unterscheidet sich das Alter hatte er Geburtstag.


select name from person where FLOOR((to_days(NOW()) - to_days(gebdate))/365.25) <> 

FLOOR((to_days(date_add(now(), INTERVAL 7 day)) - to_days(gebdate))/365.25)

Gruß Jaraz

Hi Jaraz,

Danke für Deine Antwort, aber die versteh ich leider überhaupt nicht :( Sorry.

Was gibt denn " to_days(gebdate))/365.25" zurück? Warum teilt man das Geburtsdatum in Tagen durch 365.25?

Hilft das vielleicht dabei, dass ich ja eigentlich to_days(gebdatum) nicht mit to_days(curdate()) vergleichen kann ?? Schließlich ist zum Beispiel to_days(1981-09-28) ein viel zu niedriger Wert, den ich nicht mit to_days(2005-10-05) vergleichen kann.

Es wäre super, wenn Du Deinen Vorschlag etwas mehr erläutern könntest, Danke.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also, da ich leider nicht die schöne Abfrage von Jesterday nutzen kann, habe ich jetzt was mit bmg4evers Vorschlag gebastelt. Für alle, die es interessiert, hier der Schnipsel ...

<schnipp>

//Geburtstage in den nächsten 7 Tagen holen	
$months = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31);
$dayOfCurrentYear=0;
$birthdayIds = array();

//Auf Schaltjahre überprüfen
if ( ((date("Y")%4 == 0) and (date("Y")%100 != 0)) or (date("Y")%400 == 0)) {
$months[1] = 29;
}

//Aktuellen Tag des Jahres berechnen
for ($i=0; $i < date("n")-1; $i++) {
$dayOfCurrentYear += $months[$i];
}
$dayOfCurrentYear += date("d");

/*SQL-Abfrage, um den Monats- und den Tag-Teil eines jeden Eintrages aus meiner Tabelle zu holen,
das Ergebnis ist eine Tabelle mit 3 Spalten. id des Datensatzes, numerische Angabe des Monats und
numerische Angabe des Tages vom Monat*/
$sqlGetAllBirthdays = "
SELECT id, DATE_FORMAT(geburtsdatum, '%m') AS monat, DATE_FORMAT(geburtsdatum, '%d') AS tag
FROM _spieler_senioren
WHERE 1;";
$getAllBirthdays = mysql_query($sqlGetAllBirthdays);


while ($allBirthdays = mysql_fetch_array($getAllBirthdays)) {
//Da ich auch noch Datensätze mit leeren Geburtsdaten habe, muss ich diese ausschließen
if ($allBirthdays[monat] != NULL && $allBirthdays[monat] != '00') {
$birthdayMonth = $allBirthdays[monat];
$birthdayDay = $allBirthdays[tag];
$dayOfBirthyear = 0;
//Geburtstag-Tag des Jahres berechnen
for ($j = 0; $j < $birthdayMonth-1; $j++) {
$dayOfBirthyear += $months[$j];
}
$dayOfBirthyear += $birthdayDay;

/*Berechnung der Differenz, ist sie kleiner als 7 oder kleiner als -358 (das ist sie im fall, wenn der geburtstag z.Bsp. am 1.1.2006 ist
und wir aktuell den 25.12.2005 haben, der Jahreswechsel wird also mit berücksichtigt , dann wird die id in ein Array gestopft.
Diese id´s sind dann mein Schlüssel zu den gefragten Datensätzen.*/
if ((($dayOfBirthyear - $dayOfCurrentYear) >= 0 && ($dayOfBirthyear - $dayOfCurrentYear) <= 7) || ($dayOfBirthyear - $dayOfCurrentYear) < -358) {
array_push($birthdayIds, $allBirthdays[id]);
//echo 'id:'.$allBirthdays[id].'<br/>';
}
}
}[/PHP]

Ich weiss, sieht alles total hässlich und unschön aus. Aber so ist PHP nunmal ... "poor hackers perl" eben ;)

Wer sich das ganze anschauen will, kann es auf meiner Testseite sv-bergheim.de/test einsehen.

Gruß

-Snack-

Link zu diesem Kommentar
Auf anderen Seiten teilen

Woher kennst Dich denn mit sql so aus? Wenn ich fragen darf?

Das würd mich auch interessieren. Hast du eventuell gute Empfehlungen aus dem Bereich Bücher und ähnliches, oder hast du dir das MySQL Manual mal von vorn bis hinten durchgelesen, oder einfach nur jeden Tag damit zu tun?

Einfach nur an der richtigen Stelle gesucht ;)

http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html

Dann etwas überlegt, wie man das hinbekommt und nochmal gesucht (s.o.), dann ein bisschen probiert et voilà. Und natürlich schon ab und zu mit SQL zu tun ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi Jaraz,

Danke für Deine Antwort, aber die versteh ich leider überhaupt nicht :( Sorry.

Was gibt denn " to_days(gebdate))/365.25" zurück? Warum teilt man das Geburtsdatum in Tagen durch 365.25?

Hilft das vielleicht dabei, dass ich ja eigentlich to_days(gebdatum) nicht mit to_days(curdate()) vergleichen kann ?? Schließlich ist zum Beispiel to_days(1981-09-28) ein viel zu niedriger Wert, den ich nicht mit to_days(2005-10-05) vergleichen kann.

Es wäre super, wenn Du Deinen Vorschlag etwas mehr erläutern könntest, Danke.

Wie gesagt der Ansatz war nicht Schaltjahr sicher.

So ist es richtig:

-----------------

select name from person where

(YEAR(CURDATE())-YEAR(geb)) - (RIGHT(CURDATE(),5)<RIGHT(geb,5))

<>

(YEAR(date_add(CURDATE(), INTERVAL 7 day))-YEAR(geb)) - (RIGHT(date_add(CURDATE(), INTERVAL 7 day),5)<RIGHT(geb,5))

-----------------

Erklärung:

YEAR(CURDATE())-YEAR(geb) = Jahresdifferenz heutiges Datum - Geb Datum

(RIGHT(CURDATE(),5)<RIGHT(geb,5) = wenn (MM-DD heute < MM-DD Geb Datum) ist der Ausdruck 1 ansonsten 0, d.h. ziehe ein Jahr ab, wenn die Person im aktuellen Jahr noch keinen Geb hatte.

Also liefert dir der Ausdruck:

(YEAR(CURDATE())-YEAR(geb)) - (RIGHT(CURDATE(),5)<RIGHT(geb,5))

das aktuelle Alter der Person

Das ganze nun auch für 7 Tage später ausrechnen:

(YEAR(date_add(CURDATE(), INTERVAL 7 day))-YEAR(geb)) - (RIGHT(date_add(CURDATE(), INTERVAL 7 day),5)<RIGHT(geb,5))

so, sind diese beiden Jahres Werte ungleich (deswegen das <>)

Hat die Person innerhalb der nächsten 7 Tage Geburtstag.

Gruß Jaraz

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 5 Wochen später...

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...