From 93ab43fe729a9a2b65e3886518e9ea439e5c73f3 Mon Sep 17 00:00:00 2001 From: ederag Date: Sun, 8 Mar 2020 18:04:53 +0100 Subject: [PATCH 1/3] fix from_start_end: handle datetime first --- src/hamster/lib/datetime.py | 48 +++++++++++++++++++++---------------- tests/stuff_test.py | 10 ++++++++ 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/hamster/lib/datetime.py b/src/hamster/lib/datetime.py index f819c56b1..786b8c18a 100644 --- a/src/hamster/lib/datetime.py +++ b/src/hamster/lib/datetime.py @@ -590,27 +590,35 @@ def from_start_end(cls, start, end=None): Convenient to ease backward compatibility, and to handle either hdays or datetimes. """ + if isinstance(start, Range): - assert end is None, "range and end are mutually exclusive" - range = start - else: - if isinstance(start, hday): - day = start - start = day.start - if end is None: - end = day.end - elif isinstance(start, pdt.date): - # transition from legacy - start = hday.from_pdt(start).start - - if isinstance(end, hday): - end = end.end - elif isinstance(end, pdt.date): - end = hday.from_pdt(end).end - - range = Range(start, end) - - return range + assert end is None, "end cannot be passed together with a Range" + return cls(start.start, start.end) + elif isinstance(start, datetime): + # This one must come first, + # because inheritance order is datetime < date < pdt.date. + pass + elif isinstance(start, hday): + # Idem, beware of the inheritance order; + # hday < date < pdt.date. + day = start + start = day.start + if end is None: + end = day.end + elif isinstance(start, pdt.date): + # transition from legacy + start = hday.from_pdt(start).start + + if isinstance(end, datetime): + # same as above + pass + elif isinstance(end, hday): + end = end.end + elif isinstance(end, pdt.date): + # transition from legacy + end = hday.from_pdt(end).end + + return cls(start, end) @classmethod def today(cls): diff --git a/tests/stuff_test.py b/tests/stuff_test.py index d3847b38a..218c07b71 100644 --- a/tests/stuff_test.py +++ b/tests/stuff_test.py @@ -407,6 +407,16 @@ def test_range(self): range = dt.Range(None, base) range_str = range.format(default_day=day) self.assertEqual(range_str, "-- - 21:20") + # issue #576 + start = dt.datetime(2020, 3, 8, 17, 7) + end = dt.datetime(2020, 3, 8, 18, 6) + range = dt.Range.from_start_end(start, end) + self.assertEqual(range.start, start) + self.assertEqual(range.end, end) + # check passthrough + range2 = dt.Range.from_start_end(range) + self.assertEqual(range2.start, range.start) + self.assertEqual(range2.end, range.end) def test_rounding(self): dt1 = dt.datetime(2019, 12, 31, hour=13, minute=14, second=10, microsecond=11) From 2af707ce9a3a1da8e6be7a0359720f6602d0a600 Mon Sep 17 00:00:00 2001 From: ederag Date: Fri, 13 Mar 2020 21:58:26 +0100 Subject: [PATCH 2/3] choke on invalid types in from_start_end --- src/hamster/lib/datetime.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/hamster/lib/datetime.py b/src/hamster/lib/datetime.py index 786b8c18a..0e0df47ed 100644 --- a/src/hamster/lib/datetime.py +++ b/src/hamster/lib/datetime.py @@ -590,11 +590,10 @@ def from_start_end(cls, start, end=None): Convenient to ease backward compatibility, and to handle either hdays or datetimes. """ - if isinstance(start, Range): assert end is None, "end cannot be passed together with a Range" return cls(start.start, start.end) - elif isinstance(start, datetime): + elif (start is None) or isinstance(start, datetime): # This one must come first, # because inheritance order is datetime < date < pdt.date. pass @@ -608,8 +607,13 @@ def from_start_end(cls, start, end=None): elif isinstance(start, pdt.date): # transition from legacy start = hday.from_pdt(start).start + else: + raise TypeError( + "\n First argument should be either Range, None, datetime or hday;" + "\n received {}".format(type(start)) + ) - if isinstance(end, datetime): + if (end is None) or isinstance(end, datetime): # same as above pass elif isinstance(end, hday): @@ -617,6 +621,10 @@ def from_start_end(cls, start, end=None): elif isinstance(end, pdt.date): # transition from legacy end = hday.from_pdt(end).end + else: + raise TypeError( + "\n Second argument should be either None, datetime or hday;" + "\n received {}".format(type(start))) return cls(start, end) From 6754f66a5c9f339cdcf0b81f01f16438bfab1a5a Mon Sep 17 00:00:00 2001 From: ederag Date: Sat, 14 Mar 2020 10:17:58 +0100 Subject: [PATCH 3/3] fix inheritance order in comment Co-Authored-By: Matthijs Kooijman --- src/hamster/lib/datetime.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hamster/lib/datetime.py b/src/hamster/lib/datetime.py index 0e0df47ed..5ed5f63e2 100644 --- a/src/hamster/lib/datetime.py +++ b/src/hamster/lib/datetime.py @@ -595,7 +595,7 @@ def from_start_end(cls, start, end=None): return cls(start.start, start.end) elif (start is None) or isinstance(start, datetime): # This one must come first, - # because inheritance order is datetime < date < pdt.date. + # because inheritance order is datetime < pdt.datetime < pdt.date. pass elif isinstance(start, hday): # Idem, beware of the inheritance order; @@ -716,4 +716,3 @@ def format(self, fmt="human"): def total_minutes(self): """Return the duration in minutes (float).""" return self.total_seconds() / 60 -