Datumszeitraum von Datumszeitraum abziehen?

Webgau

Mitglied
Servus,

ich steh gerade auf dem Schlauch. Ich bastel gerade eine Mitgliederübersicht, hier will ich den Zeitraum der Mitgliedschaft ausrechnen, das ist soweit auch kein Problem. Allerdings kann ein Mitglied auch mehrfach seine Mitgliedschaft ruhen lassen, dann soll dieser Zeitraum von dem Gesamtzeitraum abgezogen werden.

Bsp:
Mitgliedschaft: 15.01.2000 bis 28.05.2024 == X Jahre und X Monate

davon war:
Ruhende Mitgliedschaft:
1. 15.05.2001 bis 15.03.2002
2. 21.03.2005 bis 01.01.2010
3. ....

Bisher verwende ich folgenden Code:

PHP:
// Start- und Enddatum festlegen
$start = new DateTime($startZeit);
$ende = $start->diff(new DateTime($endZeit));
$jahreRoh = $ende->format('%y');
$monateRoh = $ende->format('%m');

Hat jemand einen Tipp oder eine Idee wie ich die ruhenden Zeiten von der Gesamtzeit abziehen könnte?

Grüße
 
Für jeder Ruhezeit dieselbe berechung machen. Anschliessned von deinen Rohzahlen abziehen
 
Ich verstehe dein "X Jahre und X Monate" nicht
Was erwartest du für dein Beispiel? 24 Jahre und 4 Monate? oder 24 Jahre und 292 Monate?
 
Ausgabe soll z.B. sein 24 Jahre und 4 Monate. Diese Zeit will ich von der gesamten Mitgliedschaft abziehen. Habe es jetzt wie folgt gelöst, weiß aber nicht ob sich das so korrekt verhält, macht zumindest den Eindruck.

PHP:
while ($disp = $stmt->fetch()) {
        // Start- und Enddatum
        $start = new DateTime($disp["von"]);
        $ende = $start->diff(new DateTime($disp["bis"]));
        $jahreRoh += $ende->format('%y');
        $monateRoh += $ende->format('%m');

        if ($monateRoh > 12) {
            $jahreRoh += 1;
            $monateRoh -= 12;
        }
    }

    return $jahreRoh . " Jahre " . $monateRoh . " Monate ";
 
Hä?
wieso so umständlich?
Monateroh div 12 ergibt jahre
monateroh mod 12 ergibt die überhängenden monate

ob die Operatoren jetzt div und mod heissen, weiß ich nicht
div=ganzzahlig teilen
mod=modulo

rechne am besten die ganze zeit in (vollen? Aufgerundet?) Monaten

ausserdem ist $ende als variable schlecht gewählt
es soll die Differenz darstellen und nicht das enddatum
 
Aircode
PHP:
while ($disp = $stmt->fetch()) {
        // Start- und Enddatum
        $start = new DateTime($disp["von"]);
        $differenz = $start->diff(new DateTime($disp["bis"])); 
        $monateGesamt = $differenz->format('%m');
        $jahre = intdiv($monateGesamt,12);
        $monate = $monateGesamt % 12;
  
    }

    return $jahre . " Jahre " . $monate . " Monate ";

EDIT: Welches DBMS verwendest du? Weil falls MySQL/Maria, dann kannst du das unter Umständen sogar direkt aus dem SQL-Statement ziehen (siehe PERIOD_DIFF-Funktion von MySQL)

EDIT2: Wie ist dein Tabellenaufbau?
Ich geh mal von aus, dass die Zeiträume in einer separaten Tabelle stehen mit nem FremdSchlüssel auf das Mitglied
Ungetestet für MySQL
SQL:
SELECT
Mitglieds_ID,
SUM(PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM COALESCE(Bis, NOW())), EXTRACT(YEAR_MONTH FROM Von))) AS MONATE
FROM TABELLE
GROUP BY
Mitglieds_ID

Ungetester Versuch basierend auf MySQL.
Ich setzte eine Tabelle Mitglieder und eine (Detail-) Tabelle Zeiträume voraus, wobei Zeitraum "Von-Bis" einen aktiven Zeitraum beschreibt ("Bis" zu "Von" vom folgenden Satz ist Ruhezeit)
SQL:
SELECT DISTINCT
M.ID,
M.MitgliedsName,
(Z.MONATE DIV 12) AS Jahre,
(Z.MONATE MOD 12) AS Monate
FROM Mitglieder AS M
INNER JOIN /*Oder LEFT JOIN, wobei aber eigentlich INNER JOIN funktionieren sollte, da ein Mitglied min. einen Eintrag haben muss/bekommt, wenn er sich anmeldet */
(SELECT Mitglieds_ID,
SUM(PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM COALESCE(Bis, NOW())), EXTRACT(YEAR_MONTH FROM Von))) AS MONATE
FROM Zeiträume GROUP BY Mitglieds_ID) AS Z
ON Z.Mitglieds_ID=M.ID
ORDER BY M.MitgliedsName
 
Zuletzt bearbeitet:
Hey.

Ist jetzt nur eine spontane Idee, aber wäre es nicht einfacher das Datum einfach in Unix Timestamps umrechnen, voneinander abziehen und die übrig gebliebenen Sekunden einfach in das gewünschte Format umrechnen?

Viele Grüße
 
Hey.

Ist jetzt nur eine spontane Idee, aber wäre es nicht einfacher das Datum einfach in Unix Timestamps umrechnen, voneinander abziehen und die übrig gebliebenen Sekunden einfach in das gewünschte Format umrechnen?

Viele Grüße
Nicht wirklich, weil du dann Schaltjahre nicht berücksichtigen kannst
 
Und hier noch ne Lösung für SQLite, sofern immer "volle" Monate gelten sollen
Könnte unter Umständen mit anderen DBMS auch funktionieren (angepasst), sofern diese DBMS rekursive CTE's unterstützen. Der Trick ist auf den jeweils Monats-Ersten zu verschieben
SQL:
SELECT COUNT() AS DIFFMONTHS FROM (
WITH RECURSIVE cnt(FromDate, ToDate) AS
    (SELECT Date(FromDate,'start of month') As 'FromDate', coalesce(Date(ToDate,'start of month'),Date('Now','localtime','start of month')) As 'ToDate'
     FROM test
     UNION ALL
     SELECT Date(FromDate,'+1 months') As 'FromDate', coalesce(Date(ToDate,'start of month'),Date('Now','localtime','start of month')) As 'ToDate'
     FROM cnt
     WHERE Date(FromDate,'+1 months')<=coalesce(Date(ToDate,'start of month'),Date('Now','localtime','start of month'))
     )
SELECT Date(FromDate,'start of month') As 'FromDate', coalesce(Date(ToDate,'start of month'),Date('Now','localtime','start of month')) As 'ToDate' FROM cnt)

EDIT: Wenn man nur die vollen "vergangenen" Monate haben will, muss man in Zeile 8 das "<=" mit einem "<" ersetzen
Im Beispiel der "Mitgliedschaft" (in einem Verein?) oben, gelten nämlich der angebrochene Januar 2000 und der angebrochene Mai 2024 mit.
Mit meiner Abfrage erhält man nämlich 293 Monate, was 24 Jahren und 5 Monaten entspricht
ersetzt man das "<=" mit einem "<" erhält man 292 Monate, was 24 Jahren und 4 Monaten entspricht
Und die "echte" Differenz zwischen beiden Tagen ist 24 Jahre, 4 Monate und 13 Tage.
Ist jetzt die Frage, was für den OP richtig ist
 
Zuletzt bearbeitet:
Zurück