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));
}
}