Search code examples
javascriptgoogle-chrome-extensiongoogle-calendar-api

Finding an open time slot in Google Calendar in Chrome Extension


i was wondering what a smart approach to finding an open time slot in Google calendar. currently i'm using HTTP requests to Google Calendar API and specifically the freeBusy call.

i need to look for a 30 minute window specifically, so a brute force method i thought of was getting the current time, checking for a window, then iterating through the rest of the day by increasing the current time by 5 minutes. that seems very janky though.

here's the current code i have to check for to find a 30 minute spare block of time:

var date = {
    value: "2022-11-15",
  };
  var startTime = {
    value: "22:30",
  };
  var endTime = {
    value: "23:00",
  };

  var dateObj = {
    timeMin: date.value + "T" + startTime.value + ":00-08:00",
    timeMax: date.value + "T" + endTime.value + ":00-08:00",
    items: [
      {
        id: calendarId,
      },
    ],
    timeZone: "America/Vancouver",
  };
  console.log(dateObj);
  const test = {
    method: "POST",
    async: true,
    headers: {
      Authorization: "Bearer " + token,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(dateObj),
  };
  
  await fetch(
    "https://www.googleapis.com/calendar/v3/freeBusy",

    test
  )
    .then((response) => response.json()) // Transform the data into json
    .then((data) => console.log(data))
    .catch((err) => console.log(err));

Solution

  • I think you only need one call to the freeBusy endpoint.

    This will be my approach:

    1. I make a call to freeBusy between the working hours.
    {
     "timeMax": "2022-11-17T08:00:00.000",
     "timeMin": "2022-11-17T17:00:00.000Z",
     "items": [{"id": "primary"}]
    }
    
    1. In the response I have the hours where the user isn't avalaible.
    ...
     "calendars": {
      "primary": {
       "busy": [
        {
         "start": "2022-11-17T15:00:00Z",
         "end": "2022-11-17T15:30:00Z"
        },
        {
         "start": "2022-11-17T16:45:00Z",
         "end": "2022-11-17T17:15:00Z"
        }
       ]
      }
    ... 
    
    1. With that information and assuming that in my Frontend I have a form where the user can introduce a date and formatted as per RFC3339.
    const busyInfo = [
      {
        "start": "2022-11-17T15:00:00Z",
        "end": "2022-11-17T15:30:00Z"
      },
      {
        "start": "2022-11-17T16:45:00Z",
        "end": "2022-11-17T17:50:00Z"
      }
    ]
    // 30 min in ms
    const gap = 1.8e6
    /*
    / Check if a user is busy 
    / @param {string} date in ms ex: "2022-11-17T17:11:00Z"
    / @param {boolean} if the customer is busy
    / @returns {boolean}
    */
    function checkBusy(clientDate = "2022-11-17T16:46:00Z", isBusy = false) {
      clientDate = Date.parse(clientDate)
      for (const bi of busyInfo) {
        const [start, end] = [Date.parse(bi.start), Date.parse(bi.end)]
        if (start >= clientDate && clientDate + gap <= end) {
          isBusy = true
        }
      }
      return isBusy
    }
    

    The next steps are to control that action from your user in the Frontend.

    Documentation: