Skip to content

Commit 15e3f3c

Browse files
authored
DAS-2431: Adds default start/end times for temporal subsetting. (#51)
1 parent c6e82c0 commit 15e3f3c

5 files changed

Lines changed: 55 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1+
## [v1.1.14] - 2025-10-22
2+
3+
### Fixed
4+
5+
- Adds support for temporal requests with only start or end time specified.
6+
When a Harmony message omits the start time, HOSS now defaults to
7+
`0001-01-01T00:00:00.000Z`. When the end time is omitted, HOSS defaults to
8+
the current time. This allows temporal subsetting to work with
9+
partially-specified time ranges. These changes do not affect requests
10+
without a temporal component or fully qualified temporal requests.
11+
112
## [v1.1.13] - 2025-10-21
213

314
### Changed
415

516
- Updates evaluation of bbox or polygon constraint to exclude areas outside the
6-
projected target grid. An error exception occurs if spatial constraint is entirely
17+
projected target grid. An error exception occurs if spatial constraint is
18+
entirely outside the projected grid extents.
719
- Updates tests to be less dependent on architecture when comparing floats.
820
- Fixes test that modified a source file fixture.
9-
- Changes infrastructure so that local and Docker runs of the tests produce output in same locations.
21+
- Changes infrastructure so that local and Docker runs of the tests produce
22+
output in same locations.
1023
- GitHub once again captures the artifacts from the tests and coverage.
1124

1225

docker/service_version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.1.13
1+
1.1.14

hoss/temporal.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from datetime import datetime, timedelta, timezone
1212
from typing import List, Set
1313

14+
from dateutil import tz
1415
from dateutil.parser import parse as parse_datetime
1516
from harmony_service_lib.message import Message
1617
from netCDF4 import Dataset
@@ -29,6 +30,14 @@
2930
units_second = {'second', 'seconds', 'sec', 'secs', 's'}
3031

3132

33+
DEFAULT_TIME_START = '0001-01-01T00:00:00.000Z'
34+
35+
36+
def default_time_end():
37+
"""Returns the current UTC time to be used as a default ending time."""
38+
return datetime.now(tz=tz.UTC).strftime('%Y-%m-%dT%H:%M:%S.000Z')
39+
40+
3241
def get_temporal_index_ranges(
3342
required_variables: Set[str],
3443
varinfo: VarInfoFromDmr,
@@ -47,8 +56,12 @@ def get_temporal_index_ranges(
4756
index_ranges = {}
4857
temporal_dimensions = varinfo.get_temporal_dimensions(required_variables)
4958

50-
time_start = get_datetime_with_timezone(harmony_message.temporal.start)
51-
time_end = get_datetime_with_timezone(harmony_message.temporal.end)
59+
time_start = get_datetime_with_timezone(
60+
harmony_message.temporal.start or DEFAULT_TIME_START
61+
)
62+
time_end = get_datetime_with_timezone(
63+
harmony_message.temporal.end or default_time_end()
64+
)
5265

5366
with Dataset(dimensions_path, 'r') as dimensions_file:
5467
for dimension in temporal_dimensions:

tests/pip_test_requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pylint ~= 3.3.9
33
pytest ~= 8.3.3
44
pytest-mock == 3.14.0
55
pytest-cov == 7.0.0
6+
freezegun ~= 1.5.5

tests/unit/test_temporal.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
from datetime import datetime, timedelta, timezone
2+
from gc import freeze
23
from shutil import rmtree
34
from tempfile import mkdtemp
45
from unittest import TestCase
56
from unittest.mock import ANY, patch
67

78
import numpy as np
9+
from freezegun import freeze_time
810
from harmony_service_lib.message import Message
911
from netCDF4 import Dataset
1012
from numpy.testing import assert_array_equal
1113
from varinfo import VarInfoFromDmr
1214

1315
from hoss.exceptions import UnsupportedTemporalUnits
1416
from hoss.temporal import (
17+
DEFAULT_TIME_START,
18+
default_time_end,
1519
get_datetime_with_timezone,
1620
get_temporal_index_ranges,
1721
get_time_ref,
@@ -130,6 +134,7 @@ def test_get_time_ref(self):
130134
with self.assertRaises(UnsupportedTemporalUnits):
131135
get_time_ref('fortnights since 2021-12-08 00:30:00')
132136

137+
@freeze_time("2025-10-21 16:15:00 UTC")
133138
def test_get_datetime_with_timezone(self):
134139
"""Ensure the string is parsed to datetime with timezone."""
135140
expected_datetime = datetime(2021, 12, 8, 0, 30, tzinfo=timezone.utc)
@@ -153,3 +158,21 @@ def test_get_datetime_with_timezone(self):
153158
self.assertEqual(
154159
get_datetime_with_timezone('2021-12-08 00:30:00Z'), expected_datetime
155160
)
161+
162+
with self.subTest('ISO with fractional seconds Z'):
163+
self.assertEqual(
164+
get_datetime_with_timezone('2021-12-08T00:30:00.000Z'),
165+
expected_datetime,
166+
)
167+
168+
with self.subTest('DEFAULT_TIME_START'):
169+
expected_start_time = datetime(1, 1, 1, 0, 0, tzinfo=timezone.utc)
170+
self.assertEqual(
171+
get_datetime_with_timezone(DEFAULT_TIME_START), expected_start_time
172+
)
173+
174+
with self.subTest('default_end_time()'):
175+
expected_stop_time = datetime(2025, 10, 21, 16, 15, tzinfo=timezone.utc)
176+
self.assertEqual(
177+
get_datetime_with_timezone(default_time_end()), expected_stop_time
178+
)

0 commit comments

Comments
 (0)