Reputation: 29465
What is the most pythonic way to check if a date period is embraced by another date period in python?
for example
start_1 = datetime.datetime(2016, 3, 16, 20, 30)
end_1 = datetime.datetime(2016, 3, 17, 20, 30)
start_2 = datetime.datetime(2016, 3, 14, 20, 30)
end_2 = datetime.datetime(2016, 3, 17, 22, 30)
so [start_1, end_1]
obviously lies inside [start_2, end_2]
, you can check it by using <
, >
operators, but I'd like to know if there's a library function to perform this check easily.
Upvotes: 1
Views: 632
Reputation: 24802
You can do that using a pip module:
pip install DateTimeRange
which can be used:
>>> start_1 = datetime.datetime(2016, 3, 16, 20, 30)
>>> end_1 = datetime.datetime(2016, 3, 17, 20, 30)
>>> start_2 = datetime.datetime(2016, 3, 14, 20, 30)
>>> end_2 = datetime.datetime(2016, 3, 17, 22, 30)
>>> dtr1 = datetimerange.DateTimeRange(start_1, end_1)
>>> dtr2 = datetimerange.DateTimeRange(start_2, end_2)
You can check whether one range intersects the other:
>>> dtr1.is_intersection(dtr2)
True
But it does not show whether the range is fully within the other. To check whether a time range contains another, you still have to check boundaries:
>>> dtr1.start_datetime in dtr2
True
>>> dtr1.end_datetime in dtr2
True
Though I believe this is a good opportunity for a patch, to implement the __contains__
method in a fashion that supports for datetimerange
as LHS argument of the in
operator.
>>> dtr1 in dtr2
[…] /datetimerange/__init__.py", line 136, in __contains__
return self.start_datetime <= value <= self.end_datetime
TypeError: unorderable types: datetime.datetime() <= DateTimeRange()
Nota Bene: I have pushed a commit to make that possible, so now the following works:
>>> import datetime
>>> import datetimerange
>>> start_1 = datetime.datetime(2016, 3, 16, 20, 30)
>>> start_2 = datetime.datetime(2016, 3, 14, 20, 30)
>>> end_1 = datetime.datetime(2016, 3, 17, 20, 30)
>>> end_2 = datetime.datetime(2016, 3, 17, 22, 30)
>>> dtr1 = datetimerange.DateTimeRange(start_1, end_1)
>>> dtr2 = datetimerange.DateTimeRange(start_2, end_2)
>>>
>>> dtr1 in dtr2
True
>>> dtr2 in dtr1
False
HTH
Upvotes: 3
Reputation: 2013
Subtract the date time. end2-end1
and end2-start1
should be a positive delta. Similary start2-start1
should be negative. If this condition is satisfied then first time lies within second.
For input in your question:
>>> start_1 = datetime.datetime(2016, 3, 16, 20, 30)
>>> end_1 = datetime.datetime(2016, 3, 17, 20, 30)
>>>
>>> start_2 = datetime.datetime(2016, 3, 14, 20, 30)
>>> end_2 = datetime.datetime(2016, 3, 17, 22, 30)
>>> (end_2 - start_1).total_seconds()
93600.0
>>> (end_2 - start_1).total_seconds()
93600.0
>>> (start_2 - start_1).total_seconds()
-172800
If result of first and second is positive while third is negative then first time is within second. This assuming that your end time is greater than start time for both cases. It is almost same no of instructions.
Upvotes: 0