Regex in dataview js match timeslot

Things I have tried

Trying to match a time slot in the format “hh:mm - hh:mm” in dataview js using this regex “^([0-9]{2}:[0-9]{2}\s?)-(\s?[0-9]{2}:[0-9]{2})$”. The problem are the spaces around the hyphen that are not detected. Can anyone help?

What I’m trying to do

That does match zero or one space around the hyphen. Another version could be to use ^([0-9]{2}:[0-9]{2})\s*-\s*([0-9]{2}:[0-9]{2})$, which would allow for zero or more spaces around the hyphen, and not keep it in either capturing groups.

This last version I’ve uploaded into which is a great tool for debugging regex’s: regex101: build, test, and debug regex

An even better version would be to use something like: ^((?:[01][0-9]|2[0-3]):[0-5][0-9])\s*-\s*((?:[01][0-9]|2[0-3]):[0-5][0-9])$, to further limit it down to allowed digits in each position (not allowing 24:00).

Thanks @holroy!

Found out my regex was fine but my posterior processing of the capture groups was at fault.

My objective is creating something similar to dayplanner inside a note using dataviewjs. I retrieve my events using icalbuddy and the process them using dataviewjs into a simple table with the event blocks over the day.

I will try to share the code for it soon.

As promised here is the code that pick up on todos that have time slots associated and makes a basic graphical representation of a timeline.

It got it from Reddit and adapted to my use-case.
I’ve made a quick snippet in dataviewjs to show todo items from the current file in a timetable : ObsidianMD (
Props to @petruc

  1. I use icalbuddy with the following command:
    /opt/homebrew/bin/icalBuddy -npn -nc -iep “title,datetime” -ps “| : |” -po “datetime,title” -b "- [ ] " eventsToday

  2. I added this command to a Templater User Function

  3. I added the User Function to my daily note template

  4. I added the following dataviewjs snippet to the template:

let tasks = dv.current().file.tasks;
let tasksObjects = [];

let dummyDay = '2023-01-24 ';

let startTime = moment(dummyDay + (dv.current().dayStart ? dv.current().dayStart : "07:00"))
let endTime = moment(dummyDay + (dv.current().dayEnd ? dv.current().dayEnd : "23:00"));
const timeRegex = /^((?:[01][0-9]|2[0-3]):[0-5][0-9])\s*-\s*((?:[01][0-9]|2[0-3]):[0-5][0-9])$/;

tasks.forEach(function(item) {
	var time = item.text.substr(0, 13);
	var matches;
	if(matches = time.match(timeRegex)) {
		var itemTimeStart = matches[1];
		var itemTimeEnd = matches[3];
			'start': moment(dummyDay + itemTimeStart),
			'end': moment(dummyDay + itemTimeEnd),
			'text': item.text.substr(15).replace('#todo', ''),
			'task': item

let header = dv.el('tr', dv.el('th', 'Hour', {attr: {align: 'right'}}));
header.append(dv.el('th', 'Task'));

let tbody = dv.el('tbody', '');
var row;
var rowSlots = 1;
mainLoop: for(var currentTime = startTime; currentTime <= endTime; currentTime.add(30, 'minutes')) {
	var nextTime = moment(currentTime);
	nextTime.add(30, 'minutes');

	if(rowSlots > 1) {
		while(--rowSlots >= 1) {
			row = dv.el('tr', dv.el('td', currentTime.format("HH:mm"), {attr: {align: 'right'}}));
			continue mainLoop;

	var content = '';
	var	rowSlots = 1;
	var style = '';

	tasksObjects.forEach(function (task) {
		if(task.start.isBetween(currentTime, nextTime, undefined, '[)')) {
			rowSlots = Math.ceil(task.end.diff(task.start, 'minutes') / 30);
			content = task.text;
			style = 'background-color: rgba(8, 109, 221, 0.1)';
	var td = dv.el('td', '', {attr: {rowspan: rowSlots, style: style}});
	row = dv.el('tr', dv.el('td', currentTime.format("HH:mm"), {attr: {align: 'right'}}));

let table = dv.el('table', dv.el('thead', header), {attr: {style: 'width:100%'}});


dv.el('div', table, {cls: "el-table"});

  1. I get a nice graphical representation of my daily timeline inside the note itself:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.