मेरे पास दो दिनांक सीमाएं हैं जहां प्रत्येक श्रेणी प्रारंभ और समाप्ति तिथि (जाहिर है, datetime.date() उदाहरणों द्वारा निर्धारित की जाती है)। दो श्रेणियां ओवरलैप हो सकती हैं या नहीं। मुझे ओवरलैप के दिनों की संख्या चाहिए। निस्संदेह मैं दोनों श्रेणियों के भीतर सभी तिथियों के साथ दो सेट पूर्व-भर सकता हूं और एक सेट चौराहे का प्रदर्शन कर सकता हूं लेकिन यह संभवतः अक्षम है ... क्या सभी मामलों को कवर करने वाले लंबे समय तक अगर एलीफ सेक्शन का उपयोग करके एक और समाधान से अलग बेहतर तरीका है?पाइथन में कुशल तिथि सीमा ओवरलैप गणना?
उत्तर
- दो आरंभ तिथियों में से नवीनतम और दो समाप्ति तिथियों में से सबसे पहले निर्धारित करें।
- उन्हें घटाने के द्वारा timedelta की गणना करें।
- यदि डेल्टा सकारात्मक है, तो ओवरलैप के दिनों की संख्या है।
यहाँ एक उदाहरण गणना है:
>>> from datetime import datetime
>>> from collections import namedtuple
>>> Range = namedtuple('Range', ['start', 'end'])
>>> r1 = Range(start=datetime(2012, 1, 15), end=datetime(2012, 5, 10))
>>> r2 = Range(start=datetime(2012, 3, 20), end=datetime(2012, 9, 15))
>>> latest_start = max(r1.start, r2.start)
>>> earliest_end = min(r1.end, r2.end)
>>> delta = (earliest_end - latest_start).days + 1
>>> overlap = max(0, delta)
>>> overlap
52
स्यूडोकोड:
1 + max(-1, min(a.dateEnd, b.dateEnd) - max(a.dateStart, b.dateStart))
समारोह कॉल अंकगणितीय आपरेशनों से ज्यादा महंगे हैं।
ऐसा करने का सबसे तेज़ तरीका 2 subtractions और 1 मिनट() शामिल है:
min(r1.end - r2.start, r2.end - r1.start).days + 1
अगला सबसे अच्छा जो 1 घटाव, 1 मिनट() और एक अधिकतम() की जरूरत है के साथ तुलना में:
(min(r1.end, r2.end) - max(r1.start, r2.start)).days + 1
बेशक दोनों अभिव्यक्तियों के साथ आपको अभी भी एक सकारात्मक ओवरलैप की जांच करने की आवश्यकता है।
यह विधि हमेशा सही उत्तर नहीं देगी। जैसे'रेंज = नामित ('रेंज', ['स्टार्ट', 'एंड']) आर 1 = रेंज (स्टार्ट = डेटटाइम (2016, 6, 15), एंड = डेटाटाइम (2016, 6, 15)) आर 2 = रेंज (प्रारंभ = डेटाटाइम (2016, 6, 11), अंत = डेटाटाइम (2016, 6, 18)) प्रिंट मिनट (r1.end - r2.start, r2.end - r1.start)। दिन + 1' प्रिंट करेगा 4 जहां यह 1 – tkyass
def get_overlap(r1,r2):
latest_start=max(r1[0],r2[0])
earliest_end=min(r1[1],r2[1])
delta=(earliest_end-latest_start).days
if delta>0:
return delta+1
else:
return 0
मैंने टाइमरेंज क्लास को कार्यान्वित किया जैसा कि आप नीचे देख सकते हैं।
get_overlapped_range पहले सभी गैर ओवरलैप्ड विकल्पों को एक साधारण स्थिति से अस्वीकार करता है, और फिर सभी संभावित विकल्पों पर विचार करके ओवरलैप्ड रेंज की गणना करता है।
वर्ग TimeRange (वस्तु):
def __init__(self, start, end):
self.start = start
self.end = end
self.duration = self.end - self.start
def is_overlapped(self, time_range):
if max(self.start, time_range.start) < min(self.end, time_range.end):
return True
else:
return False
def get_overlapped_range(self, time_range):
if not self.is_overlapped(time_range):
return
if time_range.start >= self.start:
if self.end >= time_range.end:
return TimeRange(time_range.start, time_range.end)
else:
return TimeRange(time_range.start, self.end)
elif time_range.start < self.start:
if time_range.end >= self.end:
return TimeRange(self.start, self.end)
else:
return TimeRange(self.start, time_range.end)
def __repr__(self):
return '{0} ------> {1}'.format(*[time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(d))
for d in [self.start, self.end]])
दिनों की राशि है जो आप TimeRange मूल्य कि get_overlapped_range से लौटाए गए लेने के लिए और 60 * 60 * 24 (द्वारा अवधि को विभाजित करने की आवश्यकता होगी पाने के लिए
प्रिंट करने के लिए प्रतीत होता है ओपी के मुद्दे के लिए पहले से ही एक आदर्श समाधान है। –
उत्कृष्ट उत्तर –
+1 'रेंज' नामक tuple बनाने के लिए +1 :-) – GaretJax
सुरुचिपूर्ण कोड के लिए +1। मैंने अभी यह दिनचर्या ली और इसे मेरे PHP ऐप में इस्तेमाल किया। – Eric