Skip to content

Querying by temporal extent

Retrieve datapoints that fall within a given time period, with support for precise time intervals, open-ended time ranges, and exact timestamp lookups.

Both Timeseries and Spatio-temporal datasets support efficient time-based queries.

To query data for a specific time interval, use a tuple in the form (start, end) as the temporal_extent parameter. Both start and end must be TimeScalars, which can be datetime objects or strings in ISO 8601 format.

from tilebox.datasets import Client
client = Client()
sentinel2_msi = client.dataset("open_data.copernicus.sentinel2_msi")
data = sentinel2_msi.query(
collections=["S2A_S2MSI2A", "S2B_S2MSI2A", "S2C_S2MSI2A"],
temporal_extent=("2025-05-01", "2025-06-01"),
show_progress=True,
)
print(f"Queried {data.sizes['time']} data points.")
Output
Queried 481079 data points.

A time interval specified as a tuple is interpreted as a half-closed interval. This means the start time is inclusive, and the end time is exclusive. For instance, using an end time of 2025-06-01 includes data points up to 2025-05-31 23:59:59.999, but excludes those from 2025-06-01 00:00:00.000. This behavior mimics the Python range function and is useful for chaining time intervals.

import xarray as xr
data = []
for month in [4, 5, 6]:
interval = (f"2025-{month}-01", f"2025-{month+1}-01")
data.append(collection.query(temporal_extent=interval, show_progress=True))
# Concatenate the data into a single dataset, which is equivalent
# to the result of the single request in the code example above.
data = xr.concat(data, dim="time")

Above example demonstrates how to split a large time interval into smaller chunks while loading data in separate requests. Typically, this is not necessary as the datasets client auto-paginates large intervals.

For greater control over inclusivity of start and end times, you can explicitly specify a TimeInterval. This way you can specify both the start and end times, as well as their inclusivity. Here’s an example of creating equivalent TimeInterval objects in two different ways.

from datetime import datetime
from tilebox.datasets.query import TimeInterval
interval1 = TimeInterval(
datetime(2021, 1, 1), datetime(2023, 1, 1),
end_inclusive=False
)
interval2 = TimeInterval(
# python datetime granularity is in milliseconds
datetime(2021, 1, 1), datetime(2022, 12, 31, 23, 59, 59, 999999),
end_inclusive=True
)
print("Inclusivity is indicated by interval notation: ( and [")
print(interval1)
print(interval2)
print(f"They are equivalent: {interval1 == interval2}")
print(interval2.to_half_open())
# Query data for a time interval
data = collection.query(temporal_extent=interval1, show_progress=True)
Output
Inclusivity is indicated by interval notation: ( and [
[2021-01-01T00:00:00.000 UTC, 2023-01-01T00:00:00.000 UTC)
[2021-01-01T00:00:00.000 UTC, 2022-12-31T23:59:59.999 UTC]
They are equivalent: True
[2021-01-01T00:00:00.000 UTC, 2023-01-01T00:00:00.000 UTC)

You can query all datapoints linked to a specific timestamp by specifying a TimeScalar as the time query argument. A TimeScalar can be a datetime object or a string in ISO 8601 format.

Here’s how to query a data point at a specific millisecond from a dataset or collection.

data = sentinel2_msi.query(temporal_extent="2025-06-15T02:31:41.024")
print(f"Queried {data.sizes['time']} data points.")
first_timestamp = data.time[0].dt.strftime("%Y-%m-%dT%H:%M:%S.%f").item()
print("First datapoint time:", first_timestamp)
Output
Queried 714 datapoints
First datapoint time: 2025-06-15T02:31:41.024 +0000 UTC

All TimeScalars specified as a string are treated as UTC if they do not include a timezone suffix. If you want to query data for a specific time or time range in another timezone, it’s recommended to a type that includes timezone information. Tilebox will automatically convert such objects to UTC in order to send the right query requests. All outputs will always contain UTC timestamps, which will need to be converted again to a different timezone if required.

from datetime import datetime
import pytz
# Tokyo has a UTC+9 hours offset, so this is the same as
# 2017-01-01 02:45:25.679 UTC
tokyo_time = pytz.timezone('Asia/Tokyo').localize(
datetime(2021, 1, 1, 11, 45, 25, 679000)
)
print(tokyo_time)
data = collection.query(temporal_extent=tokyo_time)
print(data)

Output

2021-01-01 11:45:25.679000+09:00
<xarray.Dataset> Size: 725B
Dimensions: (time: 1, latlon: 2)
Coordinates:
ingestion_time (time) datetime64[ns] 8B 2024-06-21T11:03:33.852435
id (time) <U36 144B '015957ea-d82f-e454-34ab-a87603ee...
* time (time) datetime64[ns] 8B 2017-01-01T02:45:25.679000
* latlon (latlon) <U9 72B 'latitude' 'longitude'
Data variables:
...