Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow open date range in dc load and find_datasets #1443

Merged
merged 5 commits into from May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions datacube/api/core.py
Expand Up @@ -232,12 +232,17 @@ def load(self, product=None, measurements=None, output_crs=None, resolution=None

x=(1516200, 1541300), y=(-3867375, -3867350), crs='EPSG:3577'

The ``time`` dimension can be specified using a tuple of datetime objects or strings with
``YYYY-MM-DD hh:mm:ss`` format. Data will be loaded inclusive of the start and finish times. E.g::
The ``time`` dimension can be specified using a single or tuple of datetime objects or strings with
``YYYY-MM-DD hh:mm:ss`` format. Data will be loaded inclusive of the start and finish times.
A ``None`` value in the range indicates an open range, with the provided date serving as either the
upper or lower bound. E.g::

time=('2000-01-01', '2001-12-31')
time=('2000-01', '2001-12')
time=('2000', '2001')
time=('2000')
time=('2000', None) # all data from 2000 onward
time=(None, '2000') # all data up to and including 2000

For 3D datasets, where the product definition contains an ``extra_dimension`` specification,
these dimensions can be queried using that dimension's name. E.g.::
Expand Down
21 changes: 6 additions & 15 deletions datacube/api/query.py
Expand Up @@ -128,8 +128,8 @@ def __init__(self, index=None, product=None, geopolygon=None, like=None, **searc
if time_coord is not None:
self.search['time'] = _time_to_search_dims(
(pandas_to_datetime(time_coord.values[0]).to_pydatetime(),
pandas_to_datetime(time_coord.values[-1]).to_pydatetime()
+ datetime.timedelta(milliseconds=1)) # TODO: inclusive time searches
pandas_to_datetime(time_coord.values[-1]).to_pydatetime()
+ datetime.timedelta(milliseconds=1)) # TODO: inclusive time searches
)

@property
Expand Down Expand Up @@ -342,7 +342,11 @@ def _time_to_search_dims(time_range):
if hasattr(tr_end, 'isoformat'):
tr_end = tr_end.isoformat()

if tr_start is None:
tr_start = datetime.datetime.fromtimestamp(0)
start = _to_datetime(tr_start)
if tr_end is None:
tr_end = datetime.datetime.now().strftime("%Y-%m-%d")
end = _to_datetime(pandas.Period(tr_end)
.end_time
.to_pydatetime())
Expand All @@ -354,19 +358,6 @@ def _time_to_search_dims(time_range):
return tr


def _time_to_open_range(time, lower_bound: bool):
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)

if lower_bound: # from date provided (not inclusive) to latest available
start = _to_datetime(pandas.Period(time).end_time.to_pydatetime())
end = _to_datetime(datetime.datetime.now())
else: # from earliest available to date provided (not inclusive)
start = _to_datetime(datetime.datetime.fromtimestamp(0))
end = _to_datetime(pandas.Period(time).start_time.to_pydatetime())
return Range(start, end)


def _convert_to_solar_time(utc, longitude):
seconds_per_degree = 240
offset_seconds = int(longitude * seconds_per_degree)
Expand Down
7 changes: 3 additions & 4 deletions datacube/ui/expression.py
Expand Up @@ -20,7 +20,7 @@

from lark import Lark, v_args, Transformer

from datacube.api.query import _time_to_search_dims, _time_to_open_range
from datacube.api.query import _time_to_search_dims
from datacube.model import Range


Expand Down Expand Up @@ -119,11 +119,10 @@ def date_pair(self, start, end):
return _time_to_search_dims((start, end))

def range_lower_bound(self, date):
return _time_to_open_range(date, lower_bound=True)
return _time_to_search_dims((date, None))

def range_upper_bound(self, date):
return _time_to_open_range(date, lower_bound=False)

return _time_to_search_dims((None, date))

def date(self, y, m=None, d=None):
return "-".join(x for x in [y, m, d] if x is not None)
Expand Down
2 changes: 1 addition & 1 deletion docs/about/whats_new.rst
Expand Up @@ -14,7 +14,7 @@ v1.8.next
- Documentation fixes (:pull:`1417`, :pull:`1418`, :pull:`1430`)
- ``datacube dataset`` cli commands print error message if missing argument (:pull:`1437`)
- Add pre-commit hook to verify license headers (:pull:`1438`)
- Support open-ended date ranges in `datacube dataset search` (:pull:`1439`)
- Support open-ended date ranges in `datacube dataset search`, `dc.load`, and `dc.find_datasets` (:pull:`1439`, :pull:`1443`)


v1.8.12 (7th March 2023)
Expand Down
6 changes: 5 additions & 1 deletion tests/api/test_query.py
Expand Up @@ -140,7 +140,11 @@ def format_test(start_out, end_out):
((datetime.datetime(2008, 1, 1), datetime.datetime(2008, 1, 10, 23, 59, 40)),
format_test('2008-01-01T00:00:00', '2008-01-10T23:59:40.999999')),
((datetime.date(2008, 1, 1)),
format_test('2008-01-01T00:00:00', '2008-01-01T23:59:59.999999'))
format_test('2008-01-01T00:00:00', '2008-01-01T23:59:59.999999')),
((datetime.date(2008, 1, 1), None),
format_test('2008-01-01T00:00:00', datetime.datetime.now().strftime("%Y-%m-%dT23:59:59.999999"))),
((None, '2008'),
format_test(datetime.datetime.fromtimestamp(0).strftime("%Y-%m-%dT%H:%M:%S"), '2008-12-31T23:59:59.999999'))
]


Expand Down