2016-06-16 21 views
5

Tôi đang tìm để tìm ngày trùng lặp giữa hai ngày dao động như sau:ngày trùng lặp giữa hai phạm vi ngày trong python

range1 = start(2016-06-01) end (2016-06-20) 
range2 = start(2016-06-10) end (2016-06-13) 

kết quả ở đây là 4 ngày (2016-06-10,2016-06-11,2016-06-12,2016-06-13). ví dụ khác:

range1 = start(2016-06-01) end (2016-06-20) range2 = start(2016-06-18) 
end (2016-06-25) 

kết quả ở đây là 3 ngày (2016-06-18,2016-06-19,2016-06-20). và nếu không có ngày trùng lặp thì kết quả là 0 ngày.

Tôi tìm thấy this đăng bài hữu ích trong việc xác định số ngày trùng lặp nhưng tôi đã tự hỏi liệu tôi có thể nhận được ngày thực tế mà không sử dụng câu lệnh if/else dài không?

Cảm ơn trước!

Trả lời

2

Tôi khuyên bạn nên tạo ngày trong mỗi phạm vi, sau đó chọn giao điểm giữa hai tập hợp. Một Snipped làm như vậy có thể trông như thế này:

from datetime import date, timedelta 


def f(d1, d2): 
    delta = d2 - d1 
    return set([d1 + timedelta(days=i) for i in range(delta.days + 1)]) 

range1 = [date(2016, 6, 1), date(2016, 6, 20)] 
range2 = [date(2016, 6, 10), date(2016, 6, 13)] 

print f(*range1) & f(*range2) 

Đối với mục đích hiệu suất mà bạn cũng có thể đúc d1 + timedelta(days=i)-str khi tạo ngày trong một phạm vi nhất định.

+0

Cảm ơn Kardaj! chỉ cần tự hỏi về phần hiệu suất, tại sao đúc thành chuỗi sẽ cải thiện hiệu suất? – tkyass

+0

Vì trong trường hợp bạn định tạo nhiều ngày, bạn muốn lưu trữ cấu trúc dữ liệu ít phức tạp hơn như một chuỗi trong trường hợp này, sẽ không dẫn đến mất thông tin. – kardaj

1

Khi bạn chưa làm việc với Python3 và do đó không thể sử dụng các đối tượng hiệu quả của bộ nhớ range, bạn có thể tạo một tên được đặt trong the answer you link to (nếu không bạn cũng có thể sử dụng đối tượng range mới). Từ đó, tất cả các bạn cần làm là sử dụng datetime.date.fromordinal trên datarange chồng chéo:

>>> from datetime import date 
>>> from collections import namedtuple 
>>> Range = namedtuple('Range', ['start', 'end']) 
>>> r1 = Range(start=date(2016, 1, 1), end=date(2016, 2, 5)) 
>>> r2 = Range(start=date(2016, 1, 28), end=date(2016, 2, 28)) 
>>> latest_start = max(r1.start, r2.start) 
>>> earliest_end = min(r1.end, r2.end) 
>>> overlap = (earliest_end - latest_start).days + 1 
>>> overlapping_dates = [] # default 
>>> if overlap > 0: 
...  overlapping_dates = range(latest_start.toordinal(), earliest_end.toordinal() + 1) # as numbers 
...  overlapping_dates = [ date.fromordinal(x) for x in overlapping_dates ] # back to datetime.date objects 
... 
>>> overlapping_dates 
[datetime.date(2016, 1, 28), 
datetime.date(2016, 1, 29), 
datetime.date(2016, 1, 30), 
datetime.date(2016, 1, 31), 
datetime.date(2016, 2, 1), 
datetime.date(2016, 2, 2), 
datetime.date(2016, 2, 3), 
datetime.date(2016, 2, 4), 
datetime.date(2016, 2, 5)] 

Một cách tiếp cận sử dụng set sẽ làm việc quá (một trong những cách tiếp cận là trong lịch sử sửa đổi của câu trả lời này), nhưng thường là kém hiệu quả, bởi vì nó phải có tất cả ngày trong bộ nhớ, ngay cả những ngày không ở trong giao lộ.

0

Tôi đã viết một chức năng nhỏ cho điều này thời gian gần đây, trong đó trả về cho dù có sự chồng chéo và sau đó là từ-to dao động

def date_overlap(start1, end1, start2, end2): 
    overlaps = start1 <= end2 and end1 >= start2 
    if not overlaps: 
     return False, None, None 
    return True, max(start1, start2), min(end1, end2) 

Rõ ràng là định dạng đầu ra có thể được thích nghi với bất cứ điều gì là cần thiết.

Các vấn đề liên quan