Katkat

Design Calendar Event CRUD with Unit Tests

RampSoftware Engineer · Technical Screen

Last updated

Design and implement a robust in-memory calendar event service supporting full CRUD operations, conflict detection, and search, along with a comprehensive suite of unit test cases.

Calendar Event Service with Unit Tests

Design and implement an in-memory CalendarService class that handles standard CRUD operations for single-user or team calendar events, enforces business validation rules, and includes a comprehensive set of unit tests.

Requirements

Implement the following class interface:

from typing import List, Optional, Dict

class Event:
    def __init__(self, event_id: str, title: str, start_time: int, end_time: int, attendees: List[str]):
        self.id = event_id
        self.title = title
        self.start_time = start_time  # Unix timestamp in seconds
        self.end_time = end_time      # Unix timestamp in seconds
        self.attendees = attendees

class CalendarService:
    def create_event(self, title: str, start_time: int, end_time: int, attendees: List[str]) -> Event:
        """Creates a new event. Raises ValueError if validation fails."""
        pass

    def get_event(self, event_id: str) -> Optional[Event]:
        """Fetches event by ID, or None if not found."""
        pass

    def update_event(self, event_id: str, title: Optional[str] = None, 
                     start_time: Optional[int] = None, end_time: Optional[int] = None,
                     attendees: Optional[List[str]] = None) -> Event:
        """Updates an existing event. Raises ValueError or KeyError on error."""
        pass

    def delete_event(self, event_id: str) -> bool:
        """Deletes an event. Returns True if deleted, False if not found."""
        pass

    def get_events_in_range(self, start_time: int, end_time: int) -> List[Event]:
        """Returns all events that overlap with [start_time, end_time], sorted by start_time ascending."""
        pass

    def find_conflicts(self, user: str, start_time: int, end_time: int, exclude_event_id: Optional[str] = None) -> List[Event]:
        """Returns existing events involving `user` that overlap with [start_time, end_time]."""
        pass

Validation Rules

  1. start_time must be strictly less than end_time (start_time < end_time).
  2. title must be a non-empty, non-whitespace string.
  3. Overlap definition: Two intervals [s1, e1] and [s2, e2] overlap if and only if max(s1, s2) < min(e1, e2) (i.e., touching boundaries e1 == s2 do not overlap).
  4. All timestamps are non-negative integers.

Deliverables

  1. A complete, clean implementation of CalendarService.
  2. A suite of unit tests (using unittest or standard pytest style assertions) covering normal paths, edge cases (boundary touching, missing IDs, invalid times), and partial updates.

Example

service = CalendarService()
e1 = service.create_event("Sprint Planning", 100, 200, ["[email protected]", "[email protected]"])
e2 = service.create_event("1:1 Sync", 200, 300, ["[email protected]"])

# Querying range [150, 250] returns both events because [100, 200] and [200, 300] both overlap [150, 250]
assert len(service.get_events_in_range(150, 250)) == 2

# Touching intervals do not conflict: [100, 200] does not overlap with candidate [200, 250]
assert len(service.find_conflicts("[email protected]", 200, 250, exclude_event_id=e2.id)) == 0

Hints

Hint 1

Ensure interval comparison strictly uses `max(s1, s2) < min(e1, e2)` to prevent off-by-one errors with adjacent events.

Hint 2

For updates, construct the prospective state of the event first to validate it before committing changes to storage.

Hint 3

Structure your unit tests into distinct classes or test functions: validation tests, CRUD behavior tests, and range/overlap query tests.

Follow-up questions

  • How would you optimize `get_events_in_range` and `find_conflicts` if the calendar holds millions of events (e.g., using interval trees or segment trees)?
  • How would you extend this service and its test suite to support recurring events (e.g., daily, weekly, RRULE format) without storing infinite instances?
  • How would you handle concurrent writes to the same calendar in a distributed environment to prevent race conditions during conflict checks?