Machine Coding Problem

Shared Calendar

macoAllproductivityrecurring-event-expansion
Commonly Asked By:GoogleMicrosoftApple

Functional Specifications

  • Dynamic Event Scheduler: Book events with subject titles, organizers, and active guest lists.
  • Recurrence Rule Engine (RRULE): Set recurring loops (daily or weekly occurrences) stored as compact rules rather than distinct static DB items.
  • Dynamic Calendar Conflict Check: Instantly parse schedules across all invited guests to detect overlapping slots before final registration.
  • Timezone Translation: Store timestamps as UTC values and dynamically translate times for local timezones (EST, IST, UTC, JST) on the client side.
  • Specific Date Occurrence Exclusions: Cancel single occurrences of a recurring event series without deleting the entire rule sequence.

Production reference implementations demonstrating rule expanders, dynamic conflicts, exclusions, and timezone conversions:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.time.*;
import java.util.*;
import java.util.concurrent.*;

enum Frequency { DAILY, WEEKLY, MONTHLY }

enum ResponseStatus { ACCEPTED, DECLINED, TENTATIVE }

class SharedCalendarService {
    private final List<CalendarEvent> events = new CopyOnWriteArrayList<>();
    private final ConcurrentHashMap<String, Map<String, ResponseStatus>> inviteResponses = new ConcurrentHashMap<>();

    public void createEvent(CalendarEvent event) {
        events.add(event);
        inviteResponses.put(event.getId(), new ConcurrentHashMap<>());
    }

    public void respondToInvite(String eventId, String attendeeEmail, ResponseStatus status) {
        inviteResponses.computeIfAbsent(eventId, k -> new ConcurrentHashMap<>())
                       .put(attendeeEmail, status);
    }

    public List<EventOccurrence> getSchedule(String email, ZonedDateTime startRange, ZonedDateTime endRange) {
        List<EventOccurrence> schedule = new ArrayList<>();

        for (CalendarEvent event : events) {
            // Check if user is either organizer or attendee
            if (!event.getOrganizer().equals(email) && !event.getAttendees().contains(email)) {
                continue;
            }

            // Skip if the user has explicitly declined the event
            Map<String, ResponseStatus> responses = inviteResponses.get(event.getId());
            if (responses != null && responses.get(email) == ResponseStatus.DECLINED) {
                continue;
            }

            if (event.getRecurrenceRule() != null) {
                // Expand recurring occurrences within the queried range window
                List<ZonedDateTime> starts = event.getRecurrenceRule().expand(event.getStartTime(), startRange, endRange);
                for (ZonedDateTime start : starts) {
                    schedule.add(new EventOccurrence(event, start, start.plus(event.getDuration())));
                }
            } else {
                ZonedDateTime start = event.getStartTime();
                ZonedDateTime end = start.plus(event.getDuration());
                if (!end.isBefore(startRange) && !start.isAfter(endRange)) {
                    schedule.add(new EventOccurrence(event, start, end));
                }
            }
        }

        // Sort chronological
        schedule.sort(Comparator.comparing(EventOccurrence::getStart));
        return schedule;
    }

    public boolean hasConflict(String email, ZonedDateTime checkStart, ZonedDateTime checkEnd) {
        List<EventOccurrence> schedule = getSchedule(email, checkStart.minusDays(1), checkEnd.plusDays(1));
        for (EventOccurrence occ : schedule) {
            if (occ.getStart().isBefore(checkEnd) && occ.getEnd().isAfter(checkStart)) {
                return true; // Overlap detected
            }
        }
        return false;
    }

    public static class RecurrenceRule {
        private final Frequency frequency;
        private final int interval;
        private final LocalDate until;
        private final Set<LocalDate> exceptionDates = ConcurrentHashMap.newKeySet();

        public RecurrenceRule(Frequency frequency, int interval, LocalDate until) {
            this.frequency = frequency;
            this.interval = interval;
            this.until = until;
        }

        public void addException(LocalDate date) {
            exceptionDates.add(date);
        }

        public List<ZonedDateTime> expand(ZonedDateTime start, ZonedDateTime rangeStart, ZonedDateTime rangeEnd) {
            List<ZonedDateTime> occurrences = new ArrayList<>();
            ZonedDateTime current = start;

            while (current.isBefore(rangeEnd) && (until == null || !current.toLocalDate().isAfter(until))) {
                LocalDate curDate = current.toLocalDate();
                if (!exceptionDates.contains(curDate)) {
                    if (!current.isBefore(rangeStart)) {
                        occurrences.add(current);
                    }
                }

                switch (frequency) {
                    case DAILY:
                        current = current.plusDays(interval);
                        break;
                    case WEEKLY:
                        current = current.plusWeeks(interval);
                        break;
                    case MONTHLY:
                        current = current.plusMonths(interval);
                        break;
                }
            }
            return occurrences;
        }

        public Frequency getFrequency() { return frequency; }
        public int getInterval() { return interval; }
        public LocalDate getUntil() { return until; }
        public Set<LocalDate> getExceptionDates() { return exceptionDates; }
    }

    public static class CalendarEvent {
        private final String id;
        private final String title;
        private final String organizer;
        private final Set<String> attendees = ConcurrentHashMap.newKeySet();
        private final ZonedDateTime startTime;
        private final Duration duration;
        private final RecurrenceRule recurrenceRule;

        public CalendarEvent(String title, String organizer, ZonedDateTime startTime, Duration duration, RecurrenceRule recurrenceRule) {
            this.id = UUID.randomUUID().toString();
            this.title = title;
            this.organizer = organizer;
            this.startTime = startTime;
            this.duration = duration;
            this.recurrenceRule = recurrenceRule;
        }

        public String getId() { return id; }
        public String getTitle() { return title; }
        public String getOrganizer() { return organizer; }
        public Set<String> getAttendees() { return attendees; }
        public ZonedDateTime getStartTime() { return startTime; }
        public Duration getDuration() { return duration; }
        public RecurrenceRule getRecurrenceRule() { return recurrenceRule; }

        public void addAttendee(String email) { attendees.add(email); }
    }

    public static class EventOccurrence {
        private final CalendarEvent event;
        private final ZonedDateTime start;
        private final ZonedDateTime end;

        public EventOccurrence(CalendarEvent event, ZonedDateTime start, ZonedDateTime end) {
            this.event = event;
            this.start = start;
            this.end = end;
        }

        public CalendarEvent getEvent() { return event; }
        public ZonedDateTime getStart() { return start; }
        public ZonedDateTime getEnd() { return end; }
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("=== SHARED CALENDAR DEMO (JAVA) ===");
        SharedCalendarService calendarService = new SharedCalendarService();

        ZonedDateTime start = ZonedDateTime.of(2026, 5, 20, 10, 0, 0, 0, ZoneId.of("UTC"));
        Duration oneHour = Duration.ofHours(1);

        // Create daily standup event
        SharedCalendarService.RecurrenceRule dailyRule = new SharedCalendarService.RecurrenceRule(
            Frequency.DAILY, 1, LocalDate.of(2026, 5, 25)
        );
        SharedCalendarService.CalendarEvent standup = new SharedCalendarService.CalendarEvent(
            "Daily Standup", "alice@company.com", start, oneHour, dailyRule
        );
        standup.addAttendee("bob@company.com");
        standup.addAttendee("charlie@company.com");

        calendarService.createEvent(standup);
        System.out.println("Daily standup created (recurrence: daily until 2026-05-25).");

        // Add exception: cancel occurrence on 2026-05-22
        dailyRule.addException(LocalDate.of(2026, 5, 22));
        System.out.println("Added recurrence exception (canceled occurrence on 2026-05-22).");

        // Get schedule for Bob in the range May 20 - May 24
        ZonedDateTime queryStart = ZonedDateTime.of(2026, 5, 20, 0, 0, 0, 0, ZoneId.of("UTC"));
        ZonedDateTime queryEnd = ZonedDateTime.of(2026, 5, 24, 23, 59, 59, 0, ZoneId.of("UTC"));

        System.out.println("\nBob's Schedule (May 20 to May 24):");
        List<SharedCalendarService.EventOccurrence> schedule = calendarService.getSchedule("bob@company.com", queryStart, queryEnd);
        for (SharedCalendarService.EventOccurrence occ : schedule) {
            System.out.println("Event: " + occ.getEvent().getTitle() + " | Start: " + occ.getStart() + " | End: " + occ.getEnd());
        }

        // Check for conflicts
        ZonedDateTime conflictStart = ZonedDateTime.of(2026, 5, 21, 10, 30, 0, 0, ZoneId.of("UTC"));
        ZonedDateTime conflictEnd = ZonedDateTime.of(2026, 5, 21, 11, 30, 0, 0, ZoneId.of("UTC"));
        System.out.println("\nChecking conflict for Bob on May 21 at 10:30 UTC: " + 
            calendarService.hasConflict("bob@company.com", conflictStart, conflictEnd));

        ZonedDateTime clearStart = ZonedDateTime.of(2026, 5, 21, 14, 0, 0, 0, ZoneId.of("UTC"));
        ZonedDateTime clearEnd = ZonedDateTime.of(2026, 5, 21, 15, 0, 0, 0, ZoneId.of("UTC"));
        System.out.println("Checking conflict for Bob on May 21 at 14:00 UTC: " + 
            calendarService.hasConflict("bob@company.com", clearStart, clearEnd));
    }
}