Skip to content

Commit 05f5804

Browse files
committed
ADD: Add support for datetime and date objects
1 parent e77d6cc commit 05f5804

File tree

9 files changed

+84
-63
lines changed

9 files changed

+84
-63
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- Added export of `BidAskPair` and `ConsolidatedBidAskPair` from `databento_dbn` to the root `databento` package
2626
- Upgraded `databento-dbn` to 0.29.0
2727
- Added `COMMODITY_SPOT` `InstrumentClass` variant
28+
- Improved handling of `datetime` and `date` objects in `start` and `end` parameters
2829

2930
## 0.49.0 - 2025-03-04
3031

databento/common/parsing.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from collections.abc import Iterable
44
from datetime import date
5+
from datetime import datetime
56
from functools import partial
67
from functools import singledispatch
78
from io import BytesIO
@@ -222,13 +223,13 @@ def optional_date_to_string(value: date | str | None) -> str | None:
222223
return datetime_to_date_string(value)
223224

224225

225-
def datetime_to_string(value: pd.Timestamp | date | str | int) -> str:
226+
def datetime_to_string(value: pd.Timestamp | datetime | date | str | int) -> str:
226227
"""
227228
Return a valid datetime string from the given value.
228229
229230
Parameters
230231
----------
231-
value : pd.Timestamp or date or str
232+
value : pd.Timestamp, datetime, date, str, or int
232233
The value to parse.
233234
234235
Returns
@@ -240,6 +241,10 @@ def datetime_to_string(value: pd.Timestamp | date | str | int) -> str:
240241
return value
241242
elif isinstance(value, int):
242243
return str(value)
244+
elif isinstance(value, date):
245+
return value.isoformat()
246+
elif isinstance(value, datetime):
247+
return value.isoformat()
243248
else:
244249
return pd.to_datetime(value).isoformat()
245250

@@ -250,7 +255,7 @@ def datetime_to_date_string(value: pd.Timestamp | date | str | int) -> str:
250255
251256
Parameters
252257
----------
253-
value : pd.Timestamp or date or str
258+
value : pd.Timestamp, date, str, or int
254259
The value to parse.
255260
256261
Returns
@@ -262,19 +267,21 @@ def datetime_to_date_string(value: pd.Timestamp | date | str | int) -> str:
262267
return value
263268
elif isinstance(value, int):
264269
return str(value)
270+
elif isinstance(value, date):
271+
return value.isoformat()
265272
else:
266273
return pd.to_datetime(value).date().isoformat()
267274

268275

269276
def optional_datetime_to_string(
270-
value: pd.Timestamp | date | str | int | None,
277+
value: pd.Timestamp | datetime | date | str | int | None,
271278
) -> str | None:
272279
"""
273280
Return a valid datetime string from the given value (if not None).
274281
275282
Parameters
276283
----------
277-
value : pd.Timestamp or date or str, optional
284+
value : pd.Timestamp, datetime, date, str, or int, optional
278285
The value to parse.
279286
280287
Returns
@@ -296,7 +303,7 @@ def datetime_to_unix_nanoseconds(
296303
297304
Parameters
298305
----------
299-
value : pd.Timestamp or date or str or int
306+
value : pd.Timestamp, date, str, or int
300307
The value to parse.
301308
302309
Returns
@@ -306,22 +313,20 @@ def datetime_to_unix_nanoseconds(
306313
"""
307314
if isinstance(value, int):
308315
return value # no checking on integer values
309-
310-
if isinstance(value, date):
316+
elif isinstance(value, date):
311317
return pd.to_datetime(value, utc=True).value
312-
313-
if isinstance(value, pd.Timestamp):
318+
elif isinstance(value, pd.Timestamp):
314319
return value.value
320+
else:
321+
try:
322+
nanoseconds = pd.to_datetime(value, utc=True).value
323+
except Exception: # different versions of pandas raise different exceptions
324+
nanoseconds = pd.to_datetime(
325+
int(value),
326+
utc=True,
327+
).value
315328

316-
try:
317-
nanoseconds = pd.to_datetime(value, utc=True).value
318-
except Exception: # different versions of pandas raise different exceptions
319-
nanoseconds = pd.to_datetime(
320-
int(value),
321-
utc=True,
322-
).value
323-
324-
return nanoseconds
329+
return nanoseconds
325330

326331

327332
def optional_datetime_to_unix_nanoseconds(
@@ -333,7 +338,7 @@ def optional_datetime_to_unix_nanoseconds(
333338
334339
Parameters
335340
----------
336-
value : pd.Timestamp or date or str or int
341+
value : pd.Timestamp, date, str, or int
337342
The value to parse.
338343
339344
Returns

databento/historical/api/batch.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from concurrent.futures import as_completed
1111
from dataclasses import dataclass
1212
from datetime import date
13+
from datetime import datetime
1314
from os import PathLike
1415
from pathlib import Path
1516
from time import sleep
@@ -63,8 +64,8 @@ def submit_job(
6364
dataset: Dataset | str,
6465
symbols: Iterable[str | int] | str | int,
6566
schema: Schema | str,
66-
start: pd.Timestamp | date | str | int,
67-
end: pd.Timestamp | date | str | int | None = None,
67+
start: pd.Timestamp | datetime | date | str | int,
68+
end: pd.Timestamp | datetime | date | str | int | None = None,
6869
encoding: Encoding | str = "dbn",
6970
compression: Compression | str = "zstd",
7071
pretty_px: bool = False,
@@ -93,11 +94,11 @@ def submit_job(
9394
If 'ALL_SYMBOLS' or `None` then will select **all** symbols.
9495
schema : Schema or str {'mbo', 'mbp-1', 'mbp-10', 'trades', 'tbbo', 'ohlcv-1s', 'ohlcv-1m', 'ohlcv-1h', 'ohlcv-1d', 'definition', 'statistics', 'status'}, default 'trades' # noqa
9596
The data record schema for the request.
96-
start : pd.Timestamp or date or str or int
97+
start : pd.Timestamp, datetime, date, str, or int
9798
The start datetime of the request time range (inclusive).
9899
Assumes UTC as timezone unless passed a tz-aware object.
99100
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
100-
end : pd.Timestamp or date or str or int, optional
101+
end : pd.Timestamp, datetime, date, str, or int, optional
101102
The end datetime of the request time range (exclusive).
102103
Assumes UTC as timezone unless passed a tz-aware object.
103104
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
@@ -183,7 +184,7 @@ def submit_job(
183184
def list_jobs(
184185
self,
185186
states: list[str] | str = "received,queued,processing,done",
186-
since: pd.Timestamp | date | str | int | None = None,
187+
since: pd.Timestamp | datetime | date | str | int | None = None,
187188
) -> list[dict[str, Any]]:
188189
"""
189190
Request all batch job details for the user account.
@@ -196,7 +197,7 @@ def list_jobs(
196197
----------
197198
states : list[str] or str, optional {'received', 'queued', 'processing', 'done', 'expired'} # noqa
198199
The filter for jobs states as a list of comma separated values.
199-
since : pd.Timestamp or date or str or int, optional
200+
since : pd.Timestamp, datetime, date, str, or int, optional
200201
The filter for timestamp submitted (will not include jobs prior to this).
201202
202203
Returns

databento/historical/api/metadata.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from collections.abc import Iterable
44
from datetime import date
5+
from datetime import datetime
56
from typing import Any
67

78
import pandas as pd
@@ -261,8 +262,8 @@ def get_dataset_range(
261262
def get_record_count(
262263
self,
263264
dataset: Dataset | str,
264-
start: pd.Timestamp | date | str | int,
265-
end: pd.Timestamp | date | str | int | None = None,
265+
start: pd.Timestamp | datetime | date | str | int,
266+
end: pd.Timestamp | datetime | date | str | int | None = None,
266267
symbols: Iterable[str | int] | str | int | None = None,
267268
schema: Schema | str = "trades",
268269
stype_in: SType | str = "raw_symbol",
@@ -277,11 +278,11 @@ def get_record_count(
277278
----------
278279
dataset : Dataset or str
279280
The dataset code for the request.
280-
start : pd.Timestamp or date or str or int
281+
start : pd.Timestamp, datetime, date, str, or int
281282
The start datetime for the request range (inclusive).
282283
Assumes UTC as timezone unless otherwise specified.
283284
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
284-
end : pd.Timestamp or date or str or int, optional
285+
end : pd.Timestamp, datetime, date, str, or int, optional
285286
The end datetime for the request range (exclusive).
286287
Assumes UTC as timezone unless otherwise specified.
287288
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
@@ -329,8 +330,8 @@ def get_record_count(
329330
def get_billable_size(
330331
self,
331332
dataset: Dataset | str,
332-
start: pd.Timestamp | date | str | int,
333-
end: pd.Timestamp | date | str | int | None = None,
333+
start: pd.Timestamp | datetime | date | str | int,
334+
end: pd.Timestamp | datetime | date | str | int | None = None,
334335
symbols: Iterable[str | int] | str | int | None = None,
335336
schema: Schema | str = "trades",
336337
stype_in: SType | str = "raw_symbol",
@@ -346,17 +347,17 @@ def get_billable_size(
346347
----------
347348
dataset : Dataset or str
348349
The dataset code for the request.
349-
start : pd.Timestamp or date or str or int
350+
start : pd.Timestamp, datetime, date, str, or int
350351
The start datetime for the request range (inclusive).
351352
Assumes UTC as timezone unless otherwise specified.
352353
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
353-
end : pd.Timestamp or date or str or int, optional
354+
end : pd.Timestamp, datetime, date, str, or int, optional
354355
The end datetime for the request range (exclusive).
355356
Assumes UTC as timezone unless otherwise specified.
356357
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
357358
Values are forward filled based on the resolution provided.
358359
Defaults to the same value as `start`.
359-
symbols : Iterable[str | int] or str or int, optional
360+
symbols : Iterable[str | int] or str, or int, optional
360361
The instrument symbols to filter for. Takes up to 2,000 symbols per request.
361362
If 'ALL_SYMBOLS' or `None` then will select **all** symbols.
362363
schema : Schema or str {'mbo', 'mbp-1', 'mbp-10', 'trades', 'tbbo', 'ohlcv-1s', 'ohlcv-1m', 'ohlcv-1h', 'ohlcv-1d', 'definition', 'statistics', 'status'}, default 'trades' # noqa
@@ -398,8 +399,8 @@ def get_billable_size(
398399
def get_cost(
399400
self,
400401
dataset: Dataset | str,
401-
start: pd.Timestamp | date | str | int,
402-
end: pd.Timestamp | date | str | int | None = None,
402+
start: pd.Timestamp | datetime | date | str | int,
403+
end: pd.Timestamp | datetime | date | str | int | None = None,
403404
mode: FeedMode | str = "historical-streaming",
404405
symbols: Iterable[str | int] | str | int | None = None,
405406
schema: Schema | str = "trades",
@@ -416,11 +417,11 @@ def get_cost(
416417
----------
417418
dataset : Dataset or str
418419
The dataset code for the request.
419-
start : pd.Timestamp or date or str or int
420+
start : pd.Timestamp, datetime, date, str, or int
420421
The start datetime for the request range (inclusive).
421422
Assumes UTC as timezone unless otherwise specified.
422423
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
423-
end : pd.Timestamp or date or str or int, optional
424+
end : pd.Timestamp, datetime, date, str, or int, optional
424425
The end datetime for the request range (exclusive).
425426
Assumes UTC as timezone unless otherwise specified.
426427
If an integer is passed, then this represents nanoseconds since the UNIX epoch.

databento/historical/api/timeseries.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from collections.abc import Iterable
44
from datetime import date
5+
from datetime import datetime
56
from os import PathLike
67

78
import pandas as pd
@@ -34,8 +35,8 @@ def __init__(self, key: str, gateway: str) -> None:
3435
def get_range(
3536
self,
3637
dataset: Dataset | str,
37-
start: pd.Timestamp | date | str | int,
38-
end: pd.Timestamp | date | str | int | None = None,
38+
start: pd.Timestamp | datetime | date | str | int,
39+
end: pd.Timestamp | datetime | date | str | int | None = None,
3940
symbols: Iterable[str | int] | str | int | None = None,
4041
schema: Schema | str = "trades",
4142
stype_in: SType | str = "raw_symbol",
@@ -51,18 +52,18 @@ def get_range(
5152
Primary method for getting historical intraday market data, daily data,
5253
instrument definitions and market status data directly into your application.
5354
54-
This method only returns after all of the data has been downloaded,
55+
This method only returns after all the data has been downloaded,
5556
which can take a long time. For large requests, consider using a batch download.
5657
5758
Parameters
5859
----------
5960
dataset : Dataset or str
6061
The dataset code (string identifier) for the request.
61-
start : pd.Timestamp or date or str or int
62+
start : pd.Timestamp, datetime, date, str, or int
6263
The start datetime of the request time range (inclusive).
6364
Assumes UTC as timezone unless passed a tz-aware object.
6465
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
65-
end : pd.Timestamp or date or str or int, optional
66+
end : pd.Timestamp, datetime, date, str, or int, optional
6667
The end datetime of the request time range (exclusive).
6768
Assumes UTC as timezone unless passed a tz-aware object.
6869
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
@@ -130,8 +131,8 @@ def get_range(
130131
async def get_range_async(
131132
self,
132133
dataset: Dataset | str,
133-
start: pd.Timestamp | date | str | int,
134-
end: pd.Timestamp | date | str | int | None = None,
134+
start: pd.Timestamp | datetime | date | str | int,
135+
end: pd.Timestamp | datetime | date | str | int | None = None,
135136
symbols: Iterable[str | int] | str | int | None = None,
136137
schema: Schema | str = "trades",
137138
stype_in: SType | str = "raw_symbol",
@@ -148,18 +149,18 @@ async def get_range_async(
148149
Primary method for getting historical intraday market data, daily data,
149150
instrument definitions and market status data directly into your application.
150151
151-
This coroutine will complete once all of the data has been downloaded,
152+
This coroutine will complete once all the data has been downloaded,
152153
which can take a long time. For large requests, consider using a batch download.
153154
154155
Parameters
155156
----------
156157
dataset : Dataset or str
157158
The dataset code (string identifier) for the request.
158-
start : pd.Timestamp or date or str or int
159+
start : pd.Timestamp, datetime, date, str, or int
159160
The start datetime of the request time range (inclusive).
160161
Assumes UTC as timezone unless passed a tz-aware object.
161162
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
162-
end : pd.Timestamp or date or str or int, optional
163+
end : pd.Timestamp, datetime, date, str, or int, optional
163164
The end datetime of the request time range (exclusive).
164165
Assumes UTC as timezone unless passed a tz-aware object.
165166
If an integer is passed, then this represents nanoseconds since the UNIX epoch.

databento/reference/api/adjustment.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from collections.abc import Iterable
44
from datetime import date
5+
from datetime import datetime
56

67
import pandas as pd
78
from databento_dbn import Compression
@@ -31,8 +32,8 @@ def __init__(self, key: str, gateway: str) -> None:
3132

3233
def get_range(
3334
self,
34-
start: pd.Timestamp | date | str | int,
35-
end: pd.Timestamp | date | str | int | None = None,
35+
start: pd.Timestamp | datetime | date | str | int,
36+
end: pd.Timestamp | datetime | date | str | int | None = None,
3637
symbols: Iterable[str] | str | None = None,
3738
stype_in: SType | str = "raw_symbol",
3839
countries: Iterable[str] | str | None = None,
@@ -48,11 +49,11 @@ def get_range(
4849
4950
Parameters
5051
----------
51-
start : pd.Timestamp or date or str or int
52+
start : pd.Timestamp, datetime, date, str, or int
5253
The start datetime of the request time range (inclusive) based on `ex_date`.
5354
Assumes UTC as timezone unless passed a tz-aware object.
5455
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
55-
end : pd.Timestamp or date or str or int, optional
56+
end : pd.Timestamp, datetime, date, str, or int, optional
5657
The end datetime of the request time range (exclusive) based on `ex_date`.
5758
Assumes UTC as timezone unless passed a tz-aware object.
5859
If an integer is passed, then this represents nanoseconds since the UNIX epoch.

0 commit comments

Comments
 (0)