निर्धारित करें कि क्या दो दिनांक रेंज ओवरलैप हैं


1248

दो तारीख सीमाओं को देखते हुए, यह निर्धारित करने का सबसे सरल या सबसे कुशल तरीका है कि क्या दो तिथि सीमाएं ओवरलैप हैं?

उदाहरण के लिए, मान लीजिए कि हम दिनांक समय चर द्वारा सूचित किया जाता पर्वतमाला है StartDate1करने के लिए EndDate1 और StartDate2 करने के लिए EndDate2


3

@CharlesBretana इसके लिए धन्यवाद, आप सही हैं - यह लगभग मेरे प्रश्न के दो-आयामी संस्करण की तरह है!
इयान नेल्सन


2
स्थिति को विभाजित करें 'दो तिथि सीमाएं' मामलों में (वहाँ दो हैं) फिर प्रत्येक मामले के लिए परीक्षण करें।
कर्नल पैनिक

1
यह कोड ठीक काम करता है। आप मेरा जवाब यहां देख सकते हैं: stackoverflow.com/a/16961719/1534785
जेहुँ रहीमोव

जवाबों:


2287

(StartA <= EndB) और (EndA> = StartB)

प्रमाण:
सशर्त का अर्थ है कि DateRange B के बाद पूरी तरह से डेट्रेंज बी
_ |---- DateRange A ------| |---Date Range B -----| _
(सही है तो StartA > EndB)

कंडीशन बी का मतलब है कि DateRange A पूरी तरह से DateRange B से पहले है
|---- DateRange A -----| _ _ |---Date Range B ----|
(सही है तो EndA < StartB)

तब ओवरलैप मौजूद है अगर न तो कोई नोर बी सच है -
(यदि एक सीमा न तो पूरी तरह से दूसरे के बाद है,
न पूरी तरह से दूसरे से पहले है, तो उन्हें ओवरलैप करना होगा।)

अब डी मोर्गन का एक नियम कहता है कि:

Not (A Or B) <=> Not A And Not B

जिसका अनुवाद है: (StartA <= EndB) and (EndA >= StartB)


नोट: इसमें ऐसी स्थितियाँ शामिल हैं, जहाँ किनारों को ओवरलैप किया जाता है। यदि आप इसे बाहर करना चाहते हैं,
तो >=आपरेटरों को >, और <= को बदल दें<


नोट 2। @Baodad के लिए धन्यवाद, देखने के इस ब्लॉग , वास्तविक ओवरलैप कम से कम का है:
{ endA-startA, endA - startB, endB-startA, endB - startB}

(StartA <= EndB) and (EndA >= StartB) (StartA <= EndB) and (StartB <= EndA)


नोट 3। @Tomosius के लिए धन्यवाद, एक छोटा संस्करण पढ़ता है:
DateRangesOverlap = max(start1, start2) < min(end1, end2)
यह वास्तव में क्या है जो लंबे समय तक कार्यान्वयन के लिए एक वाक्यात्मक शॉर्टकट है, जिसमें यह सत्यापित करने के लिए अतिरिक्त चेक शामिल हैं कि प्रारंभ तिथियां एंडडेट्स से पहले या उससे पहले हैं। इसे ऊपर से प्राप्त करना:

यदि प्रारंभ और समाप्ति दिनांक आदेश से बाहर हो सकते हैं, अर्थात, यदि यह संभव है कि startA > endAया startB > endB, तो आपको यह भी जांचना होगा कि वे क्रम में हैं, इसलिए इसका मतलब है कि आपको दो अतिरिक्त वैधता नियम जोड़ने होंगे:
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB) या:
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB) या,
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB)) या:
(Max(StartA, StartB) <= Min(EndA, EndB)

लेकिन लागू करने के लिए Min()और Max(), आपको कोड करना होगा, (terseness के लिए C ternary का उपयोग करके),:
(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)


29
यह इन दो मान्यताओं पर आधारित एक सरलीकृत तर्क है: 1) StartA <EndA; 2) StartB <EndB। यह स्पष्ट प्रतीत होता है, लेकिन वास्तव में डेटा अनजान स्रोत से आ सकता है जैसे उपयोगकर्ता इनपुट या सैनिटेशन के बिना डेटाबेस। ध्यान रखें कि आपको यह सुनिश्चित करने के लिए इनपुट डेटा को मान्य करने की आवश्यकता होगी कि इस सरल तर्क का उपयोग करने से पहले आप दो धारणाएं सच हैं या सब कुछ अलग हो जाएगा। मेरे अपने अनुभव से सीखा सबक;)
Devy

12
@Devy, आप सही हैं। सिवाय इसके कि यह भी काम करेगा अगर startA = endA। वास्तव में, यह वही है जो शब्दों Startऔर Endमतलब है। यदि आपके पास टॉप और बॉटम, या ईस्ट और वेस्ट, या हाईवैल्यू और लोवल्यू नाम के दो वैरिएबल हैं, तो यह माना जा सकता है या निहित है कि कुछ या कोई, कहीं न कहीं यह सुनिश्चित करना चाहिए कि वैल्यू के जोड़े में से कोई एक विपरीत वैरिएबल में संचित न हो। -दोनों में से किसी एक जोड़ी को, क्योंकि, यह तब भी काम करेगा जब मूल्यों के दोनों जोड़े स्विच हो जाएंगे।
चार्ल्स ब्रेटाना

15
आप आसानी से अशक्त जोड़ सकते हैं startऔर end(शब्दार्थ के साथ कि "null start" = "समय की शुरुआत से" और "null end" = "to the time of the end") उस तरह:(startA === null || endB === null || startA <= endB) && (endA === null || startB === null || endA >= startB)
केविन रॉबेल

9
Stackexchange पर सबसे अच्छा जवाब! यह स्मार्ट फॉर्मूला क्यों काम करता है, इस पर स्पष्टीकरण देखना अच्छा लगता है!
अबीर सुल

4
यहाँ सबसे कॉम्पैक्ट रूप है जिसके बारे में मैं सोच सकता था, जो कि अमान्य इनपुट (आरंभ तिथि> = अंतिम तिथि) के मामले में भी गलत हैDateRangesOverlap = max(start1, start2) < min(end1, end2)
tomosius

406

मेरा मानना ​​है कि यह कहना पर्याप्त है कि दोनों सीमाएँ ओवरलैप हैं यदि:

(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)

76
मुझे (StartDate1 <= EndDate2) and (EndDate1 >= StartDate2)यह समझने में आसानी होती है कि रेंज 1 हमेशा परीक्षणों में बाईं ओर है।
AL

8
यह मानता है कि आरंभ और समाप्ति दिनांक समावेशी हैं। बदलें <=करने के लिए <करता है, तो शुरू समावेशी है और अंत अनन्य है।
रिचर्ड श्नाइडर

यह बहुत अच्छी तरह से काम करेगा भले ही startDate2 startDate1 से पहले हो। तो यह मानने की कोई जरूरत नहीं है कि startDate1 startDate2 से पहले है।
शेहान सिमेन

3
मैंने पाया (StartDate1 <= EndDate2) और (StartDate2 <= EndDate1) अंकन (उत्तर के अनुसार) अन्य उत्तरों की तुलना में समझना आसान है।
एपीसी

कैसे अनुकूलित करें ताकि यह StartDate1 और / या EndDate1 वाले डेटा के साथ काम करे? कोड मानता है कि StartDate1 और EndDate1 हमेशा मौजूद रहते हैं। क्या होगा अगर StartDate1 दिया गया है, लेकिन कोई EndDate1 या EndDate1 नहीं दिया गया है, लेकिन StartDate1 नहीं। इस अतिरिक्त मामले को कैसे संभालें?
juFo

117

.NET के लिए यह आलेख टाइम पीरियड लाइब्रेरी में एन्युमरेशन पीरियडेशन द्वारा दो समय अवधि के संबंध का वर्णन किया गया है :

// ------------------------------------------------------------------------
public enum PeriodRelation
{
    After,
    StartTouching,
    StartInside,
    InsideStartTouching,
    EnclosingStartTouching,
    Enclosing,
    EnclosingEndTouching,
    ExactMatch,
    Inside,
    InsideEndTouching,
    EndInside,
    EndTouching,
    Before,
} // enum PeriodRelation

यहां छवि विवरण दर्ज करें


अच्छा, मैंने जावा में अल्लेंस इंटरवल
मेनो

80

लौकिक संबंधों (या किसी अन्य अंतराल के संबंध, उस पर आते हैं) के बारे में तर्क के लिए, एलन के अंतराल बीजगणित पर विचार करें । यह उन 13 संभावित संबंधों का वर्णन करता है जो दो अंतराल एक दूसरे के संबंध में हो सकते हैं। आप अन्य संदर्भ पा सकते हैं - "एलन इंटरवल" एक ऑपरेटिव खोज शब्द प्रतीत होता है। आप Snodgrass के विकासशील समय-उन्मुख अनुप्रयोगों में SQL (URL पर ऑनलाइन उपलब्ध), और दिनांक, डार्वेन और लोरेंत्ज़ोस टेम्पोरल डेटा और रिलेशनल मॉडल (2002) / समय और रिलेशनल थ्योरी में इन ऑपरेशन के बारे में जानकारी भी प्राप्त कर सकते हैं : अस्थायी डेटाबेस रिलेशनल मॉडल और एसक्यूएल (2014; प्रभावी रूप से टीडी एंड आरएम का दूसरा संस्करण)।


संक्षिप्त (ईश) उत्तर है: दो तिथि अंतराल दिए गए हैं Aऔर Bघटकों .startऔर .endबाधा के साथ .start <= .end, फिर दो अंतराल ओवरलैप करते हैं:

A.end >= B.start AND A.start <= B.end

आप ओवरलैप की डिग्री के लिए अपनी आवश्यकताओं को पूरा करने के लिए >=बनाम >और <=बनाम के उपयोग को ट्यून कर सकते <हैं।


एरिक टिप्पणियाँ:

आप केवल 13 प्राप्त कर सकते हैं यदि आप चीजों को मजाकिया गिनते हैं ... मुझे "15 संभावित संबंध मिल सकते हैं जो दो अंतराल हो सकते हैं" जब मैं इसके साथ पागल हो जाता हूं। समझदार गिनती से, मुझे केवल छह मिलते हैं, और यदि आप देखभाल करते हैं कि क्या ए या बी पहले आता है, तो मुझे केवल तीन मिलते हैं (कोई अंतर नहीं, आंशिक रूप से एक दूसरे से अलग, एक पूर्ण)। 15 इस तरह से होता है: [पहले: शुरू, भीतर, अंत, बाद], [शुरू: शुरू, भीतर, अंत, बाद], [भीतर: भीतर, अंत, बाद], [अंत: अंत: अंत, बाद], [ के बाद: के बाद]।

मुझे लगता है कि आप दो प्रविष्टियों को 'पहले: पहले' और 'बाद: बाद' में नहीं गिन सकते। मैं 7 प्रविष्टियाँ देख सकता था यदि आप उनके व्युत्क्रमों के साथ कुछ संबंधों की समानता देखते हैं (संदर्भित विकिपीडिया में आरेख देखें; इसमें 7 प्रविष्टियाँ हैं, जिनमें से 6 में एक अलग व्युत्क्रम है, जिसमें एक अलग प्रतिलोम नहीं होने के बराबर है)। और क्या तीन समझदार आपकी आवश्यकताओं पर निर्भर करता है।

----------------------|-------A-------|----------------------
    |----B1----|
           |----B2----|
               |----B3----|
               |----------B4----------|
               |----------------B5----------------|
                      |----B6----|
----------------------|-------A-------|----------------------
                      |------B7-------|
                      |----------B8-----------|
                         |----B9----|
                         |----B10-----|
                         |--------B11--------|
                                      |----B12----|
                                         |----B13----|
----------------------|-------A-------|----------------------

1
आप केवल 13 प्राप्त कर सकते हैं यदि आप चीजों को मजाकिया गिनते हैं ... मुझे "15 संभावित संबंध मिल सकते हैं जो दो अंतराल हो सकते हैं" जब मैं इसके साथ पागल हो जाता हूं। समझदार गिनती से, मुझे केवल छह मिलते हैं, और अगर आप देखभाल करते हैं कि क्या ए या बी पहले आता है, तो मुझे केवल तीन मिलते हैं (कोई अंतर नहीं, आंशिक रूप से एक दूसरे को पूरी तरह से एक दूसरे के भीतर)। 15 इस तरह से होता है: [पहले: शुरू, भीतर, अंत, बाद], [शुरू: शुरू, भीतर, अंत, बाद], [भीतर: भीतर, अंत, बाद], [अंत: अंत, बाद], [] के बाद: के बाद]।
एरिक

@Emtucifor: मुझे लगता है कि आप दो प्रविष्टियों को 'इससे ​​पहले: पहले' और 'बाद: बाद' में नहीं गिन सकते।
जोनाथन लेफ़लर

अपने अपडेट को फिर से करें: बी 1 से ए पहले है: पहले और बी 13 से ए के बाद है: के बाद। आपका अच्छा आरेख याद आ रहा है: बी 5 बी 6 के बीच शुरू, और अंत: बी 11 और बी 12 के बीच। यदि समापन बिंदु पर होना महत्वपूर्ण है, तो आपको इसे गिनना होगा, इसलिए अंतिम मिलान 15 है, न कि 13. मुझे नहीं लगता कि समापन बिंदु महत्वपूर्ण है, इसलिए मैं व्यक्तिगत रूप से इसे [पहले: पहले, भीतर, बाद में] गिनता हूं , [भीतर: भीतर, के बाद], [के बाद: के बाद] जो आता है 6. मुझे लगता है कि संपूर्ण समापन बिंदु सिर्फ भ्रम है कि क्या सीमाएं समावेशी हैं या अनन्य हैं। समापन बिंदु की विशिष्टता मुख्य संबंधों को नहीं बदलती है!
एरिक

अर्थात्, मेरी योजना में ये समतुल्य हैं: (बी 2, बी 3, बी 4), (बी 6, बी 7, बी 9, बी 10), (बी 8, बी 11, बी 12)। मुझे लगता है कि बी 7 का अर्थ है कि दो रेंज बिल्कुल मेल खाते हैं। लेकिन मैं आश्वस्त नहीं हूं कि यह अतिरिक्त जानकारी आधार चौराहे के संबंधों का हिस्सा होनी चाहिए। उदाहरण के लिए, जब दो अंतराल संयोग या अतिव्याप्ति न होते हुए भी समान लंबाई के होते हैं, तो क्या इसे एक और "संबंध" माना जाना चाहिए? मैं कहता हूं कि नहीं, और इस अतिरिक्त पहलू को देखने के रूप में बी 7 को बी 6 से अलग बनाने वाली एकमात्र चीज है, तो मुझे लगता है कि एंडपॉइंट्स के रूप में-अलग-अलग मामले चीजों को असंगत बनाते हैं।
एरिक

@Emtucifor: ठीक है - मैं देखता हूं कि मैंने 'से पहले:' से पहले और 'के बाद:' के बाद गलतियाँ क्यों कीं; हालाँकि, मैं यह नहीं देख सकता कि 'प्रारंभ: प्रारंभ' और 'अंत: अंत' प्रविष्टियाँ क्या दिखना चाहिए। चूँकि आप मेरे आरेख को संपादित नहीं कर सकते हैं, क्या आप मुझे 'स्टार्ट: स्टार्ट' और 'एंड: एंड' रिश्तों को दर्शाने वाले आरेख की संशोधित प्रति के साथ मुझे (मेरी प्रोफाइल को देख सकते हैं) ईमेल कर सकते हैं? आपके समूहों के साथ मेरा कोई बड़ा मसला नहीं है।
जोनाथन लेफ्लर

30

यदि ओवरलैप खुद भी गणना की जानी चाहिए, तो आप निम्न सूत्र का उपयोग कर सकते हैं:

overlap = max(0, min(EndDate1, EndDate2) - max(StartDate1, StartDate2))
if (overlap > 0) { 
    ...
}

इसलिए ओवरलैप वह समय है जो दो घटनाओं को साझा करता है? क्या यह सभी अलग-अलग तरीकों की घटनाओं के लिए काम कर सकता है?
NSjonas

18

सभी समाधान जो परिस्थितियों की एक भीड़ की जांच करते हैं, जिनके आधार पर सीमाएं एक दूसरे के संबंध में होती हैं, केवल यह सुनिश्चित करके बहुत सरल किया जा सकता है कि एक विशिष्ट सीमा पहले शुरू होती है! आप यह सुनिश्चित करते हैं कि पहली सीमा पहले (या उसी समय) शुरू होती है, यदि आवश्यक हो तो सामने की सीमाओं को स्वैप करके।

फिर, आप ओवरलैप का पता लगा सकते हैं यदि अन्य श्रेणी की शुरुआत पहली श्रेणी के छोर से कम या बराबर है (यदि रेंज समावेशी हैं, जिसमें प्रारंभ और समाप्ति समय दोनों शामिल हैं) या उससे कम (यदि रेंज प्रारंभ और अंतिम के अनन्य शामिल हैं) ।

दोनों सिरों को सम्मिलित करते हुए, केवल चार संभावनाएँ हैं जिनमें से एक गैर-ओवरलैप है:

|----------------------|        range 1
|--->                           range 2 overlap
 |--->                          range 2 overlap
                       |--->    range 2 overlap
                        |--->   range 2 no overlap

श्रेणी 2 का समापन बिंदु इसमें दर्ज नहीं होता है। तो, छद्म कोड में:

def doesOverlap (r1, r2):
    if r1.s > r2.s:
        swap r1, r2
    if r2.s > r1.e:
        return false
    return true

इसे और भी सरल बनाया जा सकता है:

def doesOverlap (r1, r2):
    if r1.s > r2.s:
        swap r1, r2
    return r2.s <= r1.e

पर्वतमाला अंत में शुरू और अनन्य में शामिल हैं, तो आप बस बदलने के लिए >के साथ >=दूसरे में ifबयान (पहले कोड खंड के लिए: दूसरे कोड खंड में आप उपयोग करेंगे <के बजाय <=):

|----------------------|        range 1
|--->                           range 2 overlap
 |--->                          range 2 overlap
                       |--->    range 2 no overlap
                        |--->   range 2 no overlap

आपके द्वारा किए जाने वाले चेक की संख्या को आप बहुत सीमित कर देते हैं क्योंकि आप रेंज 2 को शुरू करने के बाद सीमा 1 को सुनिश्चित करके समस्या की आधी जगह को हटा देते हैं।


2
समावेशी / अनन्य समस्या का उल्लेख करने के लिए +1। मैं अपने आप को जवाब देने के लिए जा रहा था जब मेरे पास समय था, लेकिन अब कोई ज़रूरत नहीं है। बात यह है कि आप शुरू और अंत दोनों को एक साथ समावेशी होने की अनुमति नहीं देते हैं। मेरे उद्योग में शुरू को विशेष और अंत को समावेशी के रूप में व्यवहार करना आम बात है, लेकिन जब तक आप लगातार बने रहते हैं, तब तक दोनों तरह से ठीक है। यह इस सवाल पर अब तक का पहला पूरी तरह से सही उत्तर है ... IMO।
ब्रायन गिदोन

14

यहां जावास्क्रिप्ट का उपयोग करना अभी तक एक और समाधान है। मेरे समाधान की विशेषताएं:

  • अनंत के रूप में अशक्त मूल्यों को संभालता है
  • मान लेता है कि निचला बाउंड समावेशी है और ऊपरी बाउंड अनन्य है।
  • परीक्षणों का एक गुच्छा के साथ आता है

परीक्षण पूर्णांकों पर आधारित होते हैं, लेकिन चूंकि जावास्क्रिप्ट में ऑब्जेक्ट्स तुलनीय हैं, आप सिर्फ दो डेट ऑब्जेक्ट्स में भी फेंक सकते हैं। या आप मिलीसेकंड टाइमस्टैम्प में फेंक सकते हैं।

कोड:

/**
 * Compares to comparable objects to find out whether they overlap.
 * It is assumed that the interval is in the format [from,to) (read: from is inclusive, to is exclusive).
 * A null value is interpreted as infinity
 */
function intervalsOverlap(from1, to1, from2, to2) {
    return (to2 === null || from1 < to2) && (to1 === null || to1 > from2);
}

टेस्ट:

describe('', function() {
    function generateTest(firstRange, secondRange, expected) {
        it(JSON.stringify(firstRange) + ' and ' + JSON.stringify(secondRange), function() {
            expect(intervalsOverlap(firstRange[0], firstRange[1], secondRange[0], secondRange[1])).toBe(expected);
        });
    }

    describe('no overlap (touching ends)', function() {
        generateTest([10,20], [20,30], false);
        generateTest([20,30], [10,20], false);

        generateTest([10,20], [20,null], false);
        generateTest([20,null], [10,20], false);

        generateTest([null,20], [20,30], false);
        generateTest([20,30], [null,20], false);
    });

    describe('do overlap (one end overlaps)', function() {
        generateTest([10,20], [19,30], true);
        generateTest([19,30], [10,20], true);

        generateTest([10,20], [null,30], true);
        generateTest([10,20], [19,null], true);
        generateTest([null,30], [10,20], true);
        generateTest([19,null], [10,20], true);
    });

    describe('do overlap (one range included in other range)', function() {
        generateTest([10,40], [20,30], true);
        generateTest([20,30], [10,40], true);

        generateTest([10,40], [null,null], true);
        generateTest([null,null], [10,40], true);
    });

    describe('do overlap (both ranges equal)', function() {
        generateTest([10,20], [10,20], true);

        generateTest([null,20], [null,20], true);
        generateTest([10,null], [10,null], true);
        generateTest([null,null], [null,null], true);
    });
});

कर्म और चमेली और प्रेत JS के साथ चलाने पर परिणाम:

फैंटमज 1.9.8 (लिनक्स): 20 में से 20 SUCCESS (0.003 सेकेंड / 0.004 सेकेंड)


9

मुझे क्या करना होगा

StartDate1.IsBetween(StartDate2, EndDate2) || EndDate1.IsBetween(StartDate2, EndDate2)

जहां IsBetweenकुछ ऐसा है

    public static bool IsBetween(this DateTime value, DateTime left, DateTime right) {
        return (value > left && value < right) || (value < left && value > right);
    }

मैं पसंद करूँगा (बायाँ <value && value <right) || (इस विधि के लिए दाएँ <मान और& मान <बाएँ)।
पैट्रिक Huizinga

इसके लिए धन्यवाद। मेरे सिर में चीजों को आसान बनाता है।
15

1
जब आप केवल दो की जाँच करेंगे तो आप चार शर्तों की जाँच क्यों करेंगे? असफल।
एरिक

3
आह, मेरी क्षमायाचना, मैं अब देख रहा हूं कि आप श्रेणियों को रिवर्स ऑर्डर में होने की अनुमति दे रहे हैं (StartDateX> EndDateX)। अजीब। वैसे भी, क्या होगा अगर StartDate1 StartDate2 से कम है और EndDate1 EndDate2 से अधिक है? आपके द्वारा दिया गया कोड इस अतिव्यापी स्थिति का पता नहीं लगाएगा।
एरिक

3
क्या यह रिटर्न गलत नहीं होगा अगर Date1 में पूरी Date2 शामिल है? तब StartDate1 StartDate2 से पहले है और EndDate1 EndDate2 के बाद है
user158037

9

यहां छवि विवरण दर्ज करें

यहाँ कोड है कि जादू करता है:

 var isOverlapping =  ((A == null || D == null || A <= D) 
            && (C == null || B == null || C <= B)
            && (A == null || B == null || A <= B)
            && (C == null || D == null || C <= D));

कहाँ पे..

  • ए -> 1 स्टार्ट
  • बी -> 1 ई
  • C -> 2Start
  • डी -> 2 ई

सबूत? इस परीक्षण कंसोल कोड की जाँच करें ।


यह काम करता है, लेकिन मैं ओवरलैपिंग नहीं, केवल दो परिदृश्यों के लिए परीक्षण करना पसंद करूंगा
जॉन अल्बर्ट

छवियों का उपयोग करके यह समझाने के लिए धन्यवाद। आपका जवाब इस सवाल का सही समाधान है।
राकेश वर्मा

8

यहाँ जावा में मेरा समाधान है , जो अबाधित अंतराल पर भी काम करता है

private Boolean overlap (Timestamp startA, Timestamp endA,
                         Timestamp startB, Timestamp endB)
{
    return (endB == null || startA == null || !startA.after(endB))
        && (endA == null || startB == null || !endA.before(startB));
}

मुझे लगता है कि आप खुले अंतराल के बजाय अनबाउंड समाप्त होते हैं।
हेनरिक

@ हेनरिक दोनों पद en.wikipedia.org/wiki/Interval_(mathematics)#Terminology
Khaled.K

!startA.after(endB)मतलब startA <= endB और !endA.before(startB)इसका मतलब startB <= endA है। ये एक बंद अंतराल के लिए मानदंड हैं और एक खुले अंतराल नहीं हैं।
हेनरिक

@ हेनरिक सच, और अन्य शर्तों जैसे कि endB == nullऔर startA == nullएक खुले अंतराल के लिए जाँच करें।
खालिद.के

1
endB == null, startA == null, endA == nullऔर startB == nullएक असीम अंतराल के लिए जाँच करने के लिए सभी मानदंडों को और नहीं एक खुला अंतराल कर रहे हैं। अनबाउंड और ओपन अंतराल के बीच अंतर के लिए उदाहरण: (10, 20) और (20, नल) दो खुले अंतराल हैं जो ओवरलैप नहीं होते हैं। आखिरी में एक अनबाउंड एंड होता है। आपका कार्य सही हो जाएगा, लेकिन अंतराल ओवरलैप नहीं होता है, क्योंकि अंतराल में 20 शामिल नहीं हैं। (सादगी के लिए टाइमस्टैम्प के बजाय संख्या का उपयोग किया जाता है)
हेनरिक

7

यहां पोस्ट किए गए समाधान ने सभी अतिव्यापी सीमाओं के लिए काम नहीं किया ...

---------------------- | ------- एक ------- | ----------- -----------
    | ---- बी 1 ---- |
           | ---- बी 2 ---- |
               | ---- बी 3 ---- |
               | ---------- बी 4 ---------- |
               | ---------------- B5 ---------------- |
                      | ---- बी -6 ---- |
---------------------- | ------- एक ------- | ----------- -----------
                      | ------ बी 7 ------- |
                      | ---------- B8 ----------- |
                         | ---- B9 ---- |
                         | ---- B10 ----- |
                         | -------- B11 -------- |
                                      | ---- बी 12 ---- |
                                         | ---- B13 ---- |
---------------------- | ------- एक ------- | ----------- -----------

मेरा कार्य समाधान था:

तथा (
  ('start_date' BETWEEN STARTDATE और ENDDATE) - आंतरिक और अंतिम तिथि बाहरी के लिए पूरा करता है
  या
  ('end_date' BETWEEN STARTDATE और ENDDATE) - आंतरिक और आरंभ तिथि के बाहरी के लिए पूरा करता है
  या
  (STARTDATE BETWEEN 'start_date' और 'end_date') - बाहरी सीमा के लिए केवल एक ही आवश्यक है जहाँ दिनांक अंदर हैं।
) 

5

पल के साथ यह मेरी जावास्क्रिप्ट समाधान था। js:

// Current row dates
var dateStart = moment("2014-08-01", "YYYY-MM-DD");
var dateEnd = moment("2014-08-30", "YYYY-MM-DD");

// Check with dates above
var rangeUsedStart = moment("2014-08-02", "YYYY-MM-DD");
var rangeUsedEnd = moment("2014-08-015", "YYYY-MM-DD");

// Range covers other ?
if((dateStart <= rangeUsedStart) && (rangeUsedEnd <= dateEnd)) {
    return false;
}
// Range intersects with other start ?
if((dateStart <= rangeUsedStart) && (rangeUsedStart <= dateEnd)) {
    return false;
}
// Range intersects with other end ?
if((dateStart <= rangeUsedEnd) && (rangeUsedEnd <= dateEnd)) {
    return false;
}

// All good
return true;

4

समाधान याद रखने का एक आसान तरीका होगा
min(ends)>max(starts)


3

Microsoft SQL सर्वर में - SQL फ़ंक्शन

CREATE FUNCTION IsOverlapDates 
(
    @startDate1 as datetime,
    @endDate1 as datetime,
    @startDate2 as datetime,
    @endDate2 as datetime
)
RETURNS int
AS
BEGIN
DECLARE @Overlap as int
SET @Overlap = (SELECT CASE WHEN  (
        (@startDate1 BETWEEN @startDate2 AND @endDate2) -- caters for inner and end date outer
        OR
        (@endDate1 BETWEEN @startDate2 AND @endDate2) -- caters for inner and start date outer
        OR
        (@startDate2 BETWEEN @startDate1 AND @endDate1) -- only one needed for outer range where dates are inside.
        ) THEN 1 ELSE 0 END
    )
    RETURN @Overlap

END
GO

--Execution of the above code
DECLARE @startDate1 as datetime
DECLARE @endDate1 as datetime
DECLARE @startDate2 as datetime
DECLARE @endDate2 as datetime
DECLARE @Overlap as int
SET @startDate1 = '2014-06-01 01:00:00' 
SET @endDate1 =   '2014-06-01 02:00:00'
SET @startDate2 = '2014-06-01 01:00:00' 
SET @endDate2 =   '2014-06-01 01:30:00'

SET @Overlap = [dbo].[IsOverlapDates]  (@startDate1, @endDate1, @startDate2, @endDate2)

SELECT Overlap = @Overlap

3

सबसे आसान

सबसे आसान तरीका है, तारीख-समय के काम के लिए एक अच्छी तरह से इंजीनियर समर्पित पुस्तकालय का उपयोग करना।

someInterval.overlaps( anotherInterval )

java.time और थ्रीटेन-एक्सट्रा

व्यवसाय में सबसे अच्छा java.timeजावा 8 और बाद में बनाया गया ढांचा है। थ्रीटैन-एक्स्ट्रा प्रोजेक्ट में जोड़ें जो अतिरिक्त कक्षाओं के साथ java.time को पूरक करता है, विशेष रूप से वह Intervalवर्ग जिसकी हमें यहां आवश्यकता है।

के रूप में language-agnosticइस सवाल पर टैग, दोनों परियोजनाओं के लिए स्रोत कोड अन्य भाषाओं (उनके लाइसेंस मन) में उपयोग के लिए उपलब्ध है।

Interval

org.threeten.extra.Intervalवर्ग से उपयोगी है, लेकिन आज के समय क्षणों (की आवश्यकता java.time.Instantकी वस्तुओं) के बजाय तारीख-केवल मान। इसलिए हम तारीख का प्रतिनिधित्व करने के लिए UTC में दिन के पहले क्षण का उपयोग करके आगे बढ़ते हैं।

Instant start = Instant.parse( "2016-01-01T00:00:00Z" );
Instant stop = Instant.parse( "2016-02-01T00:00:00Z" );

Intervalउस समय का प्रतिनिधित्व करने के लिए एक बनाएँ ।

Interval interval_A = Interval.of( start , stop );

हम Intervalएक प्रारंभिक क्षण के साथ भी परिभाषित कर सकते हैं प्लस ए Duration

Instant start_B = Instant.parse( "2016-01-03T00:00:00Z" );
Interval interval_B = Interval.of( start_B , Duration.of( 3 , ChronoUnit.DAYS ) );

ओवरलैप के लिए परीक्षण की तुलना करना आसान है।

Boolean overlaps = interval_A.overlaps( interval_B );

आप Intervalदूसरे के खिलाफ तुलना कर सकते हैं Intervalया Instant:

ये सभी Half-Openसमय की अवधि को परिभाषित करने के लिए दृष्टिकोण का उपयोग करते हैं, जहां शुरुआत समावेशी है और समाप्ति अनन्य है


3

यह @ charles-bretana द्वारा उत्कृष्ट उत्तर के लिए एक विस्तार है ।

हालांकि उत्तर खुले, बंद और आधे खुले (या आधे-बंद) अंतरालों के बीच अंतर नहीं करता है।

केस 1 : ए, बी बंद अंतराल हैं

A = [StartA, EndA]
B = [StartB, EndB]

                         [---- DateRange A ------]   (True if StartA > EndB)
[--- Date Range B -----]                           


[---- DateRange A -----]                             (True if EndA < StartB)
                         [--- Date Range B ----]

ओवरलैप iff: (StartA <= EndB) and (EndA >= StartB)

केस 2 : ए, बी खुले अंतराल हैं

A = (StartA, EndA)
B = (StartB, EndB)

                         (---- DateRange A ------)   (True if StartA >= EndB)
(--- Date Range B -----)                           

(---- DateRange A -----)                             (True if EndA <= StartB)
                         (--- Date Range B ----)

ओवरलैप iff: (StartA < EndB) and (EndA > StartB)

केस 3 : ए, बी राइट ओपन

A = [StartA, EndA)
B = [StartB, EndB)

                         [---- DateRange A ------)   (True if StartA >= EndB) 
[--- Date Range B -----)                           

[---- DateRange A -----)                             (True if EndA <= StartB)
                         [--- Date Range B ----)

ओवरलैप की स्थिति: (StartA < EndB) and (EndA > StartB)

केस 4 : ए, बी खुला छोड़ दिया

A = (StartA, EndA]
B = (StartB, EndB]

                         (---- DateRange A ------]   (True if StartA >= EndB)
(--- Date Range B -----]                           

(---- DateRange A -----]                             (True if EndA <= StartB)
                         (--- Date Range B ----]

ओवरलैप की स्थिति: (StartA < EndB) and (EndA > StartB)

केस 5 : एक सही खुला, बी बंद

A = [StartA, EndA)
B = [StartB, EndB]

                         [---- DateRange A ------)    (True if StartA > EndB)
[--- Date Range B -----]                           


[---- DateRange A -----)                              (True if EndA <= StartB)  
                         [--- Date Range B ----]

ओवरलैप की स्थिति: (StartA <= EndB) and (EndA > StartB)

आदि...

अंत में, ओवरलैप करने के लिए दो अंतराल के लिए सामान्य स्थिति है

(StartA <Start EndB) और (EndA>) StartB)

जहाँ where एक सख्त असमानता को एक गैर-सख्त में बदल देता है, जब भी दो सम्मिलित समापन बिंदु के बीच तुलना की जाती है।


मामलों दो, तीन और चार में एक ही ओवरलैप की स्थिति है, क्या यह जानबूझकर है?
मैरी

@ मैरी, मैंने अभी कुछ मामलों को सूचीबद्ध किया है (सभी नहीं)
user2314737

यह, लेकिन जैसा कि जोनाथन लेफ़लर के जवाब के रूप में विस्तृत है कि ओपी प्रश्न के लिए स्वीकृत जवाब के रूप में मेरे मन में क्या था।
mbx

3

क्षणिकाओं का उपयोग करते हुए लघु उत्तर :

function isOverlapping(startDate1, endDate1, startDate2, endDate2){ 
    return moment(startDate1).isSameOrBefore(endDate2) && 
    moment(startDate2).isSameOrBefore(endDate1);
}

उत्तर उपरोक्त उत्तरों पर आधारित है, लेकिन इसका संक्षिप्त रूप है।


2

यदि आप ऐसी तिथि सीमा का उपयोग कर रहे हैं जो अभी तक समाप्त नहीं हुई है (अभी भी चल रही है) जैसे कि सेट न करें EndDate = '0000-00-00' आप BETWEEN का उपयोग नहीं कर सकते क्योंकि 0000-00-00 एक वैध तिथि नहीं है!

मैंने इस समाधान का उपयोग किया:

(Startdate BETWEEN '".$startdate2."' AND '".$enddate2."')  //overlap: starts between start2/end2
OR (Startdate < '".$startdate2."' 
  AND (enddate = '0000-00-00' OR enddate >= '".$startdate2."')
) //overlap: starts before start2 and enddate not set 0000-00-00 (still on going) or if enddate is set but higher then startdate2

यदि startdate2 अधिक है तो एंडडेट है कोई ओवरलैप नहीं है!


2

इसका उत्तर मेरे लिए बहुत सरल है इसलिए मैंने एक अधिक सामान्य गतिशील SQL स्टेटमेंट बनाया है जो यह देखने के लिए जांचता है कि क्या किसी व्यक्ति के पास ओवरलैपिंग की तारीखें हैं या नहीं।

SELECT DISTINCT T1.EmpID
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.EmpID = T2.EmpID 
    AND T1.JobID <> T2.JobID
    AND (
        (T1.DateFrom >= T2.DateFrom AND T1.dateFrom <= T2.DateTo) 
        OR (T1.DateTo >= T2.DateFrom AND T1.DateTo <= T2.DateTo)
        OR (T1.DateFrom < T2.DateFrom AND T1.DateTo IS NULL)
    )
    AND NOT (T1.DateFrom = T2.DateFrom)

2

@Bretana द्वारा दिया गया गणितीय समाधान अच्छा है लेकिन दो विशिष्ट विवरणों की उपेक्षा करता है:

  1. बंद या आधे खुले अंतराल का पहलू
  2. खाली अंतराल

अंतराल सीमाओं के बंद या खुले राज्य के बारे में, @Bretana का समाधान बंद अंतराल के लिए मान्य है

(StartA <= EndB) और (EndA> = StartB)

आधे-खुले अंतराल के लिए फिर से लिखा जा सकता है:

(StartA <EndB) और (EndA> StartB)

यह सुधार आवश्यक है क्योंकि एक खुली अंतराल सीमा परिभाषा द्वारा अंतराल के मूल्य सीमा से संबंधित नहीं है।


और खाली अंतराल के बारे में , ठीक है, यहाँ ऊपर दिखाया गया संबंध नहीं है। खाली अंतराल जिसमें परिभाषा के अनुसार कोई वैध मूल्य नहीं होता है उन्हें विशेष मामले के रूप में संभाला जाना चाहिए। मैं इस उदाहरण के माध्यम से अपने जावा समय पुस्तकालय Time4J द्वारा प्रदर्शित करता हूं :

MomentInterval a = MomentInterval.between(Instant.now(), Instant.now().plusSeconds(2));
MomentInterval b = a.collapse(); // make b an empty interval out of a

System.out.println(a); // [2017-04-10T05:28:11,909000000Z/2017-04-10T05:28:13,909000000Z)
System.out.println(b); // [2017-04-10T05:28:11,909000000Z/2017-04-10T05:28:11,909000000Z)

प्रमुख वर्ग ब्रैकेट "[" एक बंद शुरुआत को इंगित करता है जबकि अंतिम ब्रैकेट ")" एक खुले अंत को इंगित करता है।

System.out.println(
      "startA < endB: " + a.getStartAsInstant().isBefore(b.getEndAsInstant())); // false
System.out.println(
      "endA > startB: " + a.getEndAsInstant().isAfter(b.getStartAsInstant())); // true

System.out.println("a overlaps b: " + a.intersects(b)); // a overlaps b: false

जैसा कि ऊपर दिखाया गया है, खाली अंतराल ऊपर की ओवरलैप स्थिति का उल्लंघन करता है (विशेष रूप से startA <endB), इसलिए Time4J (और अन्य लाइब्रेरीज़, भी) को यह सुनिश्चित करने के लिए विशेष एज केस के रूप में संभालना पड़ता है ताकि किसी खाली अंतराल के साथ किसी भी मनमाने अंतराल की ओवरलैप हो सके। अस्तित्व में नहीं है। बेशक, तिथि अंतराल (जो कि Time4J में डिफ़ॉल्ट रूप से बंद हो जाते हैं लेकिन आधे खुले हो सकते हैं, जैसे कि खाली तिथि अंतराल) को भी इसी तरह से संभाला जाता है।


1

यहां एक सामान्य विधि है जो स्थानीय रूप से उपयोगी हो सकती है।

    // Takes a list and returns all records that have overlapping time ranges.
    public static IEnumerable<T> GetOverlappedTimes<T>(IEnumerable<T> list, Func<T, bool> filter, Func<T,DateTime> start, Func<T, DateTime> end)
    {
        // Selects all records that match filter() on left side and returns all records on right side that overlap.
        var overlap = from t1 in list
                      where filter(t1)
                      from t2 in list
                      where !object.Equals(t1, t2) // Don't match the same record on right side.
                      let in1 = start(t1)
                      let out1 = end(t1)
                      let in2 = start(t2)
                      let out2 = end(t2)
                      where in1 <= out2 && out1 >= in2
                      let totover = GetMins(in1, out1, in2, out2)
                      select t2;

        return overlap;
    }

    public static void TestOverlap()
    {
        var tl1 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 1:00pm".ToDate(), Out = "1/1/08 4:00pm".ToDate() };
        var tl2 = new TempTimeEntry() { ID = 2, Name = "John", In = "1/1/08 5:00pm".ToDate(), Out = "1/1/08 6:00pm".ToDate() };
        var tl3 = new TempTimeEntry() { ID = 3, Name = "Lisa", In = "1/1/08 7:00pm".ToDate(), Out = "1/1/08 9:00pm".ToDate() };
        var tl4 = new TempTimeEntry() { ID = 4, Name = "Joe", In = "1/1/08 3:00pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
        var tl5 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 8:01pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
        var list = new List<TempTimeEntry>() { tl1, tl2, tl3, tl4, tl5 };
        var overlap = GetOverlappedTimes(list, (TempTimeEntry t1)=>t1.ID==1, (TempTimeEntry tIn) => tIn.In, (TempTimeEntry tOut) => tOut.Out);

        Console.WriteLine("\nRecords overlap:");
        foreach (var tl in overlap)
            Console.WriteLine("Name:{0} T1In:{1} T1Out:{2}", tl.Name, tl.In, tl.Out);
        Console.WriteLine("Done");

        /*  Output:
            Records overlap:
            Name:Joe T1In:1/1/2008 3:00:00 PM T1Out:1/1/2008 8:00:00 PM
            Name:Lisa T1In:1/1/2008 7:00:00 PM T1Out:1/1/2008 9:00:00 PM
            Done
         */
    }

1
public static class NumberExtensionMethods
    {
        public static Boolean IsBetween(this Int64 value, Int64 Min, Int64 Max)
        {
            if (value >= Min && value <= Max) return true;
            else return false;
        }

        public static Boolean IsBetween(this DateTime value, DateTime Min, DateTime Max)
        {
            Int64 numricValue = value.Ticks;
            Int64 numericStartDate = Min.Ticks;
            Int64 numericEndDate = Max.Ticks;

            if (numricValue.IsBetween(numericStartDate, numericEndDate) )
            {
                return true;
            }

            return false;
        }
    }

public static Boolean IsOverlap(DateTime startDate1, DateTime endDate1, DateTime startDate2, DateTime endDate2)
        {
            Int64 numericStartDate1 = startDate1.Ticks;
            Int64 numericEndDate1 = endDate1.Ticks;
            Int64 numericStartDate2 = startDate2.Ticks;
            Int64 numericEndDate2 = endDate2.Ticks;

            if (numericStartDate2.IsBetween(numericStartDate1, numericEndDate1) ||
                numericEndDate2.IsBetween(numericStartDate1, numericEndDate1) ||
                numericStartDate1.IsBetween(numericStartDate2, numericEndDate2) ||
                numericEndDate1.IsBetween(numericStartDate2, numericEndDate2))
            {
                return true;
            }

            return false;
        } 


if (IsOverlap(startdate1, enddate1, startdate2, enddate2))
            {
                Console.WriteLine("IsOverlap");
            }

3
स्पष्टीकरण के कुछ शब्दों को जोड़ने के लिए मन?
फैंटमैक्स

1

Java का उपयोग करना।

    public static boolean checkTimeOverlaps(Date startDate1, Date endDate1, Date startDate2, Date endDate2)
    {
        if (startDate1 == null || endDate1 == null || startDate2 == null || endDate2 == null)
           return false;

        if ((startDate1.getTime() <= endDate2.getTime()) && (startDate2.getTime() <= endDate1.getTime()))
           return true;

        return false;
    }

1

मेरी राय में इसे करने का सबसे आसान तरीका यह होगा कि यदि या तो EndDate1 StartDate2 से पहले है और EndDate2 StartDate1 से पहले है।

बेशक, अगर आप अंतराल पर विचार कर रहे हैं, जहां स्टार्टडेट हमेशा एंडेड से पहले है।


1

मेरे पास एक ऐसी स्थिति थी जहां हमारे पास डेटेटाइम के बजाय तारीखें थीं, और तारीखें केवल प्रारंभ / समाप्ति पर ओवरलैप हो सकती थीं। नीचे उदाहरण:

यहां छवि विवरण दर्ज करें

(ग्रीन वर्तमान अंतराल है, नीले ब्लॉक वैध अंतराल हैं, लाल वाले अंतराल को ओवरलैप कर रहे हैं)।

मैंने निम्नलिखित समाधान के लिए इयान नेल्सन के उत्तर को अनुकूलित किया:

   (startB <= startA && endB > startA)
|| (startB >= startA && startB < endA)

यह सभी ओवरलैप मामलों से मेल खाता है लेकिन अनुमत ओवरलैप वाले को अनदेखा करता है।


0

मामलों में समस्या को विभाजित करें फिर प्रत्येक मामले को संभालें

स्थिति 'दो तिथि सीमाएं प्रतिच्छेद' दो मामलों से आच्छादित है - पहली तिथि सीमा दूसरी के भीतर शुरू होती है, या दूसरी तिथि सीमा पहले के भीतर शुरू होती है।


0

आप यह कोशिश कर सकते हैं:

//custom date for example
$d1 = new DateTime("2012-07-08");
$d2 = new DateTime("2012-07-11");
$d3 = new DateTime("2012-07-08");
$d4 = new DateTime("2012-07-15");

//create a date period object
$interval = new DateInterval('P1D');
$daterange = iterator_to_array(new DatePeriod($d1, $interval, $d2));
$daterange1 = iterator_to_array(new DatePeriod($d3, $interval, $d4));
array_map(function($v) use ($daterange1) { if(in_array($v, $daterange1)) print "Bingo!";}, $daterange);

0

यह मेरा समाधान था, यह तब सच होता है जब मूल्य ओवरलैप नहीं होते:

X START 1 Y END 1

एक START 2 B END 2

TEST1: (X <= A || X >= B)
        &&
TEST2: (Y >= B || Y <= A) 
        && 
TEST3: (X >= B || Y <= A)


X-------------Y
    A-----B

TEST1:  TRUE
TEST2:  TRUE
TEST3:  FALSE
RESULT: FALSE

---------------------------------------

X---Y
      A---B

TEST1:  TRUE
TEST2:  TRUE
TEST3:  TRUE
RESULT: TRUE

---------------------------------------

      X---Y
A---B

TEST1:  TRUE
TEST2:  TRUE
TEST3:  TRUE
RESULT: TRUE

---------------------------------------

     X----Y
A---------------B

TEST1:  FALSE
TEST2:  FALSE
TEST3:  FALSE
RESULT: FALSE

0

रूबी के लिए मैंने यह भी पाया:

class Interval < ActiveRecord::Base

  validates_presence_of :start_date, :end_date

  # Check if a given interval overlaps this interval    
  def overlaps?(other)
    (start_date - other.end_date) * (other.start_date - end_date) >= 0
  end

  # Return a scope for all interval overlapping the given interval, including the given interval itself
  named_scope :overlapping, lambda { |interval| {
    :conditions => ["id <> ? AND (DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0", interval.id, interval.end_date, interval.start_date]
  }}

end

यहाँ इसे अच्छी व्याख्या के साथ मिला -> http://makandracards.com/makandra/984-test-if-two-date-ranges-overlap-in-ruby-or-rails


0

नीचे क्वेरी मुझे वह आईडी देती है जिसके लिए आपूर्ति की गई तिथि सीमा (आरंभ और समाप्ति तिथियां मेरे टेबल_नाम में किसी भी दिनांक (प्रारंभ और समाप्ति दिनांक) के साथ ओवरलैप होती हैं)

select id from table_name where (START_DT_TM >= 'END_DATE_TIME'  OR   
(END_DT_TM BETWEEN 'START_DATE_TIME' AND 'END_DATE_TIME'))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.