Something I find useful on occasion is to have a full-year calendar to refer to, so I worked out how to generate an Obsidian note with that information using Templater.
First, I wrote the following javascript file and added it to my Templater scripts folder:
mdCalendar.js
function mdCalendar(year,month,mondayFirst)
{
if (mondayFirst === undefined) { mondayFirst = false; }
//Step 1: build an array of the abbreviated weekday names
let dd = new Date(2022,1,27); //a Sunday
let wnames = [];
for (let i = 0; i < 8; i++)
{
wnames.push(dd.toLocaleString('default', { weekday: 'short' }));
dd.setDate(dd.getDate() + 1);
}
if (mondayFirst)
{
wnames = wnames.slice(1,8); //gives [Mon,Tue,Wed,Thu,Fri,Sat,Sun]
}
else
{
wnames = wnames.slice(0,7); //gives [Sun,Mon,Tue,Wed,Thu,Fri,Sat]
}
//Step 2: Get first day of the month
// (Note: in the javascript Date object, the month has values from 0[Jan] to 11[Dec].)
let day = new Date(year,month - 1,1);
//Step 3: Establish the calendar header which includes the month, year, and abbreviated weekday names
let cal = `${day.toLocaleString('default', { month: 'long' })} ${year}\n\n`
+ `| ${wnames.join(" | ")} |\n`
+ "|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n"
;
//Step 4: Populate the calendar with the days of the month
let week = [' .. ',' .. ',' .. ',' .. ',' .. ',' .. ',' .. '];
while (day.getMonth() == month - 1)
{
let wday = day.getDay(); //day of the week (0[Sun] - 6[Sat])
if (mondayFirst) { wday = (wday - 1 < 0) ? 6 : wday - 1; }
let d = `${day.getDate()}`;
week[wday] = ' ' + d.padStart(2,'0') + ' ';
if (wday == 6)
{
cal += '|' + week.join('|') + '|\n';
week = [' .. ',' .. ',' .. ',' .. ',' .. ',' .. ',' .. '];
}
day = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1);
}
if (week[0] != ' .. ') { cal += '|' + week.join('|') + '|\n'; }
return cal;
}
module.exports = mdCalendar;
The mdCalendar
function requires two pieces of information: the 4-digit year and the month number (1-12). An optional third parameter determines whether the week starts on Monday (true) or on Sunday (false). If this parameter is omitted, the calendar starts on Sunday. From these parameters, it generates a Markdown table for that month’s calendar. For example, calling mdCalendar(2022,6,true)
will return:
June 2022
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| .. | .. | 01 | 02 | 03 | 04 | 05 |
| 06 | 07 | 08 | 09 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | .. | .. | .. |
Note 1:
The month name and the weekday abbreviations come from the machine’s localization settings. Presumably, therefore, if you ran this on a system other than an English one, it should output content in the local language. I don’t have a way to verify this.
Note 2:
To turn the days into links, you’d need to modify the line week[wday] = ' ' + d.padStart(2,'0') + ' ';
to match the format you use to name day notes. For example, if you use the format YYYY-MM-DD to name your notes, try something like:
week[wday] = ' [[' + day.toISOString().slice(0, 10) + '|' + d.padStart(2,'0') + ']] ';
Second, I put together the following template and added it to my Templater templates folder:
insert-year-calendar.md
<%*
let year = await tp.system.prompt("Year of Calendar",tp.date.now("YYYY"));
let firstd = await tp.system.suggester(["Sunday","Monday"],["Sunday","Monday"],false,"First Day of the Week");
let monFirst = false;
if (firstd == "Monday") { monFirst = true; }
if (tp.file.title.startsWith("Untitled"))
{
await tp.file.rename(`${year}.calendar`);
}
tR += `# ${year} Calendar\n\n`
for (let i = 1; i <= 12; i++)
{
tR += `## ${tp.user.mdCalendar(year,i,monFirst)}\n\n`;
}
%>
Opening a new note and then running this template through Templater will prompt you to enter the desired year (defaulting to the current one) and to pick which day starts the week. From that it will populate the note with the month calendars for the entire year. On my Obsidian instance it looks like this (in edit mode) when it’s done:
I hope this helps get you to what you need.