From ffdb80da571fed466c2fb89c0c0b2c9b7901edce Mon Sep 17 00:00:00 2001
From: "E. Joshua Rigler" <erigler@usgs.gov>
Date: Sun, 22 Sep 2024 20:44:57 -0600
Subject: [PATCH] Function get_nearest_time() behaves as expected now

A FilterAlgorith.py module function get_nearest_time() is supposed to return
the nearest *allowed* time for a given filter "step". This worked fine with
steps for second and minute data, whose allowed times are the tops of seconds
and minutes. However, for hourly (and daily, and any "average" type step),
things failed since the allowed times are the center of the interval (for
example, for hourly data, which is the average of all minute samples from
00 to 59, the the allowed time is 29:30).

One consequence was that if a user specified an interval with a start and
end time that did not encompass a given hour's allowed center time (e.g.,
start=AA:29:31, end=BB:29:29), the algorithm would still return a sample
for time BB:29:30. More generally, requests for average type data would
include an extra sample.

In this fixed version, if start=AA:29:31, and end=BB:29:29, nothing is
returned, as intended (and as always worked for non-average type steps).
Furthermoref start=AA:29:30, and end=BB:29:29, a sample for hour AA is
generated; if start=AA:29:31, and end=BB:29:30, a sample for hour BB is
generated, and if start=AA:29:30, and end=BB:29:30, samples for both AA
and BB are generated, all as intended.
---
 geomagio/algorithm/FilterAlgorithm.py | 29 ++++++++++++++++-----------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/geomagio/algorithm/FilterAlgorithm.py b/geomagio/algorithm/FilterAlgorithm.py
index 6cd10448..48763ee1 100644
--- a/geomagio/algorithm/FilterAlgorithm.py
+++ b/geomagio/algorithm/FilterAlgorithm.py
@@ -64,24 +64,29 @@ STEPS = [
 
 
 def get_nearest_time(step, output_time, left=True):
+
+    # nearest allowed timestamp "left" of output_time
     interval_start = output_time - (
         output_time.timestamp % step["output_sample_period"]
     )
-    # shift interval right if needed
-    if interval_start != output_time and not left:
-        interval_start += step["output_sample_period"]
-    # position center of filter, data around interval
+
     half_width = get_step_time_shift(step)
+
     if step["type"] == "average":
-        filter_center = interval_start + half_width
-        data_start = interval_start
-        data_end = (interval_start + step["output_sample_period"]) - step[
-            "input_sample_period"
-        ]
+        interval_start += half_width
+
+    # shift interval if needed
+    if left:
+        if interval_start > output_time:
+            interval_start -= step["output_sample_period"]
     else:
-        filter_center = interval_start
-        data_start = filter_center - half_width
-        data_end = filter_center + half_width
+        if interval_start < output_time:
+            interval_start += step["output_sample_period"]
+
+    filter_center = interval_start
+    data_start = filter_center - half_width
+    data_end = filter_center + half_width
+
     return {
         "time": filter_center,
         "data_start": data_start,
-- 
GitLab