[Bounty proposal] fix(calendar): normalize naive dateTime strings and guard None values in parse_event_times ($50 proposed)
Maintainers usually reply within 1 day
@huynhnhatquandongnai-source is already working on this.
Since Oct 19, 2026.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
Research direction
Read backend/utils/conversations/calendar_utils.py and the overlap paths in backend/utils/conversations/calendar_linking.py named in the issue. Then inspect backend/tests/unit/test_calendar_linking_overlap_selection.py and reproduce the naive datetime and dateTime: None cases. Done means both cases are handled without comparison or parsing errors and the regression tests pass.
Written by the indexing model from the issue text.
Description
Summary
parse_event_times(event) in backend/utils/conversations/calendar_utils.py parses start['dateTime'] and end['dateTime'] via datetime.fromisoformat(str(start['dateTime']).replace('Z', '+00:00')) without normalizing timezone-naive datetimes to UTC, while all-day date events are constructed with +00:00 (offset-aware UTC).
When a Google Calendar feed contains a floating-time or ICS-imported event whose start.dateTime / end.dateTime lacks a UTC offset (e.g. "2026-08-18T19:30:00"), parse_event_times returns offset-naive datetime objects (tzinfo=None). Downstream callers that compare those event bounds against timezone-aware UTC conversation bounds (select_overlapping_calendar_event at backend/utils/conversations/calendar_linking.py:103-104 and select_capture_gaps at backend/utils/conversations/calendar_linking.py:166) crash with TypeError: can't compare offset-naive and offset-aware datetimes.
Additionally, if start or end carries an explicit {"dateTime": None, "date": "2026-08-18"}, 'dateTime' in start evaluates to True and str(None) fails fromisoformat("None") instead of falling through to the 'date' branch.
Exact Code Locations
backend/utils/conversations/calendar_utils.py:18-33:
if 'dateTime' in start:
start_dt = datetime.fromisoformat(str(start['dateTime']).replace('Z', '+00:00'))
elif 'date' in start:
start_dt = datetime.fromisoformat(str(start['date']) + 'T00:00:00+00:00')
backend/utils/conversations/calendar_linking.py:99-105(select_overlapping_calendar_event):
event_start, event_end = parse_event_times(event)
...
overlap_start = max(event_start, conversation_start)
overlap_end = min(event_end, conversation_end)
backend/utils/conversations/calendar_linking.py:159-168(select_capture_gaps):
event_start, event_end = parse_event_times(event)
...
covered = any(
(min(event_end, window_end) - max(event_start, window_start)).total_seconds() >= MIN_OVERLAP_SECONDS
for window_start, window_end in conversation_windows
)
Concrete Reproduction & Crash Traceback
from datetime import datetime, timezone
from utils.conversations.calendar_linking import select_overlapping_calendar_event
floating_event = {
"id": "evt-floating",
"summary": "Floating Sync",
"status": "confirmed",
"start": {"dateTime": "2026-08-18T19:30:00"},
"end": {"dateTime": "2026-08-18T20:00:00"},
}
conv_start = datetime(2026, 8, 18, 19, 35, tzinfo=timezone.utc)
conv_end = datetime(2026, 8, 18, 19, 50, tzinfo=timezone.utc)
select_overlapping_calendar_event([floating_event], conv_start, conv_end)
Raises:
TypeError: can't compare offset-naive and offset-aware datetimes
Proposed Fix
- In
parse_event_times(event)(backend/utils/conversations/calendar_utils.py), attachtzinfo=timezone.utcwhen parsedstart_dtorend_dthastzinfo is None. - Check
start.get('dateTime') is not None/end.get('dateTime') is not Nonebeforestart.get('date') is not None/end.get('date') is not None, and guard non-dicteventinputs. - Add regression tests in
backend/tests/unit/test_calendar_linking_overlap_selection.py.
Bounty settlement address (Base Mainnet USDC): 0xb9f3765aeb1974c27a193463f655a1a57b3aec94
- Dominant language
- Python
- Stars
- 13.8k
- Forks
- 2.6k
- Avg merge
- 5h 14m
- Merged PRs (30d)
- 626
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from BasedHardware/omi
-
Go device SDK: Whisper transcriber keeps buffering and transcribing audio appended after Stop()Possibly taken @apoorvdarshan claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
BasedHardware/omi#22770 ·
Maintainers usually reply within 1 day
-
[Bounty proposal] fix(entity-pages): normalize mixed naive, aware, and ISO conversation timestamps ($50 proposed)Possibly taken @huynhnhatquandongnai-source claimed this 2 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
BasedHardware/omi#22620 · 2 comments ·
Maintainers usually reply within 1 day
-
[Bounty proposal] fix(calendar): normalize naive start timestamps and guard malformed start dicts in multi-window sort ($50 proposed)Possibly taken @huynhnhatquandongnai-source claimed this 2 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
BasedHardware/omi#22614 · 2 comments ·
Maintainers usually reply within 1 day
-
[Bounty proposal] fix(memory): normalize mixed naive and aware evidence timestamps when ordering capture devices ($50 proposed)Possibly taken @huynhnhatquandongnai-source claimed this 2 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
BasedHardware/omi#22611 · 1 comment ·
Maintainers usually reply within 1 day
-
Python CLI: corrupt compressed responses hide an unknown write outcomePossibly taken @pranav440 claimed this 9 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
BasedHardware/omi#21295 · 1 comment ·
Maintainers usually reply within 1 day
All issues in BasedHardware/omi
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
pgvector/pgvector-python#169 ·
-
ChaosEngine: backup-remote doctor row passes while consumer mode hides bot memory from gitPossibly taken @MohabMohie claimed this today. Openagentic
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
ShaftHQ/SHAFT_ENGINE#7263 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 87/100
huggingface/smolagents#3045 ·
Maintainers usually reply within 1 day