Skip to content

Commit

Permalink
Reverse order of min in FiniteDatetimeRange.intersection
Browse files Browse the repository at this point in the history
In #187 the implementation of
FiniteDatetimeRange.intersection was optimised. This introduced a very
subtle change in behaviour. Previously when left.end was equal to
right.end then the right.end was favoured. In
#187 the implementation was
(unintentionally) changed to favour left.end.

This change reverses that, to again favour right.end.

This really shouldn't matter, but it can be signidicant when
the TZ of left and right are different. Eventually we'd like
to prevent this kind of mixed TZ behaviour (see
#192), but in the short
term it seems reasonable to make this tiny change to make things
consistent again with how they were before.
  • Loading branch information
Peter554 committed Jan 31, 2025
1 parent 3301ce1 commit da83e4e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
32 changes: 32 additions & 0 deletions tests/test_ranges.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
from xocto import localtime, ranges


TZ_LONDON = zoneinfo.ZoneInfo("Europe/London")
TZ_BERLIN = zoneinfo.ZoneInfo("Europe/Berlin")


@composite
def valid_integer_range(draw):
boundaries = draw(sampled_from(ranges.RangeBoundaries))
Expand Down Expand Up @@ -1174,6 +1178,20 @@ def test_union_with_continuum(self):
assert ranges._is_datetime_range(range | other)
assert range | other == other | range == ranges.DatetimeRange.continuum()

def test_preference_on_equal_end(self):
r1 = ranges.FiniteDatetimeRange(
datetime.datetime(2020, 1, 1, tzinfo=TZ_LONDON),
datetime.datetime(2022, 1, 1, tzinfo=TZ_LONDON),
)
r2 = ranges.FiniteDatetimeRange(
datetime.datetime(2021, 1, 1, hour=1, tzinfo=TZ_BERLIN),
datetime.datetime(2022, 1, 1, hour=1, tzinfo=TZ_BERLIN),
)
assert r1.end == r2.end
union = r1 | r2
# r1.end was picked over r2.end.
assert union.start.tzinfo == union.end.tzinfo == TZ_LONDON

class TestIntersection:
def test_intersection_of_touching_ranges(self):
range = ranges.FiniteDatetimeRange(
Expand Down Expand Up @@ -1237,6 +1255,20 @@ def test_intersection_with_half_finite_range(self):
)
)

def test_preference_on_equal_end(self):
r1 = ranges.FiniteDatetimeRange(
datetime.datetime(2020, 1, 1, tzinfo=TZ_LONDON),
datetime.datetime(2022, 1, 1, tzinfo=TZ_LONDON),
)
r2 = ranges.FiniteDatetimeRange(
datetime.datetime(2021, 1, 1, hour=1, tzinfo=TZ_BERLIN),
datetime.datetime(2022, 1, 1, hour=1, tzinfo=TZ_BERLIN),
)
assert r1.end == r2.end
intersection = r1 & r2
# r2.end was picked over r1.end.
assert intersection.start.tzinfo == intersection.end.tzinfo == TZ_BERLIN

class TestLocalize:
def test_converts_timezone(self):
# Create a datetime range in Sydney, which is
Expand Down
2 changes: 1 addition & 1 deletion xocto/ranges.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ def intersection(
if left.end <= right.start:
return None
else:
return FiniteDatetimeRange(right.start, min(left.end, right.end))
return FiniteDatetimeRange(right.start, min(right.end, left.end))

base_intersection = super().intersection(other)
if base_intersection is None:
Expand Down

0 comments on commit da83e4e

Please sign in to comment.