Überprüfen ob sich zwei oder mehr Zeitspannen überschneiden

  • VB.NET

Es gibt 49 Antworten in diesem Thema. Der letzte Beitrag () ist von Cebrox.

    Überprüfen ob sich zwei oder mehr Zeitspannen überschneiden

    Hi zusammen,

    wie der Titel schon sagt möchte ich überprüfen, ob sich mehrere Zeitspannen überschneiden. Momentan sind die Daten in einer Datenbank einzeln gespeichert. Also Anfang-Zeit, End-Zeit und Datum. Die Zeitspannen überstrecken sich aber nicht über mehrere Tage. Wie man die Daten abruft ist klar. Er soll jetzt halt nur überprüfen ob einen neuer Termin sich nicht mit einem anderen Termin an diesem Tag überschneidet.

    Vielen Dank schonmal :)
    Cebrox
    Du hast ja immer ein StartDatum (Typ Date) und eine Zeitspanne (Typ Timespan). StartDatum + Zeitspanne ergibt ein neues Datum - das Ende des Termins.
    Dann kannst du zwei Termine ganz einfach auf überschneiden vergleichen, mache dir dazu mal ein paar Skizzen um das zu verdeutlichen. Man kann ganz einfach sagen: zwei Termine überschneiden sich nicht, wenn

    a) A.StartDatum und A. EndDatum beide kleiner sind als B.StartDatum und
    b) A.StartDatum größer ist als B.EndDatum (und damit automatisch auch A.EndDatum größer als B.EndDatum)

    Hinweis: den Typ Date kann man wie Zahlen vergleichen - also den > und < Operator verwenden.
    Ok. Danke schonmal für deine Antwort. Das ist auch logisch. Aber wenn ich jetzt einen Termin zwischen zwei andere Termine machen möchte. Wie muss ich dann die Daten von der MySQL Datenbank abrufen um das zu überprüfen bzw. Wie muss ich dann ne Schleife oder so bauen? Irgendwie hab ich grade voll den BrainBug :D

    VB.NET-Quellcode

    1. Dim d1 As New DateTime(2013, 1, 31)
    2. Dim d2 = DateTime.Now
    3. If d2 > d1 AndAlso d2 < d1.AddDays(30) Then
    4. ' gewonnen
    5. End If
    Drück unten auf den Erledigt-Button.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Cebrox schrieb:

    Was macht den
    Wie komme ich an Elementarinformationen?
    Mit der Maus draufklicken und die Taste F1 drücken. MSDN
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Cebrox schrieb:

    geht das in meinem Fall besser.
    Wohl kaum.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wieso? Ich habe in meiner Datenbank pro Termin die Anfangszeit, Endzeit und das Datum gesspeichert. Wenn ich jetzt einfach ne Abfrage mache ob zwischen den Zeiten, des neuen Termins eine Zeit (egal welche) von einem anderen Termin liegt und ich nichts zurückbekomme müsste der Termin doch frei sein. Oder denke ich da jetzt falsch?
    Wo ist der Unterschied zwischen Anfangszeit und Datum sowie Endzeit und Datum?

    Wenn ich jetzt einfach ne Abfrage mache ob zwischen den Zeiten, des neuen Termins eine Zeit (egal welche) von einem anderen Termin liegt


    nope, funktioniert nicht (siehe skizze "oben", da ist der Gegenbeweis), laut deiner Abfrage wäre dort keine Überschneidung - ists aber.
    Mach es wie ich gepostet habe (skizze "unten"), finde heraus ob ein neuer Termin sich mit einem alten überschneidet. Wenn nie true zurückkommt, dann ist er frei. Dazu schaue einfach ob der neue Termin komplett links vom StartDatum eines alten Termins liegt ODER komplett rechts vom Enddatum eines alten Termins. In allen anderen Fällen überschneiden sie sich.
    Bilder
    • untitled.PNG

      4,95 kB, 503×334, 438 mal angesehen
    Ok, aber wie setzte ich das dann syntaktisch um? Steh da gard irgendwie auf schlauch?

    Als erstes Ruf ich erstma per SQL Befehl alle Termine an dem Tag ab und dann mit einer Schleife? Und wie müsste die Schleife dann aussehen? Oder eher schon ne Bedingung in den SQL Befehl einbauen einbauen?
    So:

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. Dim d1 As New DateTime(2013, 1, 31)
    2. Dim d2 = DateTime.Now
    3. If d2 > d1 AndAlso d2 < d1.AddDays(30) Then
    4. ' gewonnen
    5. End If
    Natürlich musste für d1 und d2 Deine speziellen Werte einsetzen und die Zeitspannen addieen statt der 30 Tage.
    ------------------------
    Und sieh Dir die Klasse TimeSpan an, damit kannst Du die Länge Deiner Zeitintervalle behandeln.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    Pack z.B. "Termin" in eine separate Klasse, da kannst Du dann akke Checks ganz elegant einbauen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So, ich hab nun probiert. Hab mir fürs checken folgende Methode gemacht:

    VB.NET-Quellcode

    1. Imports MySql.Data.MySqlClient
    2. Module zeit
    3. Public Function ueberpruefen(ByVal datum As Date, ByVal anfang_zeit As Date, ByVal dauers As Double, ByVal dauerm As Double) As Boolean
    4. Dim reader As MySqlDataReader
    5. Dim erg As Boolean = True
    6. Dim datum_string As String
    7. Dim end_zeit_alt As Date
    8. Dim anfang_zeit_neu As Date
    9. Dim end_zeit_neu As Date
    10. Dim anfang_zeit_alt As Date
    11. anfang_zeit_neu = (datum.Date)
    12. anfang_zeit_neu = anfang_zeit_neu.AddHours(anfang_zeit.Hour)
    13. anfang_zeit_neu = anfang_zeit_neu.AddMinutes(anfang_zeit.Minute)
    14. end_zeit_neu = anfang_zeit_neu.AddHours(dauers)
    15. end_zeit_neu = end_zeit_neu.AddMinutes(dauerm)
    16. datum_string = datum.Date.ToString("yyyy-MM-dd")
    17. cmd.CommandText = "select datum, hour(anfang_zeit) as anfang_stunde, minute(anfang_zeit) as anfang_minute, hour(end_zeit) as end_stunde, minute(end_zeit) as end_minute from termine where datum = '" & datum_string & "';"
    18. Try
    19. con.Open()
    20. reader = cmd.ExecuteReader
    21. If reader.HasRows = False Then
    22. erg = True
    23. con.Close()
    24. Return erg
    25. Else
    26. Do While reader.Read
    27. end_zeit_alt = (reader("datum"))
    28. end_zeit_alt = end_zeit_alt.AddHours(CDbl(reader("end_stunde")))
    29. end_zeit_alt = end_zeit_alt.AddMinutes(CDbl(reader("end_minute")))
    30. anfang_zeit_alt = (reader("datum"))
    31. anfang_zeit_alt = anfang_zeit_alt.AddHours(CDbl(reader("anfang_stunde")))
    32. anfang_zeit_alt = anfang_zeit_alt.AddMinutes(CDbl(reader("anfang_minute")))
    33. If end_zeit_alt >= anfang_zeit_neu AndAlso end_zeit_alt <= end_zeit_neu Then
    34. If erg = False Then
    35. erg = False
    36. Else
    37. erg = True
    38. End If
    39. Else
    40. erg = False
    41. End If
    42. Loop
    43. con.Close()
    44. Return erg
    45. End If
    46. Catch ex As Exception
    47. MsgBox("Folgender Fehler ist aufgetreten: " & ex.ToString)
    48. con.Close()
    49. Return False
    50. End Try
    51. End Function
    52. End Module


    Das Problem aber: Termine nach einem bestehenden Termin kann ich eintragen. Termine, wo noch gar kein Termin am Tag ist, auch. Aber Termine vor einem bestehenden Termin einzutragen, geht nicht.

    Hab schon probiert mit der Bedingung ein bisschen rumzuspielen. Habs aber net hinbekommen.
    Vlt wisst ihr ja was ich falsch mache.

    MfG
    Cebrox
    Ganz ehrlich: schreib dir ne Klasse Termin mit folgenden Properties:
    - Datum (Da startet der Termin, Typ: Date)
    - Dauer (so lange dauert der Termin, Typ TimeSpan!!)

    das EndDatum ergibt sich aus Datum + Dauer (das kannst du sogar direkt so hinschreiben, da du Date und TimeSpan zusammenrechnen kannst). Weiterhin schreibst du eine Methode die zwei Termin-Instanzen auf überschneiden prüft - halte dich dabei an meine beiden Posts, vor allem der Erste.
    Dann haust du deinen neuen Termin in eine solche TerminKlasse und durchläufst deine Datenbank (davon hab ich keine Ahnung), machst aus jedem Termin eine TerminKlasse und kannst sie dann gemütlich mit deiner Überschneiden-Methode gegenprüfen.

    So wie das jetzt ist finde ichs etwas grauenhaft - selbst meine Methode erzeugt sicherlich einen Overhead der nicht sein müsste aber gefällt mir dann doch besser. Sollte es doch mit Datenbank-Mitteln schöner gehen bin ich froh mich noch nciht damit beschäftigt zu haben xD
    Hiermal die Methode, die eine Überschneidung zweier Zeitbereiche prüft:

    VB.NET-Quellcode

    1. Private Function TimeIntersect(ByVal x0 As Date, ByVal x1 As Date, ByVal y0 As Date, ByVal y1 As Date) As Boolean
    2. Return x0 < y1 AndAlso x1 > y0
    3. End Function
    Also der kleinere Wert des einen (index 0) muß kleiner sein als der größere Wert des anneren.
    Diese Überschneidungs-Bedingung gilt übrigens für jede Maßeinheit.

    Jo, der TE macht sichs extrem schwer, wohl weil er kein Datenmodell im Kontext der Sprache VB hat (ach, ich rede schonwieder von typisiertem Dataset).

    Daher musser jeden Piss vonne DB abfragen, und das ist halt immer son Theater, letztlich weil Sql ausserhalb des Sprach-Kontextes liegt.

    Und wenner dann ermittelt hat: Ja, Termin möglich, dann kann er ihn einfügen (nächstes Sql-Theater).

    Jo, dann ist der Termin inne Datenbank, aber der User sieht leider noch nix - was tun?
    Ah ja - fragen wir doch einfach nochmal die DB ab (und nochne Runde :P)

    Und das war nur das Einfügen! Kommt ja noch ändern und löschen hinzu!

    Und das war nur der Termin - fehlen ja noch die Personen, die den Termin machen - mit denen gibts dasselbe Theater nochmal.
    Und Aufgaben gibts vmtl. auch noch...