From b7320b1b69a5f86f5804997310019a415b44aa6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Sat, 20 Jul 2019 10:17:00 +0300 Subject: [PATCH] In monthly report, show months in ascending order. Cleanup. --- hc/api/models.py | 23 ++++++++++------------- hc/api/tests/test_check_model.py | 18 +++++++++--------- hc/lib/date.py | 10 ++++------ 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/hc/api/models.py b/hc/api/models.py index aa5181ba..d043dd00 100644 --- a/hc/api/models.py +++ b/hc/api/models.py @@ -256,17 +256,16 @@ class Check(models.Model): def monthkey(dt): return dt.year, dt.month + # Datetimes of the first days of months we're interested in. Ascending order. + boundaries = month_boundaries(months=months) + # Will accumulate totals here. - # (year, month) -> [datetime, downtime_in_secs, number_of_outages] - totals = {} - # Will collect flips and month boundaries here - events = [] + # (year, month) -> [datetime, total_downtime, number_of_outages] + totals = {monthkey(b): [b, td(), 0] for b in boundaries} - for boundary in month_boundaries(months=months): - totals[monthkey(boundary)] = [boundary, 0, 0] - events.append((boundary, "---")) - - for flip in self.flip_set.filter(created__gt=boundary): + # A list of flips and month boundaries + events = [(b, "---") for b in boundaries] + for flip in self.flip_set.filter(created__gt=min(boundaries)): events.append((flip.created, flip.old_status)) # Iterate through flips and month boundaries in reverse order, @@ -275,16 +274,14 @@ class Check(models.Model): for prev_dt, prev_status in sorted(events, reverse=True): if status == "down": delta = dt - prev_dt - totals[monthkey(prev_dt)][1] += int(delta.total_seconds()) + totals[monthkey(prev_dt)][1] += delta totals[monthkey(prev_dt)][2] += 1 dt = prev_dt if prev_status != "---": status = prev_status - flattened = list(totals.values()) - flattened.sort(reverse=True) - return flattened + return sorted(totals.values()) class Ping(models.Model): diff --git a/hc/api/tests/test_check_model.py b/hc/api/tests/test_check_model.py index 3fea2eb8..b1315cf1 100644 --- a/hc/api/tests/test_check_model.py +++ b/hc/api/tests/test_check_model.py @@ -170,8 +170,8 @@ class CheckModelTestCase(BaseTestCase): check = Check.objects.create(project=self.project) r = check.outages_by_month(10) self.assertEqual(len(r), 10) - for dt, secs, outages in r: - self.assertEqual(secs, 0) + for dt, downtime, outages in r: + self.assertEqual(downtime.total_seconds(), 0) self.assertEqual(outages, 0) def test_outages_by_month_handles_currently_down_check(self): @@ -179,7 +179,7 @@ class CheckModelTestCase(BaseTestCase): r = check.outages_by_month(10) self.assertEqual(len(r), 10) - for dt, secs, outages in r: + for dt, downtime, outages in r: self.assertEqual(outages, 1) @patch("hc.api.models.timezone.now") @@ -195,12 +195,12 @@ class CheckModelTestCase(BaseTestCase): r = check.outages_by_month(10) self.assertEqual(len(r), 10) - for dt, secs, outages in r: + for dt, downtime, outages in r: if dt.month == 7: - self.assertEqual(secs, 86400) + self.assertEqual(downtime.total_seconds(), 86400) self.assertEqual(outages, 1) else: - self.assertEqual(secs, 0) + self.assertEqual(downtime.total_seconds(), 0) self.assertEqual(outages, 0) @patch("hc.api.models.timezone.now") @@ -216,14 +216,14 @@ class CheckModelTestCase(BaseTestCase): r = check.outages_by_month(10) self.assertEqual(len(r), 10) - for dt, secs, outages in r: + for dt, downtime, outages in r: if dt.month == 7: self.assertEqual(outages, 1) elif dt.month == 6: - self.assertEqual(secs, 30 * 86400) + self.assertEqual(downtime.total_seconds(), 30 * 86400) self.assertEqual(outages, 1) elif dt.month == 5: self.assertEqual(outages, 1) else: - self.assertEqual(secs, 0) + self.assertEqual(downtime.total_seconds(), 0) self.assertEqual(outages, 0) diff --git a/hc/lib/date.py b/hc/lib/date.py index 6c9ef704..a1a056d1 100644 --- a/hc/lib/date.py +++ b/hc/lib/date.py @@ -36,10 +36,7 @@ def format_duration(td): def format_hms(td): - if isinstance(td, int): - total_seconds = td - else: - total_seconds = int(td.total_seconds()) + total_seconds = int(td.total_seconds()) result = [] @@ -57,7 +54,8 @@ def format_hms(td): return " ".join(result) -def format_approx_duration(v): +def format_approx_duration(td): + v = td.total_seconds() for unit in (DAY, HOUR, MINUTE, SECOND): if v >= unit.nsecs: vv = v // unit.nsecs @@ -75,7 +73,7 @@ def month_boundaries(months=2): now = timezone.now() y, m = now.year, now.month for x in range(0, months): - result.append(dt(y, m, 1, tzinfo=timezone.utc)) + result.insert(0, dt(y, m, 1, tzinfo=timezone.utc)) m -= 1 if m == 0: