Christian Seiler: PHP-Abfrage für die jeweiligen Wochenenden

Beitrag lesen

Hallo Bene,

Ah, Datumsberechnung, mein Lieblingsthema. ;-)

Wie muss denn bitte die Abfrage aussehen, wenn ich NUR die Sachen angezeigt bekommen will, die an DIESEM Wochenende stattfinden (also praktisch WHERE datum = DIESES WOCHENENDE).

Ok, dann musst Du Dir zuerst überlegen, wie ist "dieses Wochenene" definiert? Ich gehe mal von folgender Definition aus (wenn Du das anders definierst, musst Du den Code natürlich entsprechend abwandeln):

  1. Das Wochenende besteht aus Samstag und Sonntag.
  2. Wenn Montag ist, dann ist das Wochenende in 6 Tagen gemeint, wenn Sonntag ist, dann befindet man sich gerade noch in dem Wochenende (d.h. keine Differenz).

Dann solltest Du wissen, dass es am einfachsten zu rechnen ist, wenn Du erst einmal das Ende des Wochenendes bestimmst, das Du betrachten willst, also den Sonntag, der auf den aktuellen Wochentag folgt.

Zuerst einmal: Den aktuellen Tag bekommst Du über die MySQL-Funktion CURDATE() heraus. SELECT CURDATE(); liefert Dir z.B. das aktuelle Datum.

Jetzt stellt sich die Frage: Wie finde ich den nächsten Sonntag?

a) Es gibt keine Funktion, die das direkt tut (zumindest kenne ich keine).
 b) Es lässt sich jedoch sehr einfach nachbauen.

Es gibt nämlich die Funktion DAYOFWEEK(), die den Wochentag zu einem Datum ausspuckt: 1 für Sonntag, 2 für Montag, ..., 6 für Samstag. Mit dieser Funktion lässt sich ganz einfach berechnen, wie viele Tage es noch bis zum _NÄCHSTEN_ Sonntag sind. Denn der nächste Sonntag wäre, wenn die Skala nicht immer wieder bei 1 anfangen würde, bei der Zahl 8. Wenn Du also 8 - DAYOFWEEK(CURDATE()) rechnest, erhälst Du die Anzahl an Tage bis zum NÄCHSTEN Sonntag.

Jetzt stellt sich das Problem, das ja - sollte der aktuelle Tag ein Sonntag sein - der Tag noch dazuzählen soll. Das bekommt man ganz einfach in den Griff: Per Modulo-Algebra. Wenn Du die Zahl einfach Modulo 7 (Anzahl Wochentage) rechnest, dann bekommst Du immer ein Ergebnis zwischen 0 (heute ist Sonntag) bis 6 (heute ist Montag, d.h. in 6 Tagen ist sonntag).

Folgende Tabelle veranschaulicht das ganze:

Tag            | DAYOFWEEK() | 8 - DAYOFWEEK() | (8 - DAYOFWEEK()) % 7
---------------+-------------+-----------------+------------------------
Montag         | 2           | 6               | 6
Dienstag       | 3           | 5               | 5
Mittwoch       | 4           | 4               | 4
Donnerstag     | 5           | 3               | 3
Freitag        | 6           | 2               | 2
Samstag        | 7           | 1               | 1
Sonntag        | 1           | 7               | 0

Jetzt weißt Du also, wie viele Tage es noch bis zum ENDE des Wochenendes sind. Jetzt möchtest Du aber das DATUM herausbekommen. Dafür bietet MySQL die Funktion DATE_ADD() an, die auf ein beliebiges Datum ein Intervall addieren kann. Wenn Du also das Datum des Sonntags herausbekommen willst, dann nimmst Du:

DATE_ADD(CURDATE(), INTERVAL (8 - DAYOFWEEK(CURDATE())) % 7 DAY)

Jetzt möchtest Du aber das Zeitfenster auf das Wochenende eingrenzen. Es fängt mit Samstag an und hört mit Sonntag auf.

Da Datumsfelder im Allgemeinen auch Zeit beinhalten (DATE nicht, aber z.B. DATETIME schon) willst Du nicht mit Zeitresten hantieren wollen (ein DATE wird in DATETIME umgewandelt, indem die Uhrzeit auf 00:00:00 gesetzt wird, d.h. Sonntag wird zu Sonntag 00:00:00, was dann als Bedingung relativ unbrauchbar wird). Daher willst Du nun alle Daten AB Samstag VOR Montag haben. Samstag bekommst Du, indem Du 1 Tag abziehst, Montag, indem Du 1 Tag addierst.

Ab Samstag:

datum >= DATE_ADD(CURDATE(), INTERVAL (8 - DAYOFWEEK(CURDATE())) % 7 - 1 DAY)

Vor Montag:

datum < DATE_ADD(CURDATE(), INTERVAL (8 - DAYOFWEEK(CURDATE())) % 7 + 1 DAY)

Zusammen:

SELECT  
  id,  
  datum,  
  uhrzeit,  
  titel,  
  text  
FROM  
  termine  
WHERE  
  datum >= DATE_ADD(CURDATE(), INTERVAL (8 - DAYOFWEEK(CURDATE())) % 7 - 1 DAY)  
AND  
  datum < DATE_ADD(CURDATE(), INTERVAL (8 - DAYOFWEEK(CURDATE())) % 7 + 1 DAY)  
ORDER BY  
  datum ASC;

Wenn das Wochenende bei Dir schon am Freitag anfängt, müsstest Du halt in der ersten Bedingung 2 Tage statt 1 Tag abziehen, oder eben:

Die Termine werden automatisch aus der DB gelöscht mit...

mysql_query("DELETE from termine WHERE datum < now()") OR die(mysql_error());

In dem Fall reicht Dir eine Anfrage "bis zu diesem Wochenende" aus, d.h. Du kannst den datum >= ... Teil weglassen. Dann ist es auch relativ egal, wann das Wochenende startet, denn alle Termine vor *jetzt* sind sowieso gelöscht.

Viele Grüße,
Christian