Registrierung Kalender Mitgliederliste Teammitglieder Suche Häufig gestellte Fragen Zur Startseite

Informatiker Board » Themengebiete » Praktische Informatik » Algorithmen » Datumsberechnung » Hallo Gast [Anmelden|Registrieren]
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | An Freund senden | Thema zu Favoriten hinzufügen
Neues Thema erstellen Antwort erstellen
Zum Ende der Seite springen Datumsberechnung
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
c.i.b.magic
unregistriert
Datumsberechnung Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Hallo Community,

dieser Algorithmus verfolgt mich seit Jahren, meine derzeitige Lösung funktioniert zwar, aber nicht in allen Fällen. Und das macht mich alle.
Jetzt schreibe ich die Applikation neu, und jetzt hätte ich gerne eine 100%-logische Lösung.

Ich entwickle jetzt in PHP, es geht mir aber nicht um eine PHP-Lösung (wäre natürlich toll) sondern um eine, alle Nebenbedingungen abdeckende, Lösung.

Hier die Problematik:
Gegeben ist ein Bestellformular, auf dem der User auswählen kann, zu welchem Datum er die Lieferung erhalten möchte. Dabei soll der User die Wahl aus unterschiedlichen, gültigen (!!!!) Lieferdaten haben

Folgende Nebenbedingungen bestehen:
1. Das Datum der Bestellung = heute()
2. Die möglichen Liefer-WOCHENTAGE, die der Lieferant frei wählen kann
2.1 Der Lieferant kann zwischen 1 und n Liefertagen wählen (n=Tmax=5)
2.2 Die Liefertage liegen zwischen Montag und Freitag
3. Der Lieferant kann frei wählen, wie viele Tage zwischen Bestellung und frühestem Liefertag liegen müssen (0 bis n) [Vorlauftage]
4. Wochenenden (Sa+So) verlängern, aber nur bei Überschneidung, die Frist der Vorlauftage
5. Ist die Summe der Vorlauftage<dem frühestmöglichen Liefertag, muss sich dieser auf den nächstmöglichen (erlaubten) Liefertag ändern
6. Entgegen der erlaubten Liefertage des Lieferanten, kann ein User an allen 7 Tagen der Woche bestellen

Die Problematik besteht vor allem in der Wahl der Anzahl der Wochentage (Lieferant A liefert nur Dienstags - B Montag, Mittwoch und Freitag - C an jedem Werktag).

Die "einfache" Berechnung bekomme ich problemlos hin - aufgeben muss ich leider bei der Berücksichtigung der Vorlauftage PLUS Wochenendberechnung.

Beispiel:
Der Lieferant liefert nur Donnerstag, braucht zwei Tage Vorlaufzeit.
a) Ein User bestellt Montags
=> Montag+2 Tage Vorlauf = Mittwoch < Donnerstag => der KOMMENDE Donnerstag ist der erste gültige Liefertag; weitere Liefertage sind dann DO eine Woche später usw.
b) Ein User bestellt Mittwoch
=> Mittwoch+2 Tage Vorlauf = Freitag > Donnerstag => der Donnerstag DER NÄCHSTEN WOCHE ist der erste gültige Liefertermin; weitere ....
c) Ein User bestellt Freitag
=> Freitag+2 Tage Vorlauf = Sonntag (ups, Wochenende)
[US-Software] Sonntag<Freitag - *grr* [krieg ich aber hin]
In diesem Fall nicht schlimm, weil nach wie vor b) gilt

Der Lieferant liefert nur Montag, 2 Tage Vorlaufzeit
a) Problemlos, wenn der User bis Donnerstag bestellt, aber :
b) Der User bestellt Fr(Sa/So)
=> Freitag+2 Vorlauftage = Sonntag(ungültig !!!) => Montag; Montag ist ein gültiger Liefertag, aber da zwei WochenENDtage dazwischen liegen, ist die Vorlaufzeit nicht gegeben => frühester Liefertag Montag eine Woche später

Das ganze wird halt noch spannender, wenn es mehrere Wochentage zur Lieferung gibt - und vor allem (!!) - wenn die Vorlaufzeit so hoch gewählt wird, das gleich mehrere Wochenenden überschnitten werden (könnten) [Bspw. VLZ=10].

---

Ich hasse Datum !!! :o)
Es wäre richtig toll, wenn sich der eine oder andere von Euch an dieses Konstrukt wagen würden (ich hoffe, ihr flucht dabei nicht so, wie ich es derzeit tue).

Wäre auf jeden Fall klasse, eine Antwort zu bekommen!!!

Danke
Stephan
20.09.2019 20:58
ed209
Routinier


Dabei seit: 07.09.2006
Beiträge: 324

Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Zwei Fragen:

1.) Was ist der Unterschied zwischen Vorlauftagen und Liefertagen?
2.) Verhalten sich Feiertage wie Wochenenden?

EDIT: Waehrend wir warten kann ich ja mal auf das was ich als das Kernproblem sehe eingehen:

Zitat:

3. Der Lieferant kann frei wählen, wie viele Tage zwischen Bestellung und frühestem Liefertag liegen müssen (0 bis n) [Vorlauftage]
4. Wochenenden (Sa+So) verlängern, aber nur bei Überschneidung, die Frist der Vorlauftage


Diese Formulierung ist etwas umstaendlich und lenkt dich ein bisschen in eine falsche Richtung:

Zitat:

=> Freitag+2 Vorlauftage = Sonntag(ungültig !!!) => Montag; Montag ist ein gültiger Liefertag, aber da zwei WochenENDtage dazwischen liegen

Es sieht so aus als wuerdest du die Kalendartage hochzaehlen und dann die Wochenendtage runterzaehlen. Viel einfacher waere es wenn du einfach die Werktage hochzaehlst.

Zitat:

3. Der Lieferant kann frei wählen, wie viele Werktage zwischen Bestellung und frühestem Liefertag liegen müssen (0 bis n) [Vorlauftage]


Hier mal etwa Pseudocode:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
berechne_ersten_tag_mit_genug_vorlaufzeit(heute, vorlauftage):
    tage = 0 
    naechster_tag = heute
    while tage < vorlauftage:
        naechster_tag = naechster_tag + 1
        if (naechster_tag ist ein werktag):
           tage = tage + 1
    return naechster_tag


Gruss,
ED

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ed209: 22.09.2019 10:06.

22.09.2019 09:49 ed209 ist offline E-Mail an ed209 senden Beiträge von ed209 suchen Nehmen Sie ed209 in Ihre Freundesliste auf
c.i.b.magic
unregistriert
Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Hi ED,

danke das Du dich meldest !

Zitat:
Original von ed209
Zwei Fragen:

1.) Was ist der Unterschied zwischen Vorlauftagen und Liefertagen?
2.) Verhalten sich Feiertage wie Wochenenden?


Also, als Liefertag meine ich den WOCHENtag, also Montag, Dienstag usw.
Wie beschrieben kann ein Lieferant 1 bis n=5 Liefertage haben.

Die Vorlauftage sind die Tage, die zwischen Bestellung und frühest möglichen Liefertag liegen müssen (also die Zeit, die der Lieferant zur Kommissionierung der bestellten Artikel benötigt)

Die Wochenenden zählen nicht mit, da die Lieferanten an diesen Tagen nicht arbeiten. Daher zählen sie auch nicht mit in die Vorlauftage, da am Wochenende nicht kommissioniert werden kann. (Feiertage ebenfalls, aber die ignoriere ich zunächst, obwohl ich mir die auch aus eines DB ziehen könnte).

Dein Code ist zunächst verständlich, aber wenn ich nur die Werktage zähle, wie komme ich dann auf ein gültiges Datum. Erhalte ich 5 Tage zurück, aber ein WE liegt dazwischen, kann ich nicht heute()+Tage addieren

hmm, allerdings könnte man die Wochenenden mitzählen und mal 2 rechnen
... ist eine Überlegung wert.

Danke nochmals, wenn Du weitere Ideen hast, immer her damit :-)

Stephan
22.09.2019 14:43
c.i.b.magic
unregistriert
Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Ergänzung :

außerdem berücksichtigt dein Codeschnipsel folgendes nicht :

Was ist, wenn der berechnete Zieltag kein gültiger Liefertag ist -> dann müsste bis zum nächst möglichen Liefertag weitergerechnet werden.
Und: angenommen, der berechnete Zieltag wäre ein Dienstag, der Lieferant liefert aber nur Montags - dann müsste weiter berechnet werden, wobei wiederum ein WE dazwischen liegt.
22.09.2019 14:50
NixJava
unregistriert
Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Straightforward würde ich es so lösen:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
bestelldatum := date(now);
temp_lieferdatum := bestelldatum + vorlauftage;

/* temp_lieferdatum ist der frühstmögliche Liefertermin unter
Berücksichtigung der Vorlauftage, aber ohne Berücksichtigung
der Wochenenden bzw. Feiertage. */


/* Im Folgenden werden die Wochenenden und Feiertage berücksichtigt. */

For Each tag In (bestelldatum, temp_lieferdatum) {
  if (tag.get_wochentag() == 'SA' oder 'SO' oder Feiertag) {
    temp_lieferdatum++;
  }
  /* Wichtig ist, dass die Schleifengrenze (temp_lieferdatum)
  dynamisch angepasst wird. */
}

/* Der frühstmögliche Liefertermin unter Berücksichtigung der Vorlaufzeit samt 
Wochenenden wurde ermittelt. Jetzt noch den nächsten legalen Liefertag berechnen. */

while (temp_lieferdatum.get_wochentag() != liefertag) {
  temp_lieferdatum++;
}

lieferdatum := temp_lieferdatum;
22.09.2019 16:32
as_string as_string ist männlich
Haudegen


Dabei seit: 06.11.2013
Beiträge: 607
Herkunft: Heidelberg

Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Warum so kompliziert mit temp_lieferdatum und dann ein dynamisch anpassendes Schleifenende?
Einfach einen Zähler mit den Vorlauftagen initialisieren. Dann eine while-Schleife, die ab heute los läuft und so lange checkt, ob die Tage gültige Werktage sind und den Zähler runter zählt, bis ausreichend gültige Vorlauf-Werktage gefunden sind.
Ab hier dann wieder Suche nach dem nächsten gültigen Liefertag. Das könnte man auch sequenziell Tag für Tag machen, oder man überlegt sich hier was von wegen: Wochentage Montag bis Freitag in einer Reihe Zahlen vergeben, wenn kein höherer Liefertag (in dieser Woche) findbar, nimm ersten Liefertag in der nächsten Woche.

Die Frage ist nur, ob man es irgendwie optimieren könnte, so dass man die Schleife über die Vorlaufzeit nicht bräuchte. Aber was soll man da bitte groß gewinnen können? Das werden ja nicht so häufig mehr als 5 Tage Vorlaufzeit sein und selbst ein paar Hundert hätte ein Rechner ziemlich schnell abgearbeitet. Letztlich muss man sich ja doch jeden einzelnen Tag anschauen, besonders wenn man auch Feiertage berücksichtigen muss.

Gruß
Marco
25.09.2019 13:42 as_string ist offline E-Mail an as_string senden Beiträge von as_string suchen Nehmen Sie as_string in Ihre Freundesliste auf
c.i.b.magic
unregistriert
Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Danke !!!! Ich hab's !
Kann mich erst jetzt melden, da ich krank war. Der Post von as_string hat mir endlich die Augen geöffnet.

Hier meine Lösung (ist PHP-Syntax, ich hoffe Ihr kommt damit klar - ansonsten bei Interesse fragen)

php:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
// Variablen die an anderer Stelle deklariert werden
// $feiertage = ein Array von Datum in der Form YYYY-MM-DD
// $ausgabetage = ein Array der Wochen-Liefertage des Lieferanten in der Form von 0 bis 6
// $whvorlauf = die Anzahl der Vorlauftage als Int

    $tage=0;
    $tempdat=new DateTime('NOW');
    $wochenende=array(0,6);
    while($tage<$whvorlauf) {
      $str="1 day";
      date_modify($tempdat,$str);
      $tagderwoche=date_format($tempdat,'w');
      $tagesdatum=date_format($tempdat,'Y-m-d');
      if(in_array($tagderwoche,$wochenende) || in_array($tagesdatum,$feiertage)) $whvorlauf++;
      $tage++;
    }
    while(!in_array(date_format($tempdat,'w'),$ausgabetage) || in_array(date_format($tempdat,'Y-m-d'),$feiertage)) {
      $str="1 day";
      date_modify($tempdat,$str);
    }
    $fruehest=date_format($tempdat,'d.m.Y');


Vielen Dank an alle, die sich für mich bemüht haben !!!
Stephan
25.09.2019 17:58
as_string as_string ist männlich
Haudegen


Dabei seit: 06.11.2013
Beiträge: 607
Herkunft: Heidelberg

Auf diesen Beitrag antworten Zitatantwort auf diesen Beitrag erstellen Diesen Beitrag editieren/löschen Diesen Beitrag einem Moderator melden       Zum Anfang der Seite springen

Klar, ok, Hochzählen geht natürlich auch...
Früher, in meiner Jugend..., als ich noch C programmiert hab, hat man meistens den Zähler mit der "Ziel-Zahl" initialisiert und dann runter gezählt. Solange er noch größer 0 war (also while(counter), wenn counter == 0, dann ist der Ausdruck false und while bricht ab) hat man dann geschaut, ob counter verringert werden muss oder nicht.
Aber das ist natürlich reine Geschmackssache.
Daumen hoch

Gruß
Marco
25.09.2019 18:45 as_string ist offline E-Mail an as_string senden Beiträge von as_string suchen Nehmen Sie as_string in Ihre Freundesliste auf
Baumstruktur | Brettstruktur
Gehe zu:
Neues Thema erstellen Antwort erstellen
Informatiker Board » Themengebiete » Praktische Informatik » Algorithmen » Datumsberechnung