Condensing/Simplifying a complicated If-Then problem (Templater and Full Calendar Plugins)

What I’m trying to do

I started using the Full Calendar (FC) plugin for obsidian to create a daily calendar that I can put in a sidebar. With FC, it creates a new note for every event that you add to the calendar, where the frontmatter of the note is used to place the event on the calendar in the correct place, with the correct times, day, titles, recurrences, etc.

If the event is a single instance event, its note has a frontmatter key “date:” where the value is the date of the event.

If the event is a recurring event, the note DOES NOT have the “date:” key, and instead has “daysOfWeek:”, “startRecur:”, and “endRecur:” keys. The start and end recur keys have values in date format. The Days of Week key has a value in list format, where the recurring days are represented by a single letter. EX:

daysOfWeek:

  • F
  • W
  • M

I am trying to create a template for these created “event notes” that places links to the events’ associated daily notes. For the NON-recurring events, this is easy to do through a reference to the “date:” frontmatter. i.e.

Date: <%* if (tp.frontmatter.date) { %> [[<% tp.frontmatter.date %>]] <%* } else { %> <%* } %>

However, it is tricky when trying to get all the dates for an event that recurs since I have to somehow combine the start and end date, with the letters in the daysOfWeek property to create a list of the dates. I will show how I have found a workaround below, but it is way too unwieldy and long. I do not have any formal coding or javascript experience, and have just pieced together some knowledge from the internet and have hit my limit.

The problem is that I am doing each piece of the work separately and “by hand” and it creates huge blocks of codes that feel excessive. I have to do each day (Sunday through Saturday) separately. And then for each day, I have to go through each successive week individually. It creates huge blocks that cant be the best way to do this.

Is there a way to take what I have done below and simplify it? Or automate it? Or just any other way to do this?

Thanks for all the help!!


Things I have tried

Parts Used:

StartRecur date: <% tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>

EndRecur date: <% tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.endRecur, “YYYY-MM-DD”) %>

The date of the Monday of the week in which StartRecur happens: <% tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>

The date of the Monday 15 weeks after StartRecur happens: <% tp.date.weekday(“YYYY-MM-DD”, 106, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>

every other week between 0 and 15 are also included in the below explanation, but the only change is the “offset” value of the templater script.


My Understanding of how the Program works in laymen terms:

Level 1:

  • IF
    • daysOfWeek frontmatter exists,
    • The Monday of Week of StartRecur is same or after StartRecur,
    • daysOfWeek includes “M”, AND
    • The Monday of 15 Weeks after StartRecur is same or before EndRecur
  • THEN list
    • Every Monday between Week 0 and Week 15
  • ELSE Level 2
    Level 2:
  • IF
    • daysOfWeek frontmatter exists
    • The Monday of Week of StartRecur is same or after StartRecur,
    • daysOfWeek includes “M”, AND
    • The Monday of 14 Weeks after StartRecur is same or before EndRecur
  • THEN list
    • Every Monday between Week 0 and Week 14
  • ELSE Level 3
    Level 3:
    .
    .
    .
    Level 15:
  • IF
    • daysOfWeek frontmatter exists
    • The Monday of Week of StartRecur is same or after StartRecur,
    • daysOfWeek includes “M”, AND
    • The Monday of Week after StartRecur is same or before EndRecur
  • THEN list
    • Monday of Week of StartRecur and Week after StartRecur
  • ELSE level 16
    Level 16:
  • IF
    • daysOfWeek frontmatter exists
    • The Monday of Week of StartRecur is same or after StartRecur,
    • daysOfWeek includes “M”, AND
    • The Monday of Week of StartRecur is same or before EndRecur
  • THEN list
    • Monday of Week of StartRecur
  • ELSE display “blank”

Selections from the code/program I am using:

Very Beginning (This part captures 15 and 14 weeks after StartRecur)

<%*
if (tp.frontmatter.daysOfWeek)
if (moment(tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrAfter(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.startRecur, “YYYY-MM-DD”)))
if (tp.frontmatter.daysOfWeek.includes(“M”))
if (moment(tp.date.weekday(“YYYY-MM-DD”, 106, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrBefore(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.endRecur, “YYYY-MM-DD”))) { %>

[[<% tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 8, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 15, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 22, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 29, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 36, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 43, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 50, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 57, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 64, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 71, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 78, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 85, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 92, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 99, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 106, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]

<%* }
else if (tp.frontmatter.daysOfWeek)
if (moment(tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrAfter(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.startRecur, “YYYY-MM-DD”)))
if (tp.frontmatter.daysOfWeek.includes(“M”))
if (moment(tp.date.weekday(“YYYY-MM-DD”, 99, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrBefore(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.endRecur, “YYYY-MM-DD”))) { %>

[[<% tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 8, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 15, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 22, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 29, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 36, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 43, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 50, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 57, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 64, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 71, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 78, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 85, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 92, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 99, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]


SKIPPING TO END (The below portion capture the week after and week of StartRecur) (The omitted portion repeats the patttern)

<%* }
else if (tp.frontmatter.daysOfWeek)
if (moment(tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrAfter(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.startRecur, “YYYY-MM-DD”)))
if (tp.frontmatter.daysOfWeek.includes(“M”))
if (moment(tp.date.weekday(“YYYY-MM-DD”, 8, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrBefore(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.endRecur, “YYYY-MM-DD”))) { %>

[[<% tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]
[[<% tp.date.weekday(“YYYY-MM-DD”, 8, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]

<%* }
else if (tp.frontmatter.daysOfWeek)
if (moment(tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrAfter(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.startRecur, “YYYY-MM-DD”)))
if (tp.frontmatter.daysOfWeek.includes(“M”))
if (moment(tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”)).isSameOrBefore(tp.date.now(“YYYY-MM-DD”, 0, tp.frontmatter.endRecur, “YYYY-MM-DD”))) { %>

[[<% tp.date.weekday(“YYYY-MM-DD”, 1, tp.frontmatter.startRecur, “YYYY-MM-DD”) %>]]

<%* } else { %>
“Blank”
<%* } %>


Final Thoughts

As far as I can tell, this works! I’ve tried different test files using this code for Monday and Tuesday. But even one day of this is wayyyy too much, and I’d like to be able to do it for all 7 days. Any help would be greatly appreciated. Thank you!!

The easy answer is “yes, this can be done easier”. The slightly worse part is explaining how… :smiley:

First step I think would be to switch the weekdays your event occurs on into which day number of the week it is. Second step would be to use the date functions of Templater to find the start of the week for your startRecur, let say that is stored in currDate.

Now you need to enter a while loop until currDate is larger than the endRecur, and in this loop you’ll need to repeat each of these steps:

  • for each of the day offset (from the first step) add that to the currDate and check that this tmpDate is after startRecur, and before endRecur, and if so add to the result list of dates
  • now add 7 days to currDate, and repeat…

Thank you for the response! I’ve got a couple follow up questions if you don’t mind answering!

Okay, my understanding of the process you laid out is the below steps. I am not certain that I am understanding step 2 fully. I also don’t understand how I would do the while loop for all the days an event recurs. The steps below use a hypo event that recurs on M, W, and Fs, but I only semi-understand how to do the loop for 1 of the days, but don’t know how to do it for all of them at the same time.

  1. Take the frontmatter daysOfWeek list on a given page and convert them into the numbers used in templater codes (1=M, 2=T, 3=W, etc)

  2. Use date function to find the Sunday (day 0 in my system) that is in the week of startRecur, and then store it in the (variable? Constant? I don’t know the terminology) “currDate”

  3. Create a while loop that runs until currDate is after endRecur date. (M, W, F Hypo)

    a. Take the currDate (Sunday of the startRecur week) and add the offset number for Monday
    (1).

    b. Check if the new tmpDate (currDate + 1, for the moment) is between start and endRecur.

    c. If yes, add to output list. If no, don’t add to output list.

    d. Take currDate and add 7.

    e. Repeat steps b-d.

Thanks again for the help! Also, if this is too much to explain, would you be able to point me to a resource where I can learn how to do it?

You’re summation is mostly correctly, but I would introduce the loop on the daysOfWeek list into the while loop, so that it becomes:

  1. Convert daysOfWeek to the list of numbers

  2. Use tp.date functions to find start of week for startRecurcurrDate

  3. While loop as long as we’re not after endRecur date

    3.1. for loop on the new daysOfWeek list as thisOffset

    • tmpDate = currDate + thisOffset
    • Check that tmpDate is in period
    • If so, add to outputlist

    3.2. Add 7 to currDate, (and repeat the while loop)

If you do a search for learn javascript free you’ll get plenty of resources. Not sure which are the better ones, but I do believe I’ve heard some good stuff on both freecodecamp and codeacademy. And w3schools also have plenty of resources available.