Samstag / Sonntag herausfiltern
Bernd
- php
Moin,
ich habe ein Start- und ein Enddatum. Jetzt möchte ich die Anzahl der Samstage und Sonntage herausfinden die in diesem Zeitraum vorkommen. Hat PHP dafür eine Funktion?
$start = "2018-01-01";
$ende = "2018-01-17";
In diesem Beispiel haben wir:
2x Samstag
2x Sonntag
Die Feiertage werden in einem anderen Schritt abgezogen, die spielen in diesem Beispiel keine Rolle.
Tach!
ich habe ein Start- und ein Enddatum. Jetzt möchte ich die Anzahl der Samstage und Sonntage herausfinden die in diesem Zeitraum vorkommen. Hat PHP dafür eine Funktion?
Nicht dass ich wüsste. Wäre aber auch zu speziell, dafür was eigenes zu haben.
Ist aber recht einfach umzusetzen. Iteriere über ein entsprechendes DatePeriod-Objekt, ermittle den Wochentag (Format: w), zähle wenn Sonnabend oder Sonntag.
Das kann man auch funktional lösen mit entsprechenden Array-Funktionen, die das DatePeriod-Objekt als Ausgangswert bekommen. Damit lassen sich auch recht elegant weitere Aufgabenstellungen lösen, wie eine Liste der Wochenendtage oder auch Arbeitstage zu filtern.
dedlfix.
Hallo dedlfix,
nein, nicht iterieren. Man muss folgende Größen bestimmen:
D bestimmt man am leichtesten, indem man $start und $ende in DateTime-Objekte überführt und die diff-Methode anwendet (alternativ die date_diff-Funktion). Das DateDifference-Objekt, das dabei herauskommt, hat eine Eigenschaft days.
W bekommt man vom DateTime-Objekt von $start über die format("w") Methode.
Grundwert der Anzahl Wochenend-Tage im Zeitintervall ist WE=2*Q. Dazu kommen 1 oder 2 Tage, je nach dem, ob am Intervallrand Wochenendtage hinzukommen. Dazu bildet man die Summe S von W und R.
Fall 1 und Fall 2 schließen sich gegenseitig aus; Fall 3 kann gleichzeitig mit Fall 1 auftreten.
Klingt kompliziert. Ist es aber nicht 😉. Die Fälle 1-3 musste ich mir allerdings auch mal irgendwann in eine Tabelle vor Augen führen, um festzustellen, dass die 49 möglichen Kombinationen aus Start- und Endetag letztlich auf 3 Prüfungen zurückführbar sind.
Rolf
Hallo,
leider verstehe ich nicht so recht was ihr meint bzw. wie ich es umsetzten soll. Meine Ansatz ist:
$startDate = new DateTime('2018-01-01');
$endDate = new DateTime('2018-01-18');
$diff = $startDate->diff($endDate);
echo $diff->days+1; //18
Warum ist eine +1 Nutzen muss weiß ich nicht. Ohne diese bekomme ich nur 17 Tage.
$startDate = explode(".","01.01.2018");
$endDate = explode(".","18.01.2018");
$startDate= mktime(0,0,0,$startDate[1],$startDate[0],$startDate[2]);
$endDate = mktime(0,0,0,$endDate[1],$endDate[0],$endDate[2]);
setlocale(LC_TIME, "ge","de_DE");
while($startDate <= $endDate){
echo strftime("%A" , $startDate)."
";
$startDate += 3600*24;
}
die Ausgabe ergibt
Montag
Dienstag
Mittwoch
Donnerstag
Freitag
Samstag
Sonntag
Montag
Dienstag
Mittwoch
Donnerstag
Freitag
Samstag
Sonntag
Montag
Dienstag
Mittwoch
Donnerstag
Der 01.01.2018 war ein Montag und heute haben wir Donnerstag, daher stimmt die Ausgabe. Habe ich jetzt eine Möglichkeit zu wählen wie viele Samstage und wie viele Sonntage darin vorkommen? Dann könnte ich diese Zahlen von $diff->days+1 wieder abziehen.
Tach!
leider verstehe ich nicht so recht was ihr meint bzw. wie ich es umsetzten soll. Meine Ansatz ist:
$startDate = new DateTime('2018-01-01'); $endDate = new DateTime('2018-01-18'); $diff = $startDate->diff($endDate); echo $diff->days+1; //18
Warum ist eine +1 Nutzen muss weiß ich nicht. Ohne diese bekomme ich nur 17 Tage.
Die Differenz zwischen dem ersten (0 Uhr) und dem zweiten (0 Uhr) ist ein Tag, nicht zwei. Deshalb ist auch der 18. nicht 18 sondern 17 Tage vom ersten entfernt. Wenn du den 18 mit berücksichtigen möchtest, musst du dessen Ende nehmen, oder den Anfang vom nächsten Tag.
$startDate += 3600*24;
Und an Schalttagen? Rechne bei Tagesabständen nicht mit Sekunden, sondern lass die Mathematik vom System erledigen. strtotime() kann ganze Tage hinzufügen und macht das auch an Schalttagen richtig.
Du brauchst das auch nicht zu Fuß aufzusetzen, denn DatePeriod gibt dir bereits eine Liste mit dem gewünschten Interval zwischen Start und Ende.
Der 01.01.2018 war ein Montag und heute haben wir Donnerstag, daher stimmt die Ausgabe. Habe ich jetzt eine Möglichkeit zu wählen wie viele Samstage und wie viele Sonntage darin vorkommen?
Mein Vorschlag war nun, sie zu zählen, indem du die Liste durchläufst und wenn Wochenendtag ist, dann den Zähler um eins erhöhen. RolfBs Vorschlag beruht hingegen auf Mathematik. Ist etwas komplexer aufzusetzen und zu durchschauen, dafür ist es aber bei größeren Intervallen vermutlich deutlich schneller als eine Liste durchzulaufen.
dedlfix.
Moin,
Du brauchst das auch nicht zu Fuß aufzusetzen, denn DatePeriod gibt dir bereits eine Liste mit dem gewünschten Interval zwischen Start und Ende.
passt das so besser?
$begin = new DateTime( '2018-01-01' );
$end = new DateTime( '2018-01-18' );
$end = $end->modify( '+1 day' );
$diff = $begin->diff($end);
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
$i = 0;
foreach($daterange as $date){
echo $date->format("d.m.Y") . "<br>";
$i++;
}
echo "<br><br>";
echo $i . " Tage ";
Tach!
passt das so besser?
Sieht erstmal wie ein richtiger Weg aus. Aber du musst das i++ noch abhängig vom Wochentag machen. Soll ja nur am Wochenende zählen.
dedlfix.
Moin,
hab es etwas umgebaut, was sagst du dazu?
setlocale(LC_TIME, "ge","de_DE");
$begin = new DateTime( '2018-01-01' );
$end = new DateTime( '2018-01-18' );
$end = $end->modify( '+1 day' );
$diff = $begin->diff($end);
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
$i = 0;
foreach($daterange as $date){
echo $date->format("d.m.Y") . "<br>";
$zeit = strtotime($date->format("Y-m-d"));
$d = date("l", $zeit);
echo $d . "<br>";
if ($d != "Saturday" && $d != "Sunday" ) {
$i++;
}
}
echo "<br><br>";
die Ausgabe lautet
01.01.2018
Monday
02.01.2018
Tuesday
03.01.2018
Wednesday
04.01.2018
Thursday
05.01.2018
Friday
06.01.2018
Saturday
07.01.2018
Sunday
08.01.2018
Monday
09.01.2018
Tuesday
10.01.2018
Wednesday
11.01.2018
Thursday
12.01.2018
Friday
13.01.2018
Saturday
14.01.2018
Sunday
15.01.2018
Monday
16.01.2018
Tuesday
17.01.2018
Wednesday
18.01.2018
Thursday
14 Tage
Tach!
foreach($daterange as $date){ $zeit = strtotime($date->format("Y-m-d")); $d = date("l", $zeit);
Der (gekürzte) Teil ist etwas umständlich. Die format()-Methode liefert dir bereits den Wert, den date() für einen einfachen Timestamp liefert. $date->format("l")
liefert also direkt den Wochentagsnamen. Ich würde aber nicht den nehmen, sondern die Nummer mit w
(oder auch N
, je nach Vorliebe), die ist dann auch unabhängig von locale-Einstellungen.
dedlfix.
Hi,
$startDate += 3600*24;
Und an Schalttagen?
gilt das auch.
Kritisch sind nicht die Schalttage (29. Februar fast alle 4 Jahre), sondern die Tage mit Zeitumstellung oder mit Schaltsekunden.
cu,
Andreas a/k/a MudGuard
Tach!
Kritisch sind nicht die Schalttage (29. Februar fast alle 4 Jahre), sondern die Tage mit Zeitumstellung oder mit Schaltsekunden.
Die meinte ich auch. Aber die Schaltsekunden spielen keine Rolle, die gibts nicht im Unix-Timestamp, mit dem ja PHP rechnet.
dedlfix.
Hallo,
Schalttage und Schaltsekunden haben ja auch verschiedene Aufgaben und lösen unterschiedliche Probleme.
Schalttage gleichen Ungenauigkeiten in der Definition der Jahreslänge, also im Mapping von Sonnentagen auf die jeweilige Jahresdefinition, aus. Das Wann und Wie ist kalenderspezifisch.
Schaltsekunden gleichen Ungenauigkeiten in der Definition der Sekunde UND Rumpeln in der Erdumdrehung aus. Sie werden vom IERS nach Bedarf aufgerufen; zur Zeit ca alle 18 Monate. Ob das tatsächlich weltweit verwendet wird oder ob es Kulturen gibt, die hier ihre Spezialsuppe kochen, weiß ich nicht.
Rolf
Hi,
Schaltsekunden […] Ob das tatsächlich weltweit verwendet wird oder ob es Kulturen gibt, die hier ihre Spezialsuppe kochen, weiß ich nicht.
Ob man die dann Kulturen nennen kann, weiß ich nicht.
Oder dachtest Du an eher an sowas wie Bakterienkulturen?
cu,
Andreas a/k/a MudGuard
Hallo MudGuard,
Kritisch sind […] die Tage […] mit Schaltsekunden.
M.W. werden die nicht berücksichtigt, aber ich lass mich gern korrigieren.
Bis demnächst
Matthias