JavaScript to Generate iCal in HTML

After creating a calendar on Google for the podcast we needed to add a recurring event that included enumerable episode titles. Unfortunately Google Calendars does not have a function for this. I found this site written in php but it made week long events. Seeing the output though I decided to create something similar for single day events that occur weekly and need to be numbered. This is the code I wrote to do that. The initial code wasn’t difficult however I did have some trouble because JavaScript assumes all months are 31 days long.


1
2
3
4
5
6
7
8
9
10
11
//Function to create a list of number episodes for a calendar
function episodenumber() {
var startdate = new Date(2015, 8, 10);
var caldate = startdate;
var calyr;
var calMo;
var calda;
var calset;
var addSpace = "<p>";
var i;


The above declares the variables used in the function and sets the date to the start date of Complete Developer Podcast. Currently the dates are hard coded into this. I plan to remove them and add variables so that I can publish it on this site so that more than just than our start day and day of the week may be used. When I make those adjustments I will create a new project in my portfolio.

1
document.write("<p>BEGIN:VCALENDAR<br />VERSION:2.0<br />X-WR-CALNAME:WEEKNUMBERS<br />X-WR-TIMEZONE:America/Chicago<br />CALSCALE:GREGORIAN</p>");


Begining the iCal statement that can be copy/pasted into Google Calendars.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
for (i = 1; i <= 52; i++)
{
calyr = caldate.getFullYear().toString();
calMo = ((caldate.getMonth() + 1) < 10 ? "0" + (caldate.getMonth() + 1) : "" + (caldate.getMonth() + 1));
calda = (caldate.getDate() < 10 ? "0" + caldate.getDate() : "" + caldate.getDate());
calset = calyr + calMo + calda;
document.write(addSpace + "BEGIN:VEVENT" + "<br />");
document.write("DTSTART;VALUE=DATE:" + calset + "<br />");
document.write("DTEND;VALUE=DATE:" + calset + "<br />");
document.write("SUMMARY:Episode " + i + "<br />");
document.write("X-GOOGLE-CALENDAR-CONTENT-TITLE:Episode " + i + "<br />");
document.write("X-GOOGLE-CALENDAR-CONTENT-TYPE:text/html <br />");
document.write("END:VEVENT </p>");
addWeek(caldate);
addSpace = "<p>&nbsp";
if (caldate.getFullYear() != startdate.getFullYear())
{
i = 53;
};
};


A for loop to generate a calendar event for a day each week. JavaScript doesn’t add the leading ‘0’ in the month and day so for each one I wrote a simple statement to check if it is below 10 and add the ‘0’ if needed.

1
2
3
document.write("END:VCALENDAR");
};


Ending the iCal statement.

Because this was written in vanilla JavaScript that considers every month to contain 31 days I created this function to check if the month has less than 31 days and to then adjust the month and day for the appropriate number of days in the month. This was easy for most months having 30 days but difficult for February. I ran into some luck for future usability as 2016 is a leap year so I took that into consideration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function addWeek(caldate)
{
caldate.setDate(caldate.getDate() + 7);
var daySet = caldate;
var lessDay;
var addDay = caldate.getDate();
var momo = caldate.getMonth();
var yryr = caldate.getFullYear();
//Dealing with Javascript assuming every month has 31 days
if (momo === 4 || momo === 6 || momo === 9 || momo === 11)
{
addDay++;
daySet.setDate(addDay);
lessDay = addDay - 1;
}
else if (momo === 2 && (yryr%4 === 0))
{
addDay += 3;
daySet.setDate(addDay);
lessDay = addDay - 3;
}
else if (momo === 2 && (yryr % 4 != 0))
{
addDay += 4;
daySet.setDate(addDay);
lessDay = addDay - 4;
}
else
{
lessDay = addDay;
};
if (lessDay > 30)
{
caldate.setMonth(caldate.getMonth() - 1)
};
caldate.setDate(daySet.getDate());
caldate.setDate(lessDay);


Finally to make sure that the event always fell on a Thursday as that is the day we publish I wrote a switch/case to check the day of the week and adjust the date according to the distance to Thursday.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
switch (caldate.getDay) {
case 0:
caldate.setDate(caldate.getDate() - 3);
break;
case 1:
caldate.setDate(caldate.getDate() - 4);
break;
case 2:
caldate.setDate(caldate.getDate() - 5);
break;
case 3:
caldate.setDate(caldate.getDate() - 6);
break;
case 4:
break;
case 5:
caldate.setDate(caldate.getDate() - 1);
break;
case 6:
caldate.setDate(caldate.getDate() - 2);
break;
};
}

episode numbers

The final product can be seen in the above image. To add this to Google Calendars I first copied the generated iCal to a file in VS Code and saved it as a .ics file.

1
2
3
4
5
6
7
8
9
10
11
12
13
BEGIN:VCALENDAR
VERSION:2.0
X-WR-CALNAME:WEEKNUMBERS
X-WR-TIMEZONE:Chicago
CALSCALE:GREGORIAN
BEGIN:VEVENT
DTSTART;VALUE=DATE:20150910
DTEND;VALUE=DATE:20150910
SUMMARY:Episode 1
X-GOOGLE-CALENDAR-CONTENT-TITLE:Episode 1
X-GOOGLE-CALENDAR-CONTENT-TYPE:text/html
END:VEVENT

Next I logged into the Complete Developer Podcast Google Calendar and under My calendars selected Tasks then Import calendar. I selected the .ics file I had created and imported it. Future iterations of this will produce the .ics file for download along with the html, however for a quick fix this worked.

To follow my progress on this project check out my GitHub account. You can also see an image of me with a short beard and a bow tie.