Add "next Sunday" yyyy-MM-DD to your note with a {{next[Day]} date function

NextDate Inserter

This script adds functions that allow you to insert the yyyy-MM-DD date for the next [day].

e.g.

{{nextMonday}}
silverbullet.registerFunction({name: "nextSunday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextSunday = (0 - currentDayOfWeek + 7) % 7;
const nextSundayDate = new Date(new Date().getTime() + (daysUntilNextSunday * 24 * 60 * 60 * 1000));

return `${nextSundayDate.getFullYear()}-${(nextSundayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextSundayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextMonday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextMonday = (1 - currentDayOfWeek + 7) % 7;
const nextMondayDate = new Date(new Date().getTime() + (daysUntilNextMonday * 24 * 60 * 60 * 1000));

return `${nextMondayDate.getFullYear()}-${(nextMondayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextMondayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextTuesday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextTuesday = (2 - currentDayOfWeek + 7) % 7;
const nextTuesdayDate = new Date(new Date().getTime() + (daysUntilNextTuesday * 24 * 60 * 60 * 1000));

return `${nextTuesdayDate.getFullYear()}-${(nextTuesdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextTuesdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextWednesday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextWednesday = (3 - currentDayOfWeek + 7) % 7;
const nextWednesdayDate = new Date(new Date().getTime() + (daysUntilNextWednesday * 24 * 60 * 60 * 1000));

return `${nextWednesdayDate.getFullYear()}-${(nextWednesdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextWednesdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextThursday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextThursday = (4 - currentDayOfWeek + 7) % 7;
const nextThursdayDate = new Date(new Date().getTime() + (daysUntilNextThursday * 24 * 60 * 60 * 1000));

return `${nextThursdayDate.getFullYear()}-${(nextThursdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextThursdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextFriday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextFriday = (5 - currentDayOfWeek + 7) % 7;
const nextFridayDate = new Date(new Date().getTime() + (daysUntilNextFriday * 24 * 60 * 60 * 1000));

return `${nextFridayDate.getFullYear()}-${(nextFridayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextFridayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextSaturday"}, () => {
const currentDayOfWeek = new Date().getDay();
const daysUntilNextSaturday = (6 - currentDayOfWeek + 7) % 7;
const nextSaturdayDate = new Date(new Date().getTime() + (daysUntilNextSaturday * 24 * 60 * 60 * 1000));

return `${nextSaturdayDate.getFullYear()}-${(nextSaturdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextSaturdayDate.getDate().toString().padStart(2, '0')}`;
})
4 Likes

I’ve updated this script and created a mirror one for “this[day]” as well:

Next/This Date Function

  • {{this[day]}}: Returns the date of the specified day within the current week. It considers today if it matches the specified day, past dates for days earlier in the week, and upcoming dates for days later in the week.
  • {{next[day]}}: Finds the date of the next occurrence of the specified day, ensuring it’s at least a week away if today is the specified day.
  • Key Difference: {{this[day]}} focuses on navigating through the current week, while {{next[day]}} always looks forward to the next week, ensuring the specified day is never less than a week away when it matches the current day.

Use with {{this[day}} and {{next[day}}, e.g:

nextTuesday becomes: {{nextTuesday}}
thisTuesday becomes: {{thisTuesday}}

this[day] Date Inserter:

silverbullet.registerFunction({name: "thisSunday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisSunday = (7 - currentDayOfWeek) % 7;
  const thisSundayDate = new Date(today.getTime() + (daysUntilThisSunday * 24 * 60 * 60 * 1000));

  return `${thisSundayDate.getFullYear()}-${(thisSundayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisSundayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "thisMonday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisMonday = (1 - currentDayOfWeek + 7) % 7;
  const thisMondayDate = new Date(today.getTime() + (daysUntilThisMonday * 24 * 60 * 60 * 1000));

  return `${thisMondayDate.getFullYear()}-${(thisMondayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisMondayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "thisTuesday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisTuesday = (2 - currentDayOfWeek + 7) % 7;
  const thisTuesdayDate = new Date(today.getTime() + (daysUntilThisTuesday * 24 * 60 * 60 * 1000));

  return `${thisTuesdayDate.getFullYear()}-${(thisTuesdayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisTuesdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "thisWednesday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisWednesday = (3 - currentDayOfWeek + 7) % 7;
  const thisWednesdayDate = new Date(today.getTime() + (daysUntilThisWednesday * 24 * 60 * 60 * 1000));

  return `${thisWednesdayDate.getFullYear()}-${(thisWednesdayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisWednesdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "thisThursday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisThursday = (4 - currentDayOfWeek + 7) % 7;
  const thisThursdayDate = new Date(today.getTime() + (daysUntilThisThursday * 24 * 60 * 60 * 1000));

  return `${thisThursdayDate.getFullYear()}-${(thisThursdayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisThursdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "thisFriday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisFriday = (5 - currentDayOfWeek + 7) % 7;
  const thisFridayDate = new Date(today.getTime() + (daysUntilThisFriday * 24 * 60 * 60 * 1000));

  return `${thisFridayDate.getFullYear()}-${(thisFridayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisFridayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "thisSaturday"}, () => {
  const today = new Date();
  const currentDayOfWeek = today.getDay();
  const daysUntilThisSaturday = (6 - currentDayOfWeek + 7) % 7;
  const thisSaturdayDate = new Date(today.getTime() + (daysUntilThisSaturday * 24 * 60 * 60 * 1000));

  return `${thisSaturdayDate.getFullYear()}-${(thisSaturdayDate.getMonth() + 1).toString().padStart(2, '0')}-${thisSaturdayDate.getDate().toString().padStart(2, '0')}`;
})

Next[day] Date Inserter

silverbullet.registerFunction({name: "nextSunday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextSunday = (7 - currentDayOfWeek) % 7;
  const nextSundayDate = new Date(new Date().getTime() + ((daysUntilNextSunday || 7) * 24 * 60 * 60 * 1000));

  return `${nextSundayDate.getFullYear()}-${(nextSundayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextSundayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextMonday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextMonday = (8 - currentDayOfWeek) % 7;
  const nextMondayDate = new Date(new Date().getTime() + ((daysUntilNextMonday || 7) * 24 * 60 * 60 * 1000));

  return `${nextMondayDate.getFullYear()}-${(nextMondayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextMondayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextTuesday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextTuesday = (9 - currentDayOfWeek) % 7;
  const nextTuesdayDate = new Date(new Date().getTime() + ((daysUntilNextTuesday || 7) * 24 * 60 * 60 * 1000));

  return `${nextTuesdayDate.getFullYear()}-${(nextTuesdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextTuesdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextWednesday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextWednesday = (10 - currentDayOfWeek) % 7;
  const nextWednesdayDate = new Date(new Date().getTime() + ((daysUntilNextWednesday || 7) * 24 * 60 * 60 * 1000));

  return `${nextWednesdayDate.getFullYear()}-${(nextWednesdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextWednesdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextThursday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextThursday = (11 - currentDayOfWeek) % 7;
  const nextThursdayDate = new Date(new Date().getTime() + ((daysUntilNextThursday || 7) * 24 * 60 * 60 * 1000));

  return `${nextThursdayDate.getFullYear()}-${(nextThursdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextThursdayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextFriday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextFriday = (12 - currentDayOfWeek) % 7;
  const nextFridayDate = new Date(new Date().getTime() + ((daysUntilNextFriday || 7) * 24 * 60 * 60 * 1000));

  return `${nextFridayDate.getFullYear()}-${(nextFridayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextFridayDate.getDate().toString().padStart(2, '0')}`;
})

silverbullet.registerFunction({name: "nextSaturday"}, () => {
  const currentDayOfWeek = new Date().getDay();
  const daysUntilNextSaturday = (13 - currentDayOfWeek) % 7;
  const nextSaturdayDate = new Date(new Date().getTime() + ((daysUntilNextSaturday || 7) * 24 * 60 * 60 * 1000));

  return `${nextSaturdayDate.getFullYear()}-${(nextSaturdayDate.getMonth() + 1).toString().padStart(2, '0')}-${nextSaturdayDate.getDate().toString().padStart(2, '0')}`;
})

2 Likes

@zef Is it possible that SETTINGS isn’t allowing spacescript functions to be used with indexPage? I want to use a weekly journal entry that uses this {{thisSunday}} instead of {{startWeek}}, but I’m getting “undefined” in the note title when I try to use it.

(Not sure about your issue with the SETTINGS page, but I suspect it’s not able to be formatted in the way you’re looking for)

I took the liberty of refactoring your (awesome!) code here to be a bit more succinct. Please take a look and see what you think!

function computeDay(dayNumber, offset = 0) {
  let today = Temporal.Now.plainDateISO();
  const currentDayOfWeek = today.dayOfWeek;
  offset = (dayNumber == daysMapping["Sunday"]) ? (offset - 7) : offset;
  const daysUntil = ((dayNumber - currentDayOfWeek + 7) % 7) + offset;
  const target = today.add({days: daysUntil});

  return target.toString();
}

// mapping days to their respective day numbers 
const daysMapping = {
  "Sunday": 0, "Monday": 1, "Tuesday": 2,
  "Wednesday": 3, "Thursday": 4, "Friday": 5,
  "Saturday": 6,
};

for (const [day, dayNumber] of Object.entries(daysMapping)) {
  // Register a function for getting "last" day.
  silverbullet.registerFunction({name: `last${day}`}, () => computeDay(dayNumber, -7));
  
  // Register a function for getting "this" day.
  silverbullet.registerFunction({name: `this${day}`}, () => computeDay(dayNumber));
  
  // Register a function for getting "next" day.
  silverbullet.registerFunction({name: `next${day}`}, () => computeDay(dayNumber, 7));
}

And, to test:

```template
## Last week's days

- Sunday: `{{lastSunday}}`
- Monday: `{{lastMonday}}`
- Tuesday: `{{lastTuesday}}`
- Wednesday: `{{lastWednesday}}`
- Thursday: `{{lastThursday}}`
- Friday: `{{lastFriday}}`
- Saturday: `{{lastSaturday}}`

## This week's days

- Sunday: `{{thisSunday}}`
- Monday: `{{thisMonday}}`
- Tuesday: `{{thisTuesday}}`
- Wednesday: `{{thisWednesday}}`
- Thursday: `{{thisThursday}}`
- Friday: `{{thisFriday}}`
- Saturday: `{{thisSaturday}}`

## Next week's days

- Sunday: `{{nextSunday}}`
- Monday: `{{nextMonday}}`
- Tuesday: `{{nextTuesday}}`
- Wednesday: `{{nextWednesday}}`
- Thursday: `{{nextThursday}}`
- Friday: `{{nextFriday}}`
- Saturday: `{{nextSaturday}}`
2 Likes

Thank you very much for this incredible script.

For folks like me, that work with ISO standards, in case you want Monday to be the 1st day of the week, here is the modified version (with some AI help)

```space-script
function computeDay(dayNumber, offset = 0) {
  let today = Temporal.Now.plainDateISO();
  const currentDayOfWeek = (today.dayOfWeek - 1) % 7; // Adjust for ISO standard 
  offset = (dayNumber == 0) ? (offset - 7) : offset; // Sunday is now 0
  const daysUntil = ((dayNumber - currentDayOfWeek + 7) % 7) + offset;
  const target = today.add({ days: daysUntil });

  return target.toString();
}

// Mapping days to their respective ISO day numbers 
const daysMapping = {
  "Monday": 0, "Tuesday": 1, "Wednesday": 2,
  "Thursday": 3, "Friday": 4, "Saturday": 5,
  "Sunday": 6, 
};

for (const [day, dayNumber] of Object.entries(daysMapping)) {
  // Register functions (no change needed here)
  silverbullet.registerFunction({ name: `last${day}` }, () => computeDay(dayNumber, -7));  
  silverbullet.registerFunction({ name: `this${day}` }, () => computeDay(dayNumber));  
  silverbullet.registerFunction({ name: `next${day}` }, () => computeDay(dayNumber, 7));
}
```
1 Like

Yep! That is… better in every way! I wish I really knew what I was doing here, I appreciate the help streamlining this!

1 Like

I’m more than happy to help.

Over time you’ll get better, it just takes practice :slight_smile:

I think SB is a really awesome platform to learn in, too–there’s an excellent community here that are always willing to share

4 Likes

I wanted to also share a function I wrote today to query all the days in a given week, based on some of this code. I’ve made some small refactors, but nothing insane. Notably, the daysMapping is now (properly) set to ISO standards as @paletochen brought up.

The big thing here is that it accepts a “start” parameter which should be the first day (ideally) in the week you’re trying to track, but it shouldn’t actually matter for the use cases I have tested against.

```space-script
silverbullet.registerFunction({name: "queryPagesForWeek"}, async (start = Temporal.Now.plainDateISO()) => {
  let filter = [
    "and",
    ["=~", ["attr", "name"], ["regexp", "^Journal/Day", "i"]],
    [
      "call",
      "dayInThisWeek",
      [
        [
          "call",
          "replace",
          [
            ["attr", "name"],
            ["regexp", "^Journal/Day/([0-9]{4}-[0-9]{2}-[0-9]{2})(/?.*)?$", "i"],
            ["string", "$1"],
          ],
        ],
        ["string", start],
      ],
    ],
  ];
  // filter = ["call", "dayInThisWeek", [["string", "2024-03-04"]]];
  return await syscall(
  "system.invokeFunction", 
  "index.queryObjects", 
  "page", {
    orderBy: [{expr: ["string", "created"], desc: true}],
    filter: filter,
  })
});

silverbullet.registerFunction({name: "dayInThisWeek"}, async (date, forWeek, start = "Monday", debug = false) => {
  let parsedDate = Temporal.PlainDate.from(date);
  forWeek = (typeof forWeek == "string") ? Temporal.PlainDate.from(forWeek) : forWeek;
  
  const weekStart = Temporal.PlainDate.from(computeDay(daysMapping[start], 0, forWeek));
  const weekEnd = Temporal.PlainDate.from(computeDay(daysMapping[start], 7, forWeek));

  // change to >=1 to be non-inclusive of start day.
  const isOnOrAfterWeekStart = Temporal.PlainDate.compare(parsedDate, weekStart) >= 0;
  const isBeforeWeekEnd = Temporal.PlainDate.compare(parsedDate, weekEnd) == -1;

  const result = (isOnOrAfterWeekStart && isBeforeWeekEnd)
  // debugging
  if (debug) {
    const weekDay = Object.keys(daysMapping).find(key => daysMapping[key] === parsedDate.dayOfWeek);
    return `${weekDay} ${parsedDate} | ${weekStart} | ${weekEnd} | (${isOnOrAfterWeekStart} &&  ${isBeforeWeekEnd}) = ${result} `;
  }
  return result
});

function computeDay(dayNumber, offset = 0, today = Temporal.Now.plainDateISO()) {
  const currentDayOfWeek = today.dayOfWeek;
  offset = (dayNumber == daysMapping["Sunday"]) ? (offset - 7) : offset;
  const daysUntil = ((dayNumber - currentDayOfWeek + 7) % 7) + offset;
  const target = today.add({days: daysUntil});

  return target.toString();
}

// mapping days to their respective day numbers 
const daysMapping = {
  "Sunday": 7, "Monday": 1, "Tuesday": 2,
  "Wednesday": 3, "Thursday": 4, "Friday": 5,
  "Saturday": 6,
};

One can use this like:

```template
{{#let @pages = queryPagesForWeek("2024-03-04") }}
{{#each @p in @pages}}
### {{ @p.name }}
{{readPage(@p.name)}}
{{/each}}
{{/let}}
1 Like

Super newbie question, sorry for my ignorance:

Where do I even put a script like this?

You can actually put it ANYWHERE you want :slight_smile:

If you are interested how others do it… let me share with you what I do:

I try to have some order in my instance so, everything that has to do with scripts, templates, snippets, queries, etc… I have it under a folder called Library/Personal
You probably have already 1 or 2 subfolders under Library:

  • Library/Core
  • And maybe Library/Journal (if you installed this library)

The recommended way is to have one for your Personal stuff, in case in the future you want to share things, or maybe just back them up easily.

But again, any script, query, etc, can go anywhere in your instance.
You could have ALL scripts in the same page, instead of separated, or in groups, mixed with your other markdown files… literally anything.
All what matters is to fence properly the scripts with the code blocks

So, this is how it looks in mine:

image

The Scripts subfolders look like this:

And each one of those files is a separate Space-Script for me.
For example AddDays.md looks like this:

This helps me later find things more easily, but you can build your instance using your own style.

There are a lot of ideas here that you can pick from others.

Hope this helps :slight_smile:

Wow, this is very helpful, thanks! I will try out the {{next[Day]}} function.

I have an unrelated question. You mentioned that I might have installed Journal library. I don’t understand libraries. I installed the core library on my initial installation because the button was there to do so.

But now I have no idea how to update that library (I deleted the original index file, was that a mistake?), or how to install the journal library.

You probably don’t need to update the Core Library by hand, that will be updated with every update of silverbullet, if it needs to.

You can delete index.md and create yours, I believe we all do that and customized it to our needs.
Have a look at this post: What does your Index page look like?

As for Journal, nothing better than to point you to the official page which talks about it: Library/Journal
It helps creating a daily/weekly page

Btw now that we have Meta Pages I’d also recommend tagging all pages with space scripts with a #meta tag so they don’t clutter up in your page picker (they’d appear in the Meta Picker together with your templates).

While we are here, here’s a script that (almost) abuses the awesome SpaceScript functionality to let you input dates in natural language

const chrono = import("https://esm.sh/[email protected]");
silverbullet.registerCommand({name:"Insert Date"}, async () => {
  function pad(n) {
    let s = String(n);
    if (s.length === 1) {
      s = "0" + s;
    }
    return s;
  }

  function datestr(d) {
    return d.getFullYear() + "-" + (d.getMonth() + 1).toString().padStart(2, '0') + "-" + (d.getDate()).toString().padStart(2, '0');
  }

  async function dateparse(in_str) {
    const { Chrono } = await chrono
    const chrono_parser = new Chrono()
    const result = chrono_parser.parseDate(in_str);
    return datestr(result);
  }

  const input = await syscall("editor.prompt", "Insert a date in natural language", "")
  if (input) {
    const output = await dateparse(input);
    await syscall("editor.insertAtCursor", output);
  }
})
3 Likes

Thank you. On the Library/Journal page it has two buttons ‘Page: From Template’ and ‘Libraries: Update’. Where do I find these buttons, or how do I perform these commands, in my own setup?

In your own instance, click on the top right icon >_ that says Run a command
image

There you can find Page: From Template and Libraries:Update

By the way, if you haven’t done so, I would recommend going through https://silverbullet.md pages.
You learn a lot there.

If you are a more visual person, you also have 2 great videos from Zef:

1 Like