Looking for best practice for "task and time" tracking with obsidian

What I’m trying to do

I am looking for your best practices on task tracking.

I am using daily notes to structure my day, with some boilerplate for the whole day followed by blocks where I currently write down the timeframe (10:00 -10:30 i.e.) and what I was working on, written as a comment. The comment includes a project tag.

I would like to have an overview on how much time I spent on each “project” over the course of the year.

As I understood it, most of the solutions out there use properties or tags, but I am not sure how to seperate between multiple entries in one notes-file. How are you handling that?

Things I have tried

Playing around with templater, dataview, tracker.

Dataview allows to calculate totals of found values. That would allow you to explicitly write down a “time spend” value. See Dataview sum of all prices in table - #2 by smiggles for how dataview is used to calculate a sum. A search on tag would retrieve all instances independent on whether they occur in the same or different files.

1 Like

Thanks for the answer. I thought about that, too.
But how would a query look like that finds multiple entries per file?

I have data in one file like:

Project: Something
Timespent: 0.5
Comment:
kasdjadklajsd

Project: Different
Timespent: 0.25
Comment:
qweqweqweqwe

Project: Something
Timespent: 1.25
Comment:
iuozuioizouzio

I only find a solution for dataview to aggregate all entries of timespent, and not distinguish by “project”.

But I think I am missing something…

I am not a dataview guru, but I think you would need to make separate entries for each project:

Project_Something:: Timespent 0.5
Project_Different:: Timespent: 025

I will await a Dataview Master to correct this as needed.

1 Like

You could try something like the following:


- [project:: Something] (timespent:: 0.5h)
	-  kasdjadklajsd

- [project:: Different] (timespent:: 25 min) 
	- qweqweqweqwe

- [project:: Something] (timespent:: 1h 15min) 
	- iuozuioizouzio

## Queried version

```dataview
TABLE WITHOUT ID item.project as Project,
  item.timespent.minutes as Timespent, 
  item.children.text as Comments
WHERE file = this.file
FLATTEN file.lists as item
WHERE !item.parent
```

Total workload: `= round(sum(filter(this.file.lists, (l) => l.timespent).timespent).hours, 2) `h

If this is kept in a note of its own it should display something like (with local names instead of Norwegian :stuck_out_tongue: ):

Here I’ve done the total calculation outside of the table in a separate inline query focusing on the current file.

Similar queries can also be built over multiple files.

There are a few main points I would like to make though:

  • To make dataview pick up the information as fields you need to use syntax like above with double colons
  • Fields are connected either to the page, or to a list/task context. To be able to keep the project and timespent together you need to have them in a list context. Otherwise they’re all collated into two (or more) separate lists of the project and timespent (and comment) .
  • If you note the timespent as duration, it’s a lot easier to sum them up later on, and you can use durationformat() or similar measures to make it look pretty

This forum also holds various ways to do the summation of a column within the table (or as a postprocessing of the table).

1 Like

Thank you, that pointed me into the right direction.

I have created some dataviewjs code to group the entries together, not sure if this was the easiest way, but it was for me.


let page = dv.current()
const projectRegex = /\[project:: (.+?)\]/;
const timeRegex = /\(timespent:: (.+?)\)/;
let extractedValues = {};

page.file.lists.values.forEach((item, index) => {

    const jsonString = item.text;
    const projectMatch = jsonString.match(projectRegex);
    const timeMatch = jsonString.match(timeRegex);
    let projectName = '';
    let projectTime = '';
    
    if ((projectMatch && projectMatch.length > 1) && (timeMatch && timeMatch.length > 1)) {
        projectName = projectMatch[1];
        projectTime = timeMatch[1];
        
        if (typeof extractedValues[projectName]  == "undefined") {
	        extractedValues[projectName] = {
		        comments: [],
		        time: projectTime,
		    };
        } else {
	          extractedValues[projectName].time = parseFloat(projectTime) + parseFloat(extractedValues[projectName].time);
        }
        
        item.children.forEach((comment, index) => {
	        extractedValues[projectName].comments.push(comment.text);
        });
    };
   
});

const projectsTableArray = [];
let i = 0;
for (let projectName in extractedValues) {
    if (extractedValues.hasOwnProperty(projectName)) {        
        let project = extractedValues[projectName];       
        let comments = "";
        for (let comment of project.comments) {
            comments += comment + "\r";
        }
        projectsTableArray[i] = [projectName, project.time, comments];
        i++;
    }
};

dv.table(["Projekt", "Zeit", "Kommentar"], projectsTableArray);

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