Oct 15, 2024 05:08 AM
I'm trying to build an automation that, based on a set of input values specified by a user, will output a set of available dates to create timeblocks in a calendar. The user specifies what date to start with, how many weeks to create these blocks for, as well as start & end times for the day, break time & duration, and how long each timeblock can be for (including some follow-up time). The code I've worked up seems to generate the output I am hoping for when compiled, but output.set and the console.log seem null when this runs in Airtable.
Here's my script:
let inputConfig = input.config();
let daysOfWeek = inputConfig.daysOfWeek;
let sessionDuration = inputConfig.sessionDuration;
let startTime = inputConfig.startTime;
let endTime = inputConfig.endTime;
let followUpTime = inputConfig.followUpTime;
let startDate = inputConfig.startDate;
let numWeeks = inputConfig.numWeeks;
let breakStartTime = inputConfig.breakStartTime;
let breakDuration = inputConfig.breakDuration;
// Helper function to add minutes to a Date object
function addMinutes(date, minutes) {
return new Date(date.getTime() + minutes * 60000);
}
// Helper function to get the day of the week index from a string (e.g., 'Monday' -> 1)
function getDayIndex(day) {
const daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
return daysOfWeek.indexOf(day);
}
// Function to convert 'YYYY-MM-DD' string to Date object
function parseDateString(dateString) {
const dateParts = dateString.split("-");
const year = parseInt(dateParts[0], 10);
const month = parseInt(dateParts[1], 10) - 1; // JavaScript months are 0-based
const day = parseInt(dateParts[2], 10);
return new Date(year, month, day);
}
// Main function to generate calendar entries
function generateCalendarEntries(startDateStr, numWeeks, daysOfWeek, startTime, endTime, sessionDuration, followUpTime, breakStartTime, breakDuration) {
// Parse the startDateStr to a Date object
const startDate = parseDateString(startDateStr);
const entries = [];
const msInAWeek = 7 * 24 * 60 * 60 * 1000; // Milliseconds in one week
// Loop through each week
for (let week = 0; week < numWeeks; week++) {
// Loop through the specified days of the week
daysOfWeek.forEach(day => {
const dayIndex = getDayIndex(day);
if (dayIndex === -1) return; // Invalid day name, skip
// Calculate the actual date for this day in the current week
const dayDate = new Date(startDate); // Clone the startDate
dayDate.setDate(startDate.getDate() + (7 * week) + (dayIndex - startDate.getDay()));
// Set the start and end time for the entire day
const start = new Date(dayDate);
start.setHours(startTime.split(":")[0], startTime.split(":")[1], 0, 0);
const end = new Date(dayDate);
end.setHours(endTime.split(":")[0], endTime.split(":")[1], 0, 0);
// Break period start and dynamically calculated end time
const breakStart = new Date(dayDate);
breakStart.setHours(breakStartTime.split(":")[0], breakStartTime.split(":")[1], 0, 0);
const breakEnd = addMinutes(breakStart, breakDuration);
// Handle sessions before the break
let sessionStart = start;
while (sessionStart < breakStart) {
const sessionEnd = addMinutes(sessionStart, sessionDuration + followUpTime);
// Skip session if it doesn't fit before the break
if (sessionEnd > breakStart) break;
entries.push({
title: "Session",
start: sessionStart,
end: sessionEnd
});
sessionStart = sessionEnd; // Move to the next session slot
}
// Handle sessions after the break
sessionStart = breakEnd;
while (sessionStart < end) {
const sessionEnd = addMinutes(sessionStart, sessionDuration + followUpTime);
// Skip session if it doesn't fit before the end of the day
if (sessionEnd > end) break;
entries.push({
title: "Session",
start: sessionStart,
end: sessionEnd
});
sessionStart = sessionEnd; // Move to next session slot
}
});
}
return entries;
}
const calendarEntries = generateCalendarEntries(startDate, numWeeks, daysOfWeek, startTime, endTime, sessionDuration, followUpTime, breakStartTime, breakDuration);
console.log(calendarEntries);
output.set("Entries", calendarEntries);
And here's the output I get running this through an online compiler:
[
{
title: 'Session',
start: 2024-10-15T10:00:00.000Z,
end: 2024-10-15T11:00:00.000Z
},
{
title: 'Session',
start: 2024-10-15T11:00:00.000Z,
end: 2024-10-15T12:00:00.000Z
},
{
title: 'Session',
start: 2024-10-15T13:00:00.000Z,
end: 2024-10-15T14:00:00.000Z
},
{
title: 'Session',
start: 2024-10-15T14:00:00.000Z,
end: 2024-10-15T15:00:00.000Z
},
{
title: 'Session',
start: 2024-10-17T10:00:00.000Z,
end: 2024-10-17T11:00:00.000Z
},
{
title: 'Session',
start: 2024-10-17T11:00:00.000Z,
end: 2024-10-17T12:00:00.000Z
},
{
title: 'Session',
start: 2024-10-17T13:00:00.000Z,
end: 2024-10-17T14:00:00.000Z
},
{
title: 'Session',
start: 2024-10-17T14:00:00.000Z,
end: 2024-10-17T15:00:00.000Z
},
{
title: 'Session',
start: 2024-10-22T10:00:00.000Z,
end: 2024-10-22T11:00:00.000Z
},
{
title: 'Session',
start: 2024-10-22T11:00:00.000Z,
end: 2024-10-22T12:00:00.000Z
},
{
title: 'Session',
start: 2024-10-22T13:00:00.000Z,
end: 2024-10-22T14:00:00.000Z
},
{
title: 'Session',
start: 2024-10-22T14:00:00.000Z,
end: 2024-10-22T15:00:00.000Z
},
{
title: 'Session',
start: 2024-10-24T10:00:00.000Z,
end: 2024-10-24T11:00:00.000Z
},
{
title: 'Session',
start: 2024-10-24T11:00:00.000Z,
end: 2024-10-24T12:00:00.000Z
},
{
title: 'Session',
start: 2024-10-24T13:00:00.000Z,
end: 2024-10-24T14:00:00.000Z
},
{
title: 'Session',
start: 2024-10-24T14:00:00.000Z,
end: 2024-10-24T15:00:00.000Z
},
{
title: 'Session',
start: 2024-10-29T10:00:00.000Z,
end: 2024-10-29T11:00:00.000Z
},
{
title: 'Session',
start: 2024-10-29T11:00:00.000Z,
end: 2024-10-29T12:00:00.000Z
},
{
title: 'Session',
start: 2024-10-29T13:00:00.000Z,
end: 2024-10-29T14:00:00.000Z
},
{
title: 'Session',
start: 2024-10-29T14:00:00.000Z,
end: 2024-10-29T15:00:00.000Z
},
{
title: 'Session',
start: 2024-10-31T10:00:00.000Z,
end: 2024-10-31T11:00:00.000Z
},
{
title: 'Session',
start: 2024-10-31T11:00:00.000Z,
end: 2024-10-31T12:00:00.000Z
},
{
title: 'Session',
start: 2024-10-31T13:00:00.000Z,
end: 2024-10-31T14:00:00.000Z
},
{
title: 'Session',
start: 2024-10-31T14:00:00.000Z,
end: 2024-10-31T15:00:00.000Z
},
{
title: 'Session',
start: 2024-11-05T10:00:00.000Z,
end: 2024-11-05T11:00:00.000Z
},
{
title: 'Session',
start: 2024-11-05T11:00:00.000Z,
end: 2024-11-05T12:00:00.000Z
},
{
title: 'Session',
start: 2024-11-05T13:00:00.000Z,
end: 2024-11-05T14:00:00.000Z
},
{
title: 'Session',
start: 2024-11-05T14:00:00.000Z,
end: 2024-11-05T15:00:00.000Z
},
{
title: 'Session',
start: 2024-11-07T10:00:00.000Z,
end: 2024-11-07T11:00:00.000Z
},
{
title: 'Session',
start: 2024-11-07T11:00:00.000Z,
end: 2024-11-07T12:00:00.000Z
},
{
title: 'Session',
start: 2024-11-07T13:00:00.000Z,
end: 2024-11-07T14:00:00.000Z
},
{
title: 'Session',
start: 2024-11-07T14:00:00.000Z,
end: 2024-11-07T15:00:00.000Z
}
]
And here's what I get when it runs in Airtable:
I'd welcome any guidance as to what I am missing. Thanks in advance!
Solved! Go to Solution.
Oct 16, 2024 05:28 AM
Turns out the solution here was that I had some issues caused by `sessionDuration` and `followupTime` being strings instead of ints. After converting them that solved part of the issue:
let sessionDuration = +inputConfig.sessionDuration;
let followUpTime = +inputConfig.followUpTime;
I also needed to convert dates to ISO strings :
function toISOString(date){
return new Date(date).toISOString()
}
entries.push({
title: "Session",
start: toISOString(sessionStart),
end: toISOString(sessionEnd)
});
After making those changes and some other adjustments to the date fields in my table to all use the same TZ, my script now generates the expected output. Many thanks to @TheTimeSavingCo for the assist!
Oct 15, 2024 06:26 AM
If you could DM me an invite link to your base I could try helping you troubleshoot this? I'd suggest just dumping a bunch of logging inside your functions to see what's happening. May I know how much development experience you have?
Oct 15, 2024 07:43 AM
Thanks, I followed up with you directly.
Oct 16, 2024 05:28 AM
Turns out the solution here was that I had some issues caused by `sessionDuration` and `followupTime` being strings instead of ints. After converting them that solved part of the issue:
let sessionDuration = +inputConfig.sessionDuration;
let followUpTime = +inputConfig.followUpTime;
I also needed to convert dates to ISO strings :
function toISOString(date){
return new Date(date).toISOString()
}
entries.push({
title: "Session",
start: toISOString(sessionStart),
end: toISOString(sessionEnd)
});
After making those changes and some other adjustments to the date fields in my table to all use the same TZ, my script now generates the expected output. Many thanks to @TheTimeSavingCo for the assist!