date search #549
-
Howdy, everyone. I'm working on a function to get a list of species to look for in a given locale at the current moment. Right now I'm searching for observations made this month (in any year) and in the earlier month if before the 15th or the next month if after. I'd rather search from 7 days ago to 7 days in the future, but in any year. Is there a good way to do this with the pyinat api? The two alternatives that seem best to me would both involve concatenating results of multiple searches. The less performant one would look 7 days ago to 7 days in the future and adjust the year successively to the indefinite past. The more performant one would do a search for the month/day-greater for 7 days ago and month/day-lesser for 7 days ahead. Is there any even better solution I'm missing? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
The API almost has parameters to do what you want in a single query, but not quite. There is:
This will still have to be two separate queries when the start and end date are in different months, though. Here's an example that I think will do what you want. Note that this doesn't account for larger date ranges that could span more than two months. It also doesn't handle leap years, or locations that span multiple time zones. from calendar import monthrange
from datetime import datetime, timedelta
from pyinaturalist import enable_logging, get_observations
DATE_RANGE_DAYS = 7 # days +- from today
PLACE_ID = 82448
SHORT_FMT = '%m-%d'
enable_logging('INFO')
# Get date range (month/days of any year) for observation search
today = datetime.now()
start = today - timedelta(days=DATE_RANGE_DAYS)
end = today + timedelta(days=DATE_RANGE_DAYS)
print(f'Searching date range: {start.strftime(SHORT_FMT)}, End: {end.strftime(SHORT_FMT)}')
# Get date range as a list of days to search for start month
month_days = monthrange(start.year, start.month)[1]
end_day = end.day if end.month == start.month else month_days
days = list(range(start.day, min(end_day, month_days) + 1))
search_month_days = {start.month: days}
# If the range ends in a different month, get the days for that month as well
if end.month != start.month:
days = list(range(1, end.day + 1))
search_month_days[end.month] = days
# Search observations for each month/day range
observations = []
for month, days in search_month_days.items():
print(f'Searching month: {month}, days: {days}')
response = get_observations(month=month, day=days, place_id=PLACE_ID, page='all')
observations.extend(response['results'])
print(f'Found {len(observations)} observations') And for the last part (actual observation search), here's an example with the newer API client class, which returns Observation objects instead of JSON: from pyinaturalist import iNatClient
observations = []
client = iNatClient()
for month, days in search_month_days.items():
query = client.observations.search(month=month, day=days, place_id=PLACE_ID)
observations.extend(query.all()) Also, if you think that's something you would use regularly, I might consider adding date range search (across all years) as a library feature. |
Beta Was this translation helpful? Give feedback.
The API almost has parameters to do what you want in a single query, but not quite. There is:
day
: observed on this day of the month (any year; accepts multiple values)month
: observed on this month of the year (any year; accepts multiple values)This will still have to be two separate queries when the start and end date are in different months, though. Here's an example that I think will do what you want.
Note that this doesn't account for larger date ranges that could span more than two months. It also doesn't handle leap years, or locations that span multiple time zones.