diff --git a/python/activator/middleware_interface.py b/python/activator/middleware_interface.py index 5665714e..443df4c2 100644 --- a/python/activator/middleware_interface.py +++ b/python/activator/middleware_interface.py @@ -123,6 +123,10 @@ def make_local_repo(local_storage: str, central_butler: Butler, instrument: str) return repo_dir +# Time zone used to define exposures' day_obs value. +_DAY_OBS_TZ = datetime.timezone(datetime.timedelta(hours=-12), name="day_obs") + + class MiddlewareInterface: """Interface layer between the Butler middleware and the prompt processing data handling system, to handle processing individual images. @@ -572,8 +576,8 @@ def _get_init_output_run(self, Parameters ---------- date : `datetime.date`, optional - Date of the processing run (not observation!), defaults to the UTC - date this method was called. + Date of the processing run (not observation!), defaults to the + day_obs this method was called. Returns ------- @@ -581,7 +585,7 @@ def _get_init_output_run(self, The run in which to place pipeline init-outputs. """ if date is None: - date = datetime.datetime.now(datetime.timezone.utc) + date = datetime.datetime.now(_DAY_OBS_TZ) # Current executor requires that init-outputs be in the same run as # outputs. This can be changed once DM-36162 is done. return self._get_output_run(date) @@ -594,8 +598,8 @@ def _get_output_run(self, Parameters ---------- date : `datetime.date`, optional - Date of the processing run (not observation!), defaults to the UTC - date this method was called. + Date of the processing run (not observation!), defaults to the + day_obs this method was called. Returns ------- @@ -603,7 +607,7 @@ def _get_output_run(self, The run in which to place processing outputs. """ if date is None: - date = datetime.datetime.now(datetime.timezone.utc) + date = datetime.datetime.now(_DAY_OBS_TZ) pipeline_name, _ = os.path.splitext(os.path.basename(self._get_pipeline_file())) # Order optimized for S3 bucket -- filter out as many files as soon as possible. return self.instrument.makeCollectionName( diff --git a/tests/test_middleware_interface.py b/tests/test_middleware_interface.py index 679b6b8c..fea20bd8 100644 --- a/tests/test_middleware_interface.py +++ b/tests/test_middleware_interface.py @@ -410,6 +410,25 @@ def test_get_output_run(self): "/ApPipe/prompt-proto-service-042" ) + def test_get_output_run_default(self): + # Workaround for mocking builtin class; see + # https://williambert.online/2011/07/how-to-unit-testing-in-django-with-mocking-and-patching/ + class MockDatetime(datetime.datetime): + @classmethod + def now(cls, tz=None): + # This time will be the same day in CLT/CLST, but the previous day in day_obs. + utc = datetime.datetime(2023, 3, 15, 5, 42, 3, tzinfo=datetime.timezone.utc) + if tz: + return utc.astimezone(tz) + else: + return utc.replace(tzinfo=None) + + with unittest.mock.patch("datetime.datetime", MockDatetime): + out_run = self.interface._get_output_run() + self.assertIn("output-2023-03-14", out_run) + init_run = self.interface._get_init_output_run() + self.assertIn("output-2023-03-14", init_run) + def _assert_in_collection(self, butler, collection, dataset_type, data_id): # Pass iff any dataset matches the query, no need to check them all. for dataset in butler.registry.queryDatasets(dataset_type, collections=collection, dataId=data_id):