alwbtc
alwbtc

Reputation: 29465

How to check if a date period is embraced by another date period in python?

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

Answers (2)

zmo
zmo

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

Sharad
Sharad

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

Related Questions