Rolf B: strtotime()

Beitrag lesen

problematische Seite

Hallo Helmut,

Robert ≠ Rolf 😉

Du kannst schlichtweg nicht mit der Additionsfunktion für PHP Datümer arbeiten. Die ist an dieser Stelle so spezifiziert, dass sie Dir auf die Füße fällt.

Die Frage, welches Datum "einen Monat vor dem 31.07.2023" liegt, ist aber auch nicht brauchbar zu beantworten. Den 31.06. gibt's nicht. Also nehmen wir den 30.06.? Tjaaa - damit wird die Operation "einen Monat zurück" aber nicht mehr korrekt invertierbar: Einen Monat zurück, einen Monat vor, einen Tag daneben?

Deshalb ist ein Bankmonat immer 30 Tage lang… Und Du musst das Problem selbst lösen.

Meine Lösung würde die YM-Arithmetik von der Druckdarstellung trennen.

// $currentdate = getDate();
$currentdate = [ "year" => 2023, "mon" => 7 ];
echo formatYM(addMonths($currentdate, -1)) . "\n";
echo formatYM(addMonths($currentdate, -2)) . "\n";

function addMonths($dateStruct, $offset) {
	$newMonth = $dateStruct["mon"] - 1 + $offset;   // Nullbasierend!
	$yearOffset = floor($newMonth / 12);
  return [
    'year' => $dateStruct['year'] + $yearOffset,
    'mon'  => $newMonth + 1 - 12*$yearOffset
  ];
}

function formatYM($dateStruct) {
	return sprintf("%04d%02d", $dateStruct['year'], $dateStruct['mon']);
}

Die addMonths-Funktion erwartet ein assozatives Array mit den Schlüsseln year und mon (und ggf weiteren) und gibt ein Array mit NUR diesen beidem Schlüsseln zurück. Aussagen über den Tag werden damit beseitigt, weil sie sowieso potenziell inkorrekt sind.

Sie zieht vom Monat erstmal 1 ab, bevor sie rechnet, weil Reste-Arithmetik besser 0-basierend funktioniert. $yearOffset ist der Überschuss an Jahren. floor() liefert für die Monatswerte 0-11 den Wert 0, bleibt also im Jahr. Für -12 bis -1 liefert es -1, für 12 bis 23 liefert es +1.

In der Rückgabe wird das Jahr um den $yearOffset korrigiert und von den Monaten das zwölffache des $yearOffset abgezogen. Damit kommen sie wieder in den Bereich 0-11. Ein "+1" macht das anfängliche -1 wieder rückgängig, so dass Du die Monatsnummer 1-basiert hast.

Die formatYM Funktion hat NUR die Aufgabe, ein assoziatives Array mit den Schlüsseln year und mon im Format YYYYMM zu formatieren.

Trennung der Zuständigkeiten nennt man das. Und seit PHP 7 hast Du für Funktionsaufrufe auch keine gravierenden Strafzeiten mehr.

Rolf

--
sumpsi - posui - obstruxi