Skip to content

Instantly share code, notes, and snippets.

@erichschroeter
Last active March 5, 2025 03:10
Show Gist options
  • Save erichschroeter/81252c89af1aa8914d5c3ccccef5324e to your computer and use it in GitHub Desktop.
Save erichschroeter/81252c89af1aa8914d5c3ccccef5324e to your computer and use it in GitHub Desktop.
Obsidian script and usage using Dataview community plugin to list all tasks between a date range. Thanks to https://www.youtube.com/watch?v=8MyHCQsyN1k
function aggregateTimes(...timeStrings) {
const timeUnits = { h: 3600, m: 60, s: 1 };
let totalSeconds = 0;
for (const timeString of timeStrings) {
if (typeof timeString === 'string' || timeString instanceof String) {
const matches = timeString.match(/(\d+)([hms])/g);
if (matches) {
for (const match of matches) {
const [, value, unit] = match.match(/(\d+)([hms])/);
totalSeconds += parseInt(value, 10) * timeUnits[unit];
}
}
}
}
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
let result = "";
if (hours) result += `${hours}h `;
if (minutes) result += `${minutes}m `;
if (seconds && !hours) result += `${seconds}s`;
return result.trim() || "0s";
}
function summary(...args) {
// Define your date range (inclusive)
var startDateRange = new Date("1900-01-01"); // Adjust the start date
var endDateRange = new Date("9999-01-31"); // Adjust the end date
if ("startDate" in args[0]) {
startDateRange = new Date(args[0]["startDate"]);
}
if ("endDate" in args[0]) {
endDateRange = new Date(args[0]["endDate"]);
}
// Define tags to filter (set to an empty array to retrieve all tags)
const userSpecifiedTags = ["#work"]; // Set tags here (e.g., ["#work", "#hiring-meetings"]), or leave empty for all tags
// console.log("Filtering tags " + userSpecifiedTags + " between " + startDateRange.toISOString().split("T")[0] + " to " + endDateRange.toISOString().split("T")[0]);
// Collect tasks with valid metadata within the date range
const tasks = [];
for (const page of dv.pages('"Journals"')) {
if (page.file.tasks) {
for (const task of page.file.tasks) {
// e.g. - [.] watched a youtube tutorial #work [timeTracked:: 7m 36s]
const timeTrackedMatch = task.text.match(/\[timeTracked::\s*((\d+)([hms])\s*)*\]/);
const tagMatches = task.text.match(/#[\w-]+/gi); // Match multiple hashtags, case-insensitive
if (timeTrackedMatch && tagMatches) {
try {
// Get the note's creation date using `file.ctime`
const noteDate = new Date(page.file.ctime);
// Check if the note's creation date falls within the specified range
if (noteDate >= startDateRange && noteDate <= endDateRange) {
// Add a record for each hashtag that matches the filter
for (const tag of tagMatches) {
if (userSpecifiedTags.length === 0 || userSpecifiedTags.includes(tag)) {
var timeTracked = timeTrackedMatch[0];
tasks.push({ tag, timeTracked });
}
}
}
} catch (e) {
dv.span(`Error parsing dates for task: ${task.text}\n`);
}
}
}
}
}
// Group by tag and sum durations
const grouped = tasks.reduce((acc, task) => {
acc[task.tag] = aggregateTimes((acc[task.tag] || 0), task.timeTracked);
return acc;
}, {});
// Render results
if (Object.keys(grouped).length > 0) {
dv.table(["Activity", "Total Time"],
Object.entries(grouped).map(([tag, totalTime]) => [tag, totalTime]));
} else {
dv.span(`No valid tasks with durations to display for the date range ${startDateRange.toISOString().split("T")[0]} to ${endDateRange.toISOString().split("T")[0]}.\n`);
}
}
summary(input)
function fromToday(offset) {
const date = new Date();
const dateRegex = /(-?\d+)([d])/;
if (offset && dateRegex.test(offset)) {
const [, value, unit] = offset.match(dateRegex);
if (unit === "d") {
date.setDate(date.getDate() + parseInt(value, 10));
}
}
// Convert to CST (Central Standard Time)
const options = { timeZone: "America/Chicago", year: "numeric", month: "2-digit", day: "2-digit" };
const cstDate = new Intl.DateTimeFormat("en-CA", options).format(date);
return cstDate.replace(/\//g, "-");
}
//await dv.view("scripts/aggregateTasks", {"startDate": "2025-03-04", "endDate": "2025-03-05"});
await dv.view("scripts/aggregateTasks", {"startDate": fromToday("-7d"), "endDate": fromToday("1d")});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment