Query for notes containing tags with a date of in the next x days

Things I have tried

dv.taskList(dv.pages().file.tasks.where(t => t.text.includes("#knx")).where(t => !t.completed));

What I’m trying to do

I want to query for all uncompleted tasks containing a tag and a date (as tag), which is in the next x days. To e.g. get an overview over all upcoming tasks for the next 7 days containing a specific tag. Since I’m pretty new to Obsidian and completely new to dataviewjs I am honestly lost. Above is my working approach without the date filtering.

An example line that should be caught as of today would be

- [ ] Example task #knx #2022-12-01

One that should be ignored is

- [ ] Another example task #knx #2022-11-28

To achieve that I think you have two options:

  • or you know regex… to extract any “date” in the text or tag (“date”, because isn’t a recognized date value)
  • or you need to write the date as an inline field, not as tag. (to inline fields, check plugin documentation)

Thanks so far. Regex is no problem at all, I think

[\d]{4}-[\d]{2}-[\d]{2}

should do the job for me. The question for me would then be how to connect everything. So how to include the regex and compare the result as date object to the current date.

I’m not versed in JS (nor in regex), but taking your regex expression I think you can start by something similar to this

// regex expression
const regex = /[\d]{4}-[\d]{2}-[\d]{2}/g

// filter tasks
const tasks = dv.pages('#knx').file.tasks.where(t => t.text.includes("#knx")).where(t => dv.date(t.text.match(regex)[0]) > dv.date('today'))

dv.taskList(tasks)

For me dates in JS are a mistery… So, now it’s your time to find a way to delimit the next x days from today date :slight_smile:

EDIT:
This is a ‘stupid’ repetition, but maybe with dv.date(t.text.match(regex)[0]) > dv.date('today') && dv.date(t.text.match(regex)[0]) <= dv.date('today').plus({days: 7})

1 Like

Thanks a lot so far. The date stuff should be fine, however I’m a bit stuck with the regex match command. Obviously t.text.match(regex)[0] should match the first group, but it seems that sometimes no group is returned (probably when nothing is found in a task), causing the evaluation to fail

Evaluation Error: TypeError: Cannot read properties of null (reading '0')
    at eval (eval at <anonymous> (plugin:dataview), <anonymous>:4:117)
    at Array.filter (<anonymous>)
    at Proxy.where (plugin:dataview:9414:39)
    at eval (eval at <anonymous> (plugin:dataview), <anonymous>:4:79)
    at DataviewInlineApi.eval (plugin:dataview:19673:16)
    at evalInContext (plugin:dataview:19674:7)
    at asyncEvalInContext (plugin:dataview:19684:32)
    at DataviewJSRenderer.render (plugin:dataview:19705:19)
    at DataviewJSRenderer.onload (plugin:dataview:19289:14)
    at DataviewJSRenderer.e.load (app://obsidian.md/app.js:1:852364)

So I tried getting rid of this case, but that approach always returns an empty result list:

// regex expression
const regex = /[\d]{4}\-[\d]{2}\-[\d]{2}/g

function safe_match(t) {
	m = t.text.match(regex)
	if (match != null) {
		return match[0]
	}
}

// filter tasks
const tasks = dv.pages('#knx').file.tasks.where(t => t.text.includes("#knx")).where(t => dv.date(safe_match(t)) > dv.date('today'))
dv.taskList(tasks)

btw what is the best way to debug print variables within dataviewjs? I just learned the hard way that document.write is a pretty bad idea and that window.alert is not much better.

using console?

console.log(tasks)

(the other things you wrote are unknown to me - I’m not a coder, programmer or similar :slight_smile: )

About your previous post with the code, well I really don’t know how function works but I guess - just a guess, because the syntax - if you use m = t.text.match(regex), then you need to use something like:

function safe_match(t) {
	m = t.text.match(regex)
	if (m != null) {
		return m[0]
	}
}

(or maybe not, I don’t know…)

1 Like

Stupid me, mixing up the variable names, the following works:

// regex expression
const regex = /[\d]{4}\-[\d]{2}\-[\d]{2}/g

function safe_match(t) {
	m = t.text.match(regex)
	if (m != null) {
		return m[0]
	}
	return null
}

// filter tasks
const tasks = dv.pages().file.tasks.where(t => t.text.includes("#knx")).where(t => dv.date(safe_match(t)) >= dv.date('today'))
dv.taskList(tasks)

Thanks a lot! I just saw your reply after posting mine. Yes, of course.

if you want a list of tasks without the default group by files, use dv.taskList(tasks, false)

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