Liczenie (dat) czy elementy kalendarza się ze sobą zazębiają

0

Witam.
Piszę z pytaniem, ponieważ już próbowałem wielu rzeczy i jednak jestem na to za głupi. Potrzebuje nakierowania jak sprawdzić czy dwa elementy kalendarza się zazębiają.

zlecenie_merged.png

To niestety nie działa


        private bool IsInRange(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
        {
            return (start1 == start2 && end1 == end2) ||
                (start1 < start2 && end1 < end2 && start1 < end2 && end1 > start2) ||
                (start1 > start2 && end1 > end2 && start1 < end2 && end1 > start2) ||
                (start1 > start2 && end1 < end2 && start1 < end2 && end1 > start2) ||
                (start1 < start2 && end1 == end2 && start1 < end2 && end1 > start2) ||
                (start1 == start2 && end1 < end2 && start1 < end2 && end1 > start2);
        }

Większość odpowiedzi na SO jest gdy chce sprawdzić czy data (jedna) zawiera się w przedziale dat. Ja niestety muszę sprawdzić czy przedziały dat się zazębiają. Czy to na zrzucie to nie jest przypadkiem ten warunek start1 == start2 && end1 < end2 && start1 < end2 && end1 > start2?

0

Ogólnie do rozważenia masz następujące przypadki ( trzeba jeszcze zdefiniować czy znaki mniejszości / większości są ostre czy nie ).

Przedział A :                    |-------------------------------------|

Przedziały B różne przypadki:

Przypadek 1 :    |---------| 
Przypadek 2 :               |----------| 
Przypadek 3 :                                 |----------| 
Przypadek 4 :                                                     |----------| 
Przypadek 5 :              |-------------------------------------------------------| 
Przypadek 6 :                                                                        |----------| 

Warto to rozpisać do wyrażenia boolowskiego i zoptymalizować.

0

Nie będę miał takich przypadków. U mnie jest więcej reguł jak mają być wrzucane appointmenty do kalendarza i jedyne co się może zdarzyć to różne przypadki tego co zaznaczyłem na czerwono w obrębie "jednej linii" (resource), w tym przypadku M3. Zazębianie się na innych zasobach ma zostać. Nie mogę robić dwóch różnych zleceń w tym samym czasie czyli to na czerwono. Jeżeli w tym zakresie dat jest już jakiś wpis to kolejny wpis w tym zasobie powinien się zacząć jak ten poprzedni się skończy.

0

Ok, chyba też tak miałem. Nie ogarnia przypadku, w którym drugi miałby się zacząć w tej samej godzinie co pierwszy skończył. Na przykład:

ZADANIE 1
Start: 07.10.2020 11:00
End: 07.10.2020 13:00

ZADANIE 2
Start: 07.10.2020 8:00
End: 07.10.2020 11:00

Skoro ZADANIE 2 skończyło się o 11:00 to śmiało ZADANIE 1 może od 11:00 zacząć.

0

jest taki paradoksalny (dla mnie - długo wydawał mi się wbrew intuicji) sposób na zaledwie dwóch porównaniach (mi intuicja podpowiadała przynajmniej cztery)

bool common = range1.start < range2.end && range1.end > range2.start;

Przepracuj sobie sam ostre / nieostre nierówności

1

Wg mnie to nie takie oczywiste.
Niech pierwszy przedział dat definiują daty od A1 do A2 a drugi to będą od B1 do B2.


                                 A1                                    A2
Przedział A :                    |-------------------------------------|
                                 .                                     .
Przedziały B różne przypadki:    .                                     .
                                 .                                     .
                 B1        B2    .                                     .
Przypadek 1 :    |---------|     .                                     .
                            B1   .     B2                              .
Przypadek 2 :               |----------|                               .
                                 .            B1         B2            .
Przypadek 3 :                    .            |----------|             .
                                 .                                B1         B2
Przypadek 4 :                    .                                |----------| 
                            B1   .                                     .     B2
Przypadek 5 :               |------------------------------------------------| 
                                 .                                     .       B1         B2
Przypadek 6 :                    .                                     .       |----------| 

Rozpisujemy poszczególne przypadki:

1.                B1 <= A1 AND B2 <= A1 AND B1 <= A2 AND B2 <= A2
2.                B1 <= A1 AND B2 >= A1 AND B1 <= A2 AND B2 <= A2
3.                B1 >= A1 AND B2 >= A1 AND B1 <= A2 AND B2 <= A2
4.                B1 >= A1 AND B2 >= A1 AND B1 <= A2 AND B2 >= A2
5.                B1 <= A1 AND B2 >= A1 AND B1 <= A2 AND B2 >= A2
6.                B1 >= A1 AND B2 >= A1 AND B1 >= A2 AND B2 >= A2

Przypadek 1 i 6 nas nie interesują więc pozostają tylko:

2.                B1 <= A1 AND B2 >= A1 AND B2 <= A2
3.                B1 >= A1 AND B1 <= A2
4.                B1 >= A1 AND B1 <= A2
5.                B1 <= A1 AND B2 >= A2

Teraz uprościmy sobie wyrażenie odpowiednimi podstawieniami. Zamienimy warunki na zmienne logiczne.
Niech:

              B1 <= A1 = a
              B2 <= A1 = b
              B1 >= A1 = c
              B2 >= A1 = d
              B1 <= A2 = e
              B2 <= A2 = f
              B1 >= A2 = g
              B2 >= A2 = h

Otrzymamy z tego wyrażenie:


                ( a AND d AND f ) OR ( c AND e ) OR ( c AND e ) OR ( a AND h )
                
                => (adf)+(ce)+(ce)+(ah)
                po zoptymalizowaniu wyjdzie => adf + ce + ah

Czyli końcowy warunek to:

    ( B1 <= A1 AND B2 >= A1 AND B2 <= A2 ) OR ( B1 >= A1 AND B1 <= A2 ) OR ( B1 <= A1 AND B2 >= A2 )

Po długim wyprowadzeniu i dyskusji w komentarzach jednak trzeba dopisać, że wystarczające i o wiele bardziej optymalne jest:

( B2 >= A1 AND B1 <= A2 )  
1

Jeszcze raz wyprowadzenie tym razem dla wersji optymalnej:

                                 A1                                    A2
Przedział A :                    |-------------------------------------|
                                 .                                     .
Przedziały B różne przypadki:    .                                     .
                                 .                                     .
                 B1        B2    .                                     .
Przypadek 1 :    |---------|     .                                     .
                            B1   .     B2                              .
Przypadek 2 :               |----------|                               .
                                 .            B1         B2            .
Przypadek 3 :                    .            |----------|             .
                                 .                                B1         B2
Przypadek 4 :                    .                                |----------| 
                            B1   .                                     .     B2
Przypadek 5 :               |------------------------------------------------| 
                                 .                                     .       B1         B2
Przypadek 6 :                    .                                     .       |----------| 

Rozpisujemy poszczególne przypadki:

1.                B1 <= A1 AND B2 <= A1 AND B1 <= A2 AND B2 <= A2
2.                B1 <= A1 AND B2 >= A1 AND B1 <= A2 AND B2 <= A2
3.                B1 >= A1 AND B2 >= A1 AND B1 <= A2 AND B2 <= A2
4.                B1 >= A1 AND B2 >= A1 AND B1 <= A2 AND B2 >= A2
5.                B1 <= A1 AND B2 >= A1 AND B1 <= A2 AND B2 >= A2
6.                B1 >= A1 AND B2 >= A1 AND B1 >= A2 AND B2 >= A2

Teraz podchodzimy to tematu odwrotnie niż w poprzednim wyprowadzeniu i bierzemy przypadki które nas nie interesują czyli te które nie spełniają naszych założeń. Zatem pozostają tylko:

1.                B1 <= A1 AND B2 <= A1 AND B1 <= A2 AND B2 <= A2
6.                B1 <= A1 AND B2 <= A1 AND B1 <= A2 AND B2 <= A2

Po wywaleniu warunków "zbędnych" pozostanie:

1.                B2 < A1
6.                B1 > A2


                  ( B2 < A1 OR B1 > A2 )

Teraz uprościmy sobie wyrażenie odpowiednimi podstawieniami. Zamienimy warunki na zmienne logiczne.
Niech:

              B2 < A1 = a
              B1 > A2 = b

Otrzymamy wyrażenie wybierające wszystkie przypadki nie spełniające naszego kryterium.

                ( a OR b ) 

Zatem by uzyskać to co chcemy, czyli zakresy mające część wspólną wystarczy je zanegować:

                !( a OR b )  =>  ( ~a AND ~b )

Z tetgo wynika że czym jest negacją dla nierówności? Odwrócona nierówność. Odpowiednio podstawiamy i mamy:

                ( B2 >= A1 AND B1 <= A2 )

1 użytkowników online, w tym zalogowanych: 0, gości: 1