I created the date picker with the Templater plugin

Hello, everyone.
I wanted to have a way to easily insert different dates into my notes, so I created a simple date picker using the Templater plugin and want to share it. The template is in the end of the post. Here how it works.

When you insert the template you get the suggestion window asking you to pick from the few options:

If you choose “write date” you will get a prompt asking you to write date in “DD MMMM YYYY” format. It’s actually not necessary to write the full date, you can write only part of it. For example, if you write “14” you will get a 14’th of the current month and the current year.

If you choose “today” or “tomorrow”, you will get today’s or tomorrow’s date, it’s pretty straightforward.

If you choose “> weekday” you will get another suggestion window asking you to pick the day of the week. As a result you will get the closest date of this weekday in the future. For example, if today is wednesday, and you pick “monday” you will get the next week’s monday.

If you choose “> calendar” you will be suggested to pick the year, then the month, then the date. You can choose between this year and 9 next. In the date list you can also see weekdays, and the lines added to the sundays to help visually separate weeks.

The result date will be inserted in the “YYYY-MM-DD” format. I use it, because it works with the dataview metadata. But you can change if, just change the “resultFormat” value at the top of the template.

Some other options to pick can be easily added to the template, but these are ones I personally find useful for now. Keep in mind that I’m not a programmer, just know a little bit of js. Also sorry if my English is bad.

Here is the template:

<%*
let resultDate = ""
let myformat = "DD MMMM YYYY"
let resultFormat = "YYYY-MM-DD"

let dateString = await tp.system.suggester(["(write date)", "today", "tomorrow", "> weekday", "> calendar"], ["(write date)", "today", "tomorrow", "> weekday", "> calendar"])
if (dateString != null) {

if (dateString == "today") {
	resultDate = tp.date.now()

}  else if (dateString == "tomorrow") {
	resultDate = tp.date.tomorrow()

}  else if (dateString == "> weekday") {
	let weekday = await tp.system.suggester(["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], [1, 2, 3, 4, 5, 6, 0])
	if (weekday != null) {
		let offset = weekday - tp.date.now("d")
		if (offset <= 0) { offset =  offset + 7 }
		resultDate = tp.date.now("YYYY-MM-DD", offset)
	}

}  else if (dateString == "> calendar") {
	let thisYear = Number(tp.date.now("YYYY"))
	let yearList = []
	for (let  i= 0; i < 10; i++) {
	    yearList.push(thisYear + i)
	}
let year = await tp.system.suggester(yearList, yearList)

if (year != null) {

	let month = await tp.system.suggester(["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])

	if (month != null) {

		let daysInMonth = new Date(year, month, 0).getDate();
		let dateList = []
		for (let i = 1; i <= daysInMonth; i++) {
			dateList.push(i)
		}
		
		const getDateString = (year, month, date) => {
			const dateStringFix = (num) => {
			    if (num < 10) {
				      return "0" + num
				} else return "" + num
			}
		    return year + "-" + dateStringFix(month) + "-" + dateStringFix(date)
	    }
	    
		let dateListString = dateList.map(d => {
			let rawString =  getDateString(year, month, d)
			let weekdayString = tp.date.now("d", 0, rawString, "YYYY-MM-DD")
			let resultString = tp.date.now("DD MMMM — dd", 0, rawString, "YYYY-MM-DD")
			if (weekdayString == 0) {
				resultString = resultString + "   ________________________________________________________"
			}
			return resultString
		})
		let date = await tp.system.suggester(dateListString, dateList)
		
		if (date != null) {	
			resultDate = getDateString(year, month, date)
		}}} 

} else if (dateString == "(write date)") {
	dateString = await tp.system.prompt("Date format: " + myformat)
	resultDate = tp.date.now("YYYY-MM-DD", 0, dateString, myformat)
	if (resultDate == "Invalid date") {
		resultDate = ""
}}}

if (resultDate != "") {
resultDate = tp.date.now(resultFormat, 0, resultDate)
}

%><%* tR +=  resultDate%>
10 Likes

Thanks! I modified your code to obtain a slightly different behavior. This code inserts selected date after the cursor position and returns focus to the editor, so you can continue to type.

<%*
const dayOfWeek = moment().day();
const dateFormat = "YYYY-MM-DD";

const suggestions = new Map();
suggestions.set("manual", null);
suggestions.set("today", moment());
suggestions.set("tomorrow", moment().add(1, 'days'));
suggestions.set("next monday", moment().add(1, 'weeks').day(1));
suggestions.set(dayOfWeek >= 2 ? "next tuesday" : "tuesday",
                dayOfWeek >= 2 ? moment().add(1, 'weeks').day(2) : moment().day(2)
);
suggestions.set(dayOfWeek >= 3 ? "next wednesday" : "wednesday",
                dayOfWeek >= 3 ? moment().add(1, 'weeks').day(3) : moment().day(3)
);
suggestions.set(dayOfWeek >= 4 ? "next thursday" : "thursday",
                dayOfWeek >= 4 ? moment().add(1, 'weeks').day(4) : moment().day(4)
);
suggestions.set(dayOfWeek >= 5 ? "next friday" : "friday",
                dayOfWeek >= 5 ? moment().add(1, 'weeks').day(5) : moment().day(5)
);
suggestions.set(dayOfWeek >= 6 ? "next saturday" : "saturday",
                dayOfWeek >= 6 ? moment().add(1, 'weeks').day(6) : moment().day(6)
);
suggestions.set(dayOfWeek == 0 ? "next sunday" : "sunday",
                dayOfWeek >= 0 ? moment().add(1, 'weeks').day(0) : moment().day(0)
);

const selection = await tp.system.suggester(
    [...suggestions].map(([k, v]) => k !== "manual" ? k + " (" + v.format(dateFormat) + ")" : k),
    Array.from(suggestions.values())
);

let resultDate = null;

if (!selection) {
    inputDate = await tp.system.prompt("Type a date (DD MM? YY?):");
    resultDate = moment(inputDate, "DD MM YY");
    if (!resultDate.isValid()) {
        resultDate = moment();
    }
} else {
    resultDate = selection;
}

tp.file.cursor_append(resultDate.format(dateFormat));
app.workspace.activeLeaf.view.editor.focus();
%>

5 Likes

@reaty You are great, I was looking for the same thing. Thanks for sharing this.
I ended up using it as a function that returned me the date whenever called.
This code was simple as plug and play. Thanks again.

Hi, im trying to do something similar. I wanted to create a grafical representation of a calendar to pick a date from, but I am way to new/bad at coding.
I wanted to use your code and try to modify it, so it fits my purpous but im stuck. Everything works fine, except the output, when i choose the calendar option.

let resultDate = ""
let resultFormat = "YYYY-MM-DD"

async function datePicker2(tp) {
    const selectedOption = await tp.system.suggester(
        ['No Date given!', 'Select Date!'], 
        [1, 2], 
        false, 
        "What's the completion date?"
        );

    if (selectedOption === 1) {
        return 'No Date given!'.fontcolor("green");

    } else if (selectedOption === 2) {

        const dateString = await tp.system.suggester(
            ['Today', 'Tomorrow', 'Calendar'],
            [3, 4, 5],
            false,
            'aksldhfk'
            );

        if (dateString === 3){
            return '[[' + tp.date.now() + ']]';

        } else if (dateString === 4){
            return '[[' + tp.date.tomorrow() + ']]';

        } else if (dateString == 5){
            
            let thisYear = Number(tp.date.now("YYYY"))
            let yearList = []
            for (let  i= 0; i < 10; i++) {
                yearList.push(thisYear + i)
            }
        let year = await tp.system.suggester(yearList, yearList)
        
        if (year != null) { // wenn das Jahr gegeben ist, kann das Programm weiter
        
            let month = await tp.system.suggester(["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], false)
        
            if (month != null) { // wenn der Monat gegeben ist, kann das Programm weiter 
        
                let daysInMonth = new Date(year, month, 0).getDate();
                let dateList = []
                for (let i = 1; i <= daysInMonth; i++) {
                    dateList.push(i)
                } //Ich glaube, dass dieser Block die Tage angibt, also dass mit Date die Tage für die entsprechenden Monate abgerufen werden
                
                const getDateString = (year, month, date) => {
                    const dateStringFix = (num) => {
                        if (num < 10) {
                              return "0" + num
                        } else return "" + num
                    }
                    return year + "-" + dateStringFix(month) + "-" + dateStringFix(date) 
                }
                
                let dateListString = dateList.map(d => { // dieser ganze block hat mit der Darstellung der Tagesauswahl zu tun.
                    let rawString =  getDateString(year, month, d)
                    let weekdayString = tp.date.now("d", 0, rawString, "YYYY-MM-DD")
                    let resultString = tp.date.now("DD MMMM — dd", 0, rawString, "YYYY-MM-DD")
                    if (weekdayString == 0) {
                        resultString = resultString + "   ________________________________________________________"
                    }
                    return resultString 
                })
                let date = await tp.system.suggester(dateListString, dateList) // mit dem werden die tage als ein array angezeigt, mit hilfe von .map
                
                if (date != null) {	
                    resultDate = getDateString(year, month, date)
                }}} 
                
                if (resultDate != "") {
                    resultDate = tp.date.now(resultFormat, 0, resultDate)
                }

        } else {
            return 'Nothing was indicated!!!'.fontcolor('red')
        }


    } else {
        return 'Nothing was indicated!!!'.fontcolor("red")
    }

}

module.exports = datePicker2;


Could someone maybe help me?

Thanks for your code examples, @chokko @reaty !

I’ve done a slightly different iteration:

const suggestions = new Map()
suggestions.set(
  "Today, "+moment().format('ddd MMM, D'),
  moment()
)
suggestions.set(
  "Tomorrow, "+moment().add(1,'days').format('ddd MMM, D'),
  moment().add(1,'days')
)
suggestions.set(
  moment().add(2,'days').format('ddd MMM, D'),
  moment().add(2,'days')
)
suggestions.set(
  moment().add(3,'days').format('ddd MMM, D'),
  moment().add(3,'days')
)
suggestions.set(
  moment().add(4,'days').format('ddd MMM, D'),
  moment().add(4,'days')
)
suggestions.set(
  moment().add(5,'days').format('ddd MMM, D'),
  moment().add(5,'days')
)
suggestions.set(
  "Manual",
  null
)

const selection = await tp.system.suggester(
    [...suggestions].map(([k, v]) => k !== "Manual" ? k + " (" + v.format("YYYY-MM-DD") + ")" : k),
    Array.from(suggestions.values())
)

let fileDate = null
if (!selection) {
    inputDate = await tp.system.prompt("Type a date (DD MM? YY?):")
    fileDate = moment(inputDate, "DD MM YY")
    if (!fileDate.isValid()) {
      fileDate = moment()
    }
} else {
    fileDate = selection
}

Which offers a smaller fly-out selector and date selection options that might be easier for date-challenged individuals (like me) because it shows the name of the day in the future as well as the numeric date (redundantly, even).

3 Likes

Hi there, the thing I created is different, but it might be a nice alternative. I essentially just call a function from the natural language date plugin, but it works like a charm.

async function datePicker(tp) {
    const selectedOption = await tp.system.suggester(
        ['No Date given!', 'Select Date!'], 
        [1, 2], 
        false, 
        "What's the completion date?"
        );

    if (selectedOption === 1) {
        return 'No Date given!'.fontcolor("green");
    } else if (selectedOption === 2) {
        await app.commands.executeCommandById("nldates-obsidian:nlp-picker");
        return '';
    } else {
        return 'Nothing was indicated!!!'.fontcolor("red")
    }
}

module.exports = datePicker;

I have no knowlage when it comes to coding but I somehow managed to frankenstein it.

When selecting “Select Date!”

@reaty, @chokko, @JRyven— y’all are awesome. Been looking for a date picker, and I adapted variations of all your code to make this function.

The differences are mainly some reformatting to make things more readable (comments, indenting, etc), changing the manual date picker to be MM DD YY because I’m hopelessly American, and changing the presets to be today, tomorrow, and the past 7 days, since that’s my general use case.

This is my script file named datePicker.js in my Templater “scripts” folder:

// Code adapted from @chokko, @reaty, and @JRyven on Obsidian forum, by @solarboi
// https://forum.obsidian.md/t/i-created-the-date-picker-with-the-templater-plugin/55782

async function datePicker ( ) {
	// Calls Templater API for use in script
	const tp = app.plugins.plugins["templater-obsidian"].templater.current_functions_object
	
	// Set up constants for script
	const dayOfWeek = moment().day()
	const dateFormat = "YYYY-MM-DD"

	// Sets up a set of pre-made suggestions - today, tomorrow, and the previous 7 days
	const suggestions = new Map()
	suggestions.set(
		"Today, "+moment().format('ddd MMM, D'),
		moment()
	)
	suggestions.set(
		"Tomorrow, "+moment().add(1,'days').format('ddd MMM, D'),
		moment().add(1,'days')
	)
	suggestions.set(
		"Yesterday, "+moment().subtract(1, 'days').format('ddd MMM, D'),
		moment().subtract(1, 'days')
	)
	suggestions.set(
		moment().subtract(2,'days').format('ddd MMM, D'),
		moment().subtract(2,'days')
	)
	suggestions.set(
		moment().subtract(3,'days').format('ddd MMM, D'),
		moment().subtract(3,'days')
	)
	suggestions.set(
		moment().subtract(4,'days').format('ddd MMM, D'),
		moment().subtract(4,'days')
	)
	suggestions.set(
		moment().subtract(5,'days').format('ddd MMM, D'),
		moment().subtract(5,'days')
	)
	suggestions.set(
		moment().subtract(6,'days').format('ddd MMM, D'),
		moment().subtract(6,'days')
	)
	suggestions.set(
		moment().subtract(7,'days').format('ddd MMM, D'),
		moment().subtract(7,'days')
	)
	suggestions.set(
		"Manual",
		null
	)
	suggestions.set(
		"> Calendar",
		"full date picker"
	)

	// Prompts for selection
	const selection = await tp.system.suggester(
    	[...suggestions].map(([k, v]) => k !== "Manual" ? k + " (" + v.format(dateFormat) + ")" : k),
    	Array.from(suggestions.values())
	)

	// Resolves selection
	let resultDate = null
	if (!selection) {
		// Asks for manual input if user selected "Manual"
    	inputDate = await tp.system.prompt("Type a date (MM DD YY?):")
    	resultDate = moment(inputDate, "MM DD YY")
    	if (!resultDate.isValid()) {
    		resultDate = moment()
    	}
	} else if (selection == "full date picker") {
		// This is a full year/month/day picker
		
		// Year picker
		let thisYear = Number(tp.date.now("YYYY"))
		let yearList = []
		for (let  i= 0; i < 10; i++) {
	    	yearList.push(thisYear + i)
		}
		let year = await tp.system.suggester(yearList, yearList)
		
		// Month picker
		if (year != null) {
			let month = await tp.system.suggester(["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
			
			// Day picker
			if (month != null) {
				let daysInMonth = new Date(year, month, 0).getDate();
				let dateList = []
				for (let i = 1; i <= daysInMonth; i++) {
					dateList.push(i)
				}
				const getDateString = (year, month, date) => {
					const dateStringFix = (num) => {
				    	if (num < 10) {
					    	  return "0" + num
						} else return "" + num
					}
		    		return year + "-" + dateStringFix(month) + "-" + dateStringFix(date)
	    		}
	    		// Formats dates for picking
				let dateListString = dateList.map(d => {
					let rawString =  getDateString(year, month, d)
					let weekdayString = tp.date.now("d", 0, rawString, "YYYY-MM-DD")
					let resultString = tp.date.now("DD MMMM — dd", 0, rawString, "YYYY-MM-DD")
					if (weekdayString == 0) {
						resultString = resultString + "   ________________________________________________________"
					}
					return resultString
				})
				let date = await tp.system.suggester(dateListString, dateList)
		
				if (date != null) {	
					resultDate = getDateString(year, month, date)
				}
			}
		}
	} else {
    	// This returns whatever was specifically selected from the preset entries
    	resultDate = selection
	}

	return resultDate.format(dateFormat)
}
module.exports = datePicker

And a test Templater action for those who find it useful:

<%*
let date = await tp.user.datePicker()
tR += date
%>