`<%*tR += "" %>``dataviewjs
const curr = dv.current();
const currentFile = app.vault.getAbstractFileByPath(curr.file.path);
const tasks = curr.file.tasks;
// regexes
const estimateRegex = /est::\s*(\d+)/i;
const clockRegex = /\[clock::(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})--(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\]/;
const timeRegex = /(\d{1,2}):(\d{2})-(\d{1,2}):(\d{2})/;
let totalEstimate = 0;
let actualMinutes = 0;
let allInMinutes = 0;
for (let task of tasks) {
// 1) parse estimate
let estMatch = task.text.match(estimateRegex);
let est = estMatch ? Number(estMatch[1]) : 0;
totalEstimate += est;
// 2) try clock entry first
let clkMatch = task.text.match(clockRegex);
if (clkMatch) {
let [ , startStr, endStr ] = clkMatch;
let start = Date.parse(startStr);
let end = Date.parse(endStr);
let diffM = Math.round((end - start) / 60000);
actualMinutes += diffM;
allInMinutes += diffM;
}
// 3) no clock, but completed: fall back to inline HH:MM–HH:MM
else if (task.completed) {
let tMatch = task.text.match(timeRegex);
if (tMatch) {
let [ , sh, sm, eh, em ] = tMatch.map(Number);
let startTotal = sh * 60 + sm;
let endTotal = eh * 60 + em;
if (endTotal < startTotal) endTotal += 24 * 60;
let diffM = endTotal - startTotal;
actualMinutes += diffM;
allInMinutes += diffM;
} else {
// no clock or time range: assume estimate for completed
allInMinutes += est;
}
}
// 4) neither clock nor completed: use estimate
else {
allInMinutes += est;
}
}
// 5) write back to frontmatter
await app.fileManager.processFrontMatter(currentFile, (fm) => {
fm["estimateDisplay"] = totalEstimate;
fm["actualDisplay"] = actualMinutes;
fm["allInDisplay"] = allInMinutes;
fm["remainingDisplay"]= allInMinutes - actualMinutes;
});
```
| Status | ``INPUT[inlineSelect(option(❌), option(🚧), option(🔄), option(✅)):status]`` | Priority | ``INPUT[inlineSelect(option(2), option(1), option(0)):priority]`` | Remaining | ``VIEW[{remainingDisplay}]`` |
| ------------ | ---------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------- | ------------ | ---------------------------- |
| Estimate min | ``VIEW[{estimateDisplay}]`` | Actual min | ``VIEW[{actualDisplay}]`` | _All-In min_ | ``VIEW[{allInDisplay}]`` |
## Tasks
- [ ] #task