Autor |
Beitrag |
Yankyy02
      
Beiträge: 138
Erhaltene Danke: 21
Win 11 x64
C# (VS 2022 - Rider)
|
Verfasst: Di 18.03.14 22:42
Servus @all,
ich habe folgendes Problem womit ich mich nun schon seit einigen Tagen herumschlage und leider auf keinen grünen Zweig komme! Ich möchte überprüfen ob ein Datum/Zeit bereich in einen anderen fällt.
Ich habe eine Klasse TestDrive in der unter anderem zwei DateTime Objekte mit Startzeit und Endzeit gespeichert werden. Diese Testfahrten sind zur Laufzeit in einer Liste vom Typ List<TestDrive> abgelegt. Wenn ich nun eine neue Testfahrt abspeichern bzw. der Liste hinzufügen möchte würde ich gerne vorab prüfen ob in diesem Zeitraum bereits ein Eintrag vorhanden ist. Ich iteriere also mit einer foreach Schleife über die Listeneinträge.
Google Suche spuckte mir folgende 2 Methoden aus
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| public bool vollstaendig(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2) { return startTime2 >= startTime1 & startTime2 <= endTime2 & endTime1 >= startTime1 & endTime2 <= endTime1; }
public bool teilweise(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2) { return startTime2 >= startTime1 & startTime2 <= endTime2 | endTime1 >= startTime1 & endTime2 <= endTime1; } |
Angenommen ich habe bereits eine Probefahrten in der Liste mit folgenden Werten: 17.03.2014 10:00 bis 17.03.2014 11:00 und möchte nun einen neuen Eintrag mit folgenden Werten 18.03.2014 08:00 bis 18.03.2014 09:00 in die Liste hinzufüge dann gibt die Methode "teilweise" true zurück obwohl es sich um einen ganz anderen Tag handelt. Ich hoffe ich habe mich verständlich ausgedrückt und hoffe es kann mir jemand einen Tip geben wo ich hier ansetzen muss.
Anbei noch der Code wie ich die Prüfung gemacht habe
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| private bool IsCarForTestDriveAvailable(TestDrive drive) { foreach (TestDrive item in testDrives) { if (item.TestCar == drive.TestCar) { if (vollstaendig(item.BeginTimeTestDrive, item.EndTimeTestDrive, drive.BeginTimeTestDrive, drive.EndTimeTestDrive) || teilweise(item.BeginTimeTestDrive, item.EndTimeTestDrive, drive.BeginTimeTestDrive, drive.EndTimeTestDrive)) return false; } } return true; } |
Vielen Dank schonmal für eure Unterstützung ....
MfG
_________________ the quiter you become, the more you are able to hear
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Di 18.03.14 23:48
Wenn du schon möchtest, dass andere deinen Code debuggen, wäre es sehr nett ein abgeschlossenes (=compilierbares) Beispiel zu präsentieren. Sowas z.B.:
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: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| using System; using System.Windows;
namespace Test_1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { var a = new Fahrt(new DateTime(2014, 3, 17, 10, 0, 0), new DateTime(2014, 3, 17, 11, 0, 0)); var b = new Fahrt(new DateTime(2014, 3, 18, 8, 0, 0), new DateTime(2014, 3, 18, 9, 0, 0));
Console.WriteLine(teilweise(a, b)); } public bool vollstaendig(Fahrt a, Fahrt b) { return b.Start >= a.Start && b.Start <= b.Stop && a.Stop >= a.Start && b.Stop <= a.Stop; } public bool teilweise(Fahrt a, Fahrt b) { return (b.Start >= a.Start && b.Start <= b.Stop) || (a.Stop >= a.Start && b.Stop <= a.Stop); } }
public class Fahrt { public DateTime Start { get; set; } public DateTime Stop { get; set; } public Fahrt(DateTime start, DateTime stop) { Start = start; Stop = stop; } } } |
Ich habe dir dort auch schon deinen Fehler angemerkt: Du hast da Bedingungen die (bei einem wohlgeformten Intervall) immer true ergeben. Ich nehme mal an, da muss die Endzeit von der anderen Fahrt stehen.
Zuletzt bearbeitet von jfheins am Mi 19.03.14 16:09, insgesamt 1-mal bearbeitet
|
|
Yankyy02 
      
Beiträge: 138
Erhaltene Danke: 21
Win 11 x64
C# (VS 2022 - Rider)
|
Verfasst: Mi 19.03.14 13:12
Hallo jfheins,
vielen Dank vorab für deinen Beitrag und das freundliche debuggen meines nicht vorhandenen Codes obwohl ich ja nicht drum gebeten habe!? Ich habe an der Stelle an der du einen Vermerk hinterlassen hast die Änderung vorgenommen allerdings brachte auch dies keinen gewünschten Erfolg.
Ich werde mich nochmals intensiv von Anfang an mit der Problemstellung auseinandersetzen da es scheinbar ja ein triviales Problem ist.
MfG
_________________ the quiter you become, the more you are able to hear
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mi 19.03.14 16:28
Hallo,
das soll jetzt nicht böse gemeint ein (im Gegenteil) aber wie soll ich dir denn jetzt noch helfen? Ich weis, dass du deinen Code geändert hast, aber sonst nichts. Nicht wie er jetzt ausschaut, ob es immer noch an dem Testfall oben hängt, oder ob er überhaupt compiliert. Das ist echt eine magere Basis um weiter zu helfen.
Zitat: | vielen Dank vorab für deinen Beitrag und das freundliche debuggen meines nicht vorhandenen Codes obwohl ich ja nicht drum gebeten habe!? |
Ja, doch so kam das zumindest bei mir an. Du hast Code, der nicht funktioniert und möchtest dabei Hilfe. Das geht entweder durch Debugging (also Analysieren und Nachverfolgen) oder Nachfragen. Alles braucht etwas Übung, sowohl das Debugging als auch das stellen von guten Fragen. Je besser die Frage, desto schneller kommt oft die Antwort da Nachfragen entfallen können
Aber zum Thema.
Die Änderung, die ich meinte, schaut so aus:
C#-Quelltext 1: 2: 3: 4:
| public bool teilweise(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2) { return startTime2 >= startTime1 & startTime2 <= endTime1 | endTime2 >= startTime1 & endTime2 <= endTime1; } |
Die Zwei Prüfungen sind ja
1. Ist startTime2 innerhalb des Intervalls 1?
2. Ist endTime2 innerhalb der Intervalls 1?
Wenn eine dieser Beide Bedingungen wahr ist, dann überschneiden sie beiden Intervalle sich teilweise.
Der Vergleich endTime1 >= startTime1 Ist in dem Kontext ja sinnlos.
Der andere Fall, nämlich das ein Intervall das andere vollständig enthält, wird übrigens durch die vollständig Methode nicht abgedeckt. Dafür müsste man schon beide Fälle (a enthält b oder b enthält a) prüfen.
Nebenbei gesagt: Ich würde immer die Operatoren || und && einsetzen. Und in deinem Fall auch etwas mehr Klammern hinzufügen, das vermeidet Verwirrung.
Für diesen Beitrag haben gedankt: Yankyy02
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 19.03.14 17:26
Zitat: | Die Zwei Prüfungen sind ja
1. Ist startTime2 innerhalb des Intervalls 1?
2. Ist endTime2 innerhalb der Intervalls 1? |
Nur die beiden Bedingungen zu verodern ist vermutlich zu wenig. Dann würde die Bedingung ja auch auf "enthält vollständig" zutreffen und nicht nur auf echte Überschneidungen. Wenn man vollstaendig und teilweise unterscheiden will(?) dann ist hier wohl eher ein exclusiv oder gefragt (also ^ anstatt |).
Edit:
Und ein & für die "vollständig" Variante 
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mi 19.03.14 17:50
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 19.03.14 19:06
Kann dir nicht folgen  hätte gedacht einfach ein XOR dazwischen und gut
Da er scheinbar nur verhindern will das sich Einträge überschneiden, wenn ich mal Code ignoriere und seine Frage lese  , dann wäre das aber anders simpler zulösen.
Wenn der Zeitraum vor dem Start des anderen endet oder nach dem dem Ende des anderen startet gibt keine Überschneidungen aka.
C#-Quelltext 1: 2: 3: 4:
| public static bool IsOverlapping(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2) { return !(endTime1 < startTime2 || startTime1 > endTime2); } |
Was natürlich nur unter der Prämisse funktioniert das startTime immer kleiner oder gleich der endTime ist. Das läßt sich am einfachsten mit eine Klasse bewerkstelligen die einen Zeitraum darstellt und entsprechendes prüft. Ähnlich der gezeigten Fahrt Klasse . Dann mit entsprechender Prüfung oder tauschen der Start/Stop Zeiten.
|
|
Yankyy02 
      
Beiträge: 138
Erhaltene Danke: 21
Win 11 x64
C# (VS 2022 - Rider)
|
Verfasst: Do 20.03.14 20:34
Hallo jfheins,
glaub mir ich bin hier jedem dankbar der mir nur ansatzweise weiterhelfen kann um ein Problem zu lösen das grundsätzlich nicht seines ist und ich empfinde es auch nicht als Selbstverständlichkeit daß jemand seine Zeit für andere opfert aber daß macht doch schließlich so ein Forum aus oder?!
Und sorry wenn ich da was missverstanden habe aber wenn jemand einen Satz so anfängt
Zitat: |
Wenn du schon möchtest, dass andere deinen Code debuggen, wäre es sehr nett ein abgeschlossenes (=compilierbares) Beispiel zu präsentieren. Sowas z.B.:
|
dann hört sich daß eher als ein "muss" an als wenn man wirklich helfen möchte.
Andererseits bin ich dir dafür auch dankbar da ich mich so nochmals selbst intensiv mit dem Problem beschäftigt habe und so zu einer Lösung gekommen bin die ich keinem vorenthalten möchte. Natürlich wäre ich auch jetzt noch sehr dankbar wenn jemandem noch etwas auffallen würde was noch zu verbessern wäre.
Hier die Methode dir mir prüft ob bereits ein Termin zu diesem Zeitpunkt eingetragen wurde
C#-Quelltext 1: 2: 3: 4: 5: 6:
| internal bool IsTestDriveTimeNotValid(DateTime SavedTestDriveStartTime, DateTime SavedTestDriveEndTime, DateTime NewTestDriveStartTime, DateTime NewTestDriveEndTime) { return (SavedTestDriveStartTime <= NewTestDriveStartTime && NewTestDriveStartTime <= SavedTestDriveEndTime) || (SavedTestDriveStartTime <= NewTestDriveEndTime && NewTestDriveEndTime <= SavedTestDriveEndTime) || (NewTestDriveStartTime <= SavedTestDriveStartTime && NewTestDriveEndTime >= SavedTestDriveEndTime); } |
Und hier der Aufruf beim Versuch eine neue Testfahrt einzutragen
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| private bool IsCarForTestDriveAvailable(TestDrive drive) { foreach (TestDrive item in testDrives) { if (item.TestCar == drive.TestCar) { if (IsTestDriveTimeNotValid(item.BeginTimeTestDrive, item.EndTimeTestDrive, drive.BeginTimeTestDrive, drive.EndTimeTestDrive)) return false; } } return true; } |
Ich weiß das dies wieder kein compilierbares Programm ist aber ich glaube dennoch daß man den Gedankengang nachvollziehen kann und jeder der ein ähnliches Problem hatt die Methode ohne weiteres in seinem Projekt wiederverwenden könnte.
Zum Abschluss wäre ich dir jfheins über nochmaliges Feedback sehr dankbar.
MfG
_________________ the quiter you become, the more you are able to hear
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 20.03.14 22:36
Hallo,
auf Anhieb fallen mir 2 Dinge auf:
- du solltest die Methode positiv benennen (d.h. IsTestDriveTimeValid) und dementsprechend die Bedingung negieren
- bei den Parameternamen solltest du TestDrive als Bestandteil entfernen, da es bei allen Parametern auftaucht und den Code länger und unübersichtlicher macht (m.E. wäre sogar Start1, End1, Start2, End2 übersichtlicher - so wie Ralf Jansen und jfheins ihren Code auch gepostet haben).
Für diesen Beitrag haben gedankt: Yankyy02
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 20.03.14 22:41
Yankyy02 hat folgendes geschrieben : | Hallo jfheins,
glaub mir ich bin hier jedem dankbar der mir nur ansatzweise weiterhelfen kann um ein Problem zu lösen das grundsätzlich nicht seines ist und ich empfinde es auch nicht als Selbstverständlichkeit daß jemand seine Zeit für andere opfert aber daß macht doch schließlich so ein Forum aus oder?!
Und sorry wenn ich da was missverstanden habe aber wenn jemand einen Satz so anfängt
[...]dann hört sich daß eher als ein "muss" an als wenn man wirklich helfen möchte. |
Hmmm, ja tut mir Leid. Ich glaube ich war schon ein wenig zu müde
Und mit dem Ansatz von Ralf (ein Post über deinem) solltest du mit zwei Vergleichen auskommen. Und so allgemein würde ich die Methode auf zwei Parameter vom Typ TestDrive reduzieren. Außerdem ist eine Property "TestDrive.BeginTimeTestDrive" auch eher unglücklich benannt. dass es sich um einen TestDrive handelt, sagt ja schon die Klasse aus. Dass es sich um eine zeit handelt, sagt der Typ der Property. "TestDrive.Begin" würde also vollkommen reichen. Sprechende Bezeichner sind gut, aber das wäre mir dann doch zu viel Redundanz
Und noch anders benennen. Die Methode prüft ja eigentlich nur, ob die zwei Fahrten überlappen. Es gibt ja noch andere Kriterien, die eine geplante Fahrt ungültig machen. "IsOverlapping" macht sich da eigentlich schon gut: C#-Quelltext 1: 2: 3: 4:
| internal bool IsOverlapping(TestDrive a, TestDrive b) { return (a.End >= b.Begin) && (a.Begin <= b.End); } |
Und dann könntest du die andere Methode etwas eindampfen, falls Bedarf deinerseits besteht:
C#-Quelltext 1: 2: 3: 4:
| private bool IsAvailableForTestDrive(TestDrive drive) { return testDrives.Where(item => item.TestCar == drive.TestCar).Any(x => IsOverlapping(x, drive)); } |
Letzteres würde ich aber nur empfehlen, falls dir klar ist was dort passiert.
Für diesen Beitrag haben gedankt: Yankyy02
|
|
Yankyy02 
      
Beiträge: 138
Erhaltene Danke: 21
Win 11 x64
C# (VS 2022 - Rider)
|
Verfasst: Fr 21.03.14 01:07
Hallo,
ich danke dir für dein freundliches Feedback  und werde deine Vorschläge versuchen umzusetzen da ich dir vollkommen recht geben muss  . Mit den Linq Ausdrücken bin ich leider noch nicht so vertraut aber mit deiner und der Unterstüzung der Community wird das sicher auch noch werden.
MfG
Gery
_________________ the quiter you become, the more you are able to hear
|
|
|