Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/releases/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ Example:
```

-->

## Fixed

- (#1124) Fixed `tasks-default.base` views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons
- `today()` returns midnight, so `date(due) == today()` and `date(due) <= today() + "7d"` evaluated to false for any value with a non-zero time
- Affected views: Today, This Week
- Affected formulas: `isDueThisWeek`, `isThisWeek`, `dueDateCategory`, `nextDateCategory`, `dueDateDisplay`
- Added `.date()` to strip the time component before comparing, matching the pattern already used in `isDueToday` and `isScheduledToday`
- Thanks to @kmaustral for reporting
28 changes: 14 additions & 14 deletions docs/views/default-base-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The formula set is broad so views can reuse shared computed properties without c
|---------|-------------|------------|
| `isOverdue` | True if task has a past due date and is not completed | `due && date(due) < today() && status != "done"` |
| `isDueToday` | True if task is due today | `due && date(due).date() == today()` |
| `isDueThisWeek` | True if task is due within the next 7 days | `due && date(due) >= today() && date(due) <= today() + "7d"` |
| `isDueThisWeek` | True if task is due within the next 7 days | `due && date(due).date() >= today() && date(due).date() <= today() + "7d"` |
| `isScheduledToday` | True if task is scheduled for today | `scheduled && date(scheduled).date() == today()` |
| `isRecurring` | True if task has a recurrence rule | `recurrence && !recurrence.isEmpty()` |
| `hasTimeEstimate` | True if task has a time estimate > 0 | `timeEstimate && timeEstimate > 0` |
Expand All @@ -65,7 +65,7 @@ These formulas return string values useful for grouping tasks in views:
| `dueWeek` | Due date as year-week | "2025-W01", "No due date" | `if(due, date(due).format("YYYY-[W]WW"), "No due date")` |
| `scheduledMonth` | Scheduled date as year-month | "2025-01", "Not scheduled" | `if(scheduled, date(scheduled).format("YYYY-MM"), "Not scheduled")` |
| `scheduledWeek` | Scheduled date as year-week | "2025-W01", "Not scheduled" | `if(scheduled, date(scheduled).format("YYYY-[W]WW"), "Not scheduled")` |
| `dueDateCategory` | Human-readable due date bucket | "Overdue", "Today", "Tomorrow", "This week", "Later", "No due date" | `if(!due, "No due date", if(date(due) < today(), "Overdue", if(date(due).date() == today(), "Today", if(date(due).date() == today() + "1d", "Tomorrow", if(date(due) <= today() + "7d", "This week", "Later")))))` |
| `dueDateCategory` | Human-readable due date bucket | "Overdue", "Today", "Tomorrow", "This week", "Later", "No due date" | `if(!due, "No due date", if(date(due) < today(), "Overdue", if(date(due).date() == today(), "Today", if(date(due).date() == today() + "1d", "Tomorrow", if(date(due).date() <= today() + "7d", "This week", "Later")))))` |
| `timeEstimateCategory` | Task size by time estimate | "No estimate", "Quick (<30m)", "Medium (30m-2h)", "Long (>2h)" | `if(!timeEstimate \|\| timeEstimate == 0 \|\| timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))` |
| `ageCategory` | Task age bucket | "Today", "This week", "This month", "Older" | `if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))` |
| `createdMonth` | Creation date as year-month | "2025-01" | `file.ctime.format("YYYY-MM")` |
Expand All @@ -85,8 +85,8 @@ These formulas work with either due date or scheduled date, useful for finding t
| `daysUntilNext` | Days until next date (due or scheduled, whichever is sooner) | -2, 0, 5, null | `if(due && scheduled, min(formula.daysUntilDue, formula.daysUntilScheduled), if(due, formula.daysUntilDue, formula.daysUntilScheduled))` |
| `hasDate` | True if task has either a due or scheduled date | true, false | `due \|\| scheduled` |
| `isToday` | True if due OR scheduled today | true, false | `(due && date(due).date() == today()) \|\| (scheduled && date(scheduled).date() == today())` |
| `isThisWeek` | True if due OR scheduled within 7 days | true, false | `(due && date(due) >= today() && date(due) <= today() + "7d") \|\| (scheduled && date(scheduled) >= today() && date(scheduled) <= today() + "7d")` |
| `nextDateCategory` | Human-readable bucket for next date | "Overdue/Past", "Today", "Tomorrow", "This week", "Later", "No date" | `if(!due && !scheduled, "No date", if((due && date(due) < today()) \|\| (scheduled && date(scheduled) < today()), "Overdue/Past", if((due && date(due).date() == today()) \|\| (scheduled && date(scheduled).date() == today()), "Today", if((due && date(due).date() == today() + "1d") \|\| (scheduled && date(scheduled).date() == today() + "1d"), "Tomorrow", if((due && date(due) <= today() + "7d") \|\| (scheduled && date(scheduled) <= today() + "7d"), "This week", "Later")))))` |
| `isThisWeek` | True if due OR scheduled within 7 days | true, false | `(due && date(due).date() >= today() && date(due).date() <= today() + "7d") \|\| (scheduled && date(scheduled).date() >= today() && date(scheduled).date() <= today() + "7d")` |
| `nextDateCategory` | Human-readable bucket for next date | "Overdue/Past", "Today", "Tomorrow", "This week", "Later", "No date" | `if(!due && !scheduled, "No date", if((due && date(due) < today()) \|\| (scheduled && date(scheduled) < today()), "Overdue/Past", if((due && date(due).date() == today()) \|\| (scheduled && date(scheduled).date() == today()), "Today", if((due && date(due).date() == today() + "1d") \|\| (scheduled && date(scheduled).date() == today() + "1d"), "Tomorrow", if((due && date(due).date() <= today() + "7d") \|\| (scheduled && date(scheduled).date() <= today() + "7d"), "This week", "Later")))))` |
| `nextDateMonth` | Next date as year-month | "2025-01", "No date" | `if(due && scheduled, if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if(due, date(due).format("YYYY-MM"), if(scheduled, date(scheduled).format("YYYY-MM"), "No date")))` |
| `nextDateWeek` | Next date as year-week | "2025-W01", "No date" | `if(due && scheduled, if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if(due, date(due).format("YYYY-[W]WW"), if(scheduled, date(scheduled).format("YYYY-[W]WW"), "No date")))` |

Expand All @@ -102,7 +102,7 @@ These formulas work with either due date or scheduled date, useful for finding t
| Formula | Description | Example values | Expression |
|---------|-------------|----------------|------------|
| `timeTrackedFormatted` | Total time tracked as readable text | "2h 30m", "45m", "0m" | `if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")` |
| `dueDateDisplay` | Due date as relative text | "Today", "Tomorrow", "Yesterday", "3d ago", "Mon", "Dec 15" | `if(!due, "", if(date(due).date() == today(), "Today", if(date(due).date() == today() + "1d", "Tomorrow", if(date(due).date() == today() - "1d", "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due) <= today() + "7d", date(due).format("ddd"), date(due).format("MMM D")))))))` |
| `dueDateDisplay` | Due date as relative text | "Today", "Tomorrow", "Yesterday", "3d ago", "Mon", "Dec 15" | `if(!due, "", if(date(due).date() == today(), "Today", if(date(due).date() == today() + "1d", "Tomorrow", if(date(due).date() == today() - "1d", "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).date() <= today() + "7d", date(due).format("ddd"), date(due).format("MMM D")))))))` |

## Mini Calendar

Expand All @@ -129,7 +129,7 @@ formulas:
# Booleans
isOverdue: 'due && date(due) < today() && status != "done"'
isDueToday: 'due && date(due).date() == today()'
isDueThisWeek: 'due && date(due) >= today() && date(due) <= today() + "7d"'
isDueThisWeek: 'due && date(due).date() >= today() && date(due).date() <= today() + "7d"'
isScheduledToday: 'scheduled && date(scheduled).date() == today()'
isRecurring: 'recurrence && !recurrence.isEmpty()'
hasTimeEstimate: 'timeEstimate && timeEstimate > 0'
Expand All @@ -144,7 +144,7 @@ formulas:
dueWeek: 'if(due, date(due).format("YYYY-[W]WW"), "No due date")'
scheduledMonth: 'if(scheduled, date(scheduled).format("YYYY-MM"), "Not scheduled")'
scheduledWeek: 'if(scheduled, date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'
dueDateCategory: 'if(!due, "No due date", if(date(due) < today(), "Overdue", if(date(due).date() == today(), "Today", if(date(due).date() == today() + "1d", "Tomorrow", if(date(due) <= today() + "7d", "This week", "Later")))))'
dueDateCategory: 'if(!due, "No due date", if(date(due) < today(), "Overdue", if(date(due).date() == today(), "Today", if(date(due).date() == today() + "1d", "Tomorrow", if(date(due).date() <= today() + "7d", "This week", "Later")))))'
dueDateDisplay: '...' # Shows "Today", "Tomorrow", "3d ago", "Mon", "Dec 15"
timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'
ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'
Expand All @@ -159,7 +159,7 @@ formulas:
daysUntilNext: 'if(due && scheduled, min(formula.daysUntilDue, formula.daysUntilScheduled), if(due, formula.daysUntilDue, formula.daysUntilScheduled))'
hasDate: 'due || scheduled'
isToday: '(due && date(due).date() == today()) || (scheduled && date(scheduled).date() == today())'
isThisWeek: '(due && date(due) >= today() && date(due) <= today() + "7d") || (scheduled && date(scheduled) >= today() && date(scheduled) <= today() + "7d")'
isThisWeek: '(due && date(due).date() >= today() && date(due).date() <= today() + "7d") || (scheduled && date(scheduled).date() >= today() && date(scheduled).date() <= today() + "7d")'
nextDateCategory: '...' # "Overdue/Past", "Today", "Tomorrow", "This week", "Later", "No date"
nextDateMonth: '...' # YYYY-MM format for next date
nextDateWeek: '...' # YYYY-[W]WW format for next date
Expand Down Expand Up @@ -350,8 +350,8 @@ views:
- "!complete_instances.contains(today().format(\"yyyy-MM-dd\"))"
# Due or scheduled today
- or:
- date(due) == today()
- date(scheduled) == today()
- date(due).date() == today()
- date(scheduled).date() == today()
order:
- status
- priority
Expand Down Expand Up @@ -421,11 +421,11 @@ views:
# Due or scheduled this week
- or:
- and:
- date(due) >= today()
- date(due) <= today() + "7 days"
- date(due).date() >= today()
- date(due).date() <= today() + "7 days"
- and:
- date(scheduled) >= today()
- date(scheduled) <= today() + "7 days"
- date(scheduled).date() >= today()
- date(scheduled).date() <= today() + "7 days"
order:
- status
- priority
Expand Down
22 changes: 11 additions & 11 deletions src/templates/defaultBasesFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ function generateAllFormulas(plugin: TaskNotesPlugin): Record<string, string> {
isDueToday: `${dueProperty} && date(${dueProperty}).date() == today()`,

// Boolean: is this task due within the next 7 days?
isDueThisWeek: `${dueProperty} && date(${dueProperty}) >= today() && date(${dueProperty}) <= today() + "7d"`,
isDueThisWeek: `${dueProperty} && date(${dueProperty}).date() >= today() && date(${dueProperty}).date() <= today() + "7d"`,

// Boolean: is this task scheduled for today?
isScheduledToday: `${scheduledProperty} && date(${scheduledProperty}).date() == today()`,
Expand Down Expand Up @@ -327,7 +327,7 @@ function generateAllFormulas(plugin: TaskNotesPlugin): Record<string, string> {
scheduledWeek: `if(${scheduledProperty}, date(${scheduledProperty}).format("YYYY-[W]WW"), "Not scheduled")`,

// Due date category for grouping: Overdue, Today, Tomorrow, This Week, Later, No Due Date
dueDateCategory: `if(!${dueProperty}, "No due date", if(date(${dueProperty}) < today(), "Overdue", if(date(${dueProperty}).date() == today(), "Today", if(date(${dueProperty}).date() == today() + "1d", "Tomorrow", if(date(${dueProperty}) <= today() + "7d", "This week", "Later")))))`,
dueDateCategory: `if(!${dueProperty}, "No due date", if(date(${dueProperty}) < today(), "Overdue", if(date(${dueProperty}).date() == today(), "Today", if(date(${dueProperty}).date() == today() + "1d", "Tomorrow", if(date(${dueProperty}).date() <= today() + "7d", "This week", "Later")))))`,

// Time estimate category for grouping
timeEstimateCategory: `if(!${timeEstimateProperty} || ${timeEstimateProperty} == 0 || ${timeEstimateProperty} == null, "No estimate", if(${timeEstimateProperty} < 30, "Quick (<30m)", if(${timeEstimateProperty} <= 120, "Medium (30m-2h)", "Long (>2h)")))`,
Expand Down Expand Up @@ -368,10 +368,10 @@ function generateAllFormulas(plugin: TaskNotesPlugin): Record<string, string> {
isToday: `(${dueProperty} && date(${dueProperty}).date() == today()) || (${scheduledProperty} && date(${scheduledProperty}).date() == today())`,

// Boolean: is due or scheduled this week
isThisWeek: `(${dueProperty} && date(${dueProperty}) >= today() && date(${dueProperty}) <= today() + "7d") || (${scheduledProperty} && date(${scheduledProperty}) >= today() && date(${scheduledProperty}) <= today() + "7d")`,
isThisWeek: `(${dueProperty} && date(${dueProperty}).date() >= today() && date(${dueProperty}).date() <= today() + "7d") || (${scheduledProperty} && date(${scheduledProperty}).date() >= today() && date(${scheduledProperty}).date() <= today() + "7d")`,

// Next date category for grouping (combines due and scheduled)
nextDateCategory: `if(!${dueProperty} && !${scheduledProperty}, "No date", if((${dueProperty} && date(${dueProperty}) < today()) || (${scheduledProperty} && date(${scheduledProperty}) < today()), "Overdue/Past", if((${dueProperty} && date(${dueProperty}).date() == today()) || (${scheduledProperty} && date(${scheduledProperty}).date() == today()), "Today", if((${dueProperty} && date(${dueProperty}).date() == today() + "1d") || (${scheduledProperty} && date(${scheduledProperty}).date() == today() + "1d"), "Tomorrow", if((${dueProperty} && date(${dueProperty}) <= today() + "7d") || (${scheduledProperty} && date(${scheduledProperty}) <= today() + "7d"), "This week", "Later")))))`,
nextDateCategory: `if(!${dueProperty} && !${scheduledProperty}, "No date", if((${dueProperty} && date(${dueProperty}) < today()) || (${scheduledProperty} && date(${scheduledProperty}) < today()), "Overdue/Past", if((${dueProperty} && date(${dueProperty}).date() == today()) || (${scheduledProperty} && date(${scheduledProperty}).date() == today()), "Today", if((${dueProperty} && date(${dueProperty}).date() == today() + "1d") || (${scheduledProperty} && date(${scheduledProperty}).date() == today() + "1d"), "Tomorrow", if((${dueProperty} && date(${dueProperty}).date() <= today() + "7d") || (${scheduledProperty} && date(${scheduledProperty}).date() <= today() + "7d"), "This week", "Later")))))`,

// Next date as month for grouping
nextDateMonth: `if(${dueProperty} && ${scheduledProperty}, if(date(${dueProperty}) < date(${scheduledProperty}), date(${dueProperty}).format("YYYY-MM"), date(${scheduledProperty}).format("YYYY-MM")), if(${dueProperty}, date(${dueProperty}).format("YYYY-MM"), if(${scheduledProperty}, date(${scheduledProperty}).format("YYYY-MM"), "No date")))`,
Expand All @@ -391,7 +391,7 @@ function generateAllFormulas(plugin: TaskNotesPlugin): Record<string, string> {
timeTrackedFormatted: `if(${timeEntriesProperty}, if(list(${timeEntriesProperty}).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(${timeEntriesProperty}).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(${timeEntriesProperty}).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(${timeEntriesProperty}).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")`,

// Due date as human-readable relative text
dueDateDisplay: `if(!${dueProperty}, "", if(date(${dueProperty}).date() == today(), "Today", if(date(${dueProperty}).date() == today() + "1d", "Tomorrow", if(date(${dueProperty}).date() == today() - "1d", "Yesterday", if(date(${dueProperty}) < today(), formula.daysUntilDue * -1 + "d ago", if(date(${dueProperty}) <= today() + "7d", date(${dueProperty}).format("ddd"), date(${dueProperty}).format("MMM D")))))))`,
dueDateDisplay: `if(!${dueProperty}, "", if(date(${dueProperty}).date() == today(), "Today", if(date(${dueProperty}).date() == today() + "1d", "Tomorrow", if(date(${dueProperty}).date() == today() - "1d", "Yesterday", if(date(${dueProperty}) < today(), formula.daysUntilDue * -1 + "d ago", if(date(${dueProperty}).date() <= today() + "7d", date(${dueProperty}).format("ddd"), date(${dueProperty}).format("MMM D")))))))`,
};
}

Expand Down Expand Up @@ -572,8 +572,8 @@ ${orderYaml}
- ${recurringIncompleteFilter}
# Due or scheduled today
- or:
- date(${dueProperty}) == today()
- date(${scheduledProperty}) == today()
- date(${dueProperty}).date() == today()
- date(${scheduledProperty}).date() == today()
order:
${orderYaml}
sort:
Expand Down Expand Up @@ -617,11 +617,11 @@ ${orderYaml}
# Due or scheduled this week
- or:
- and:
- date(${dueProperty}) >= today()
- date(${dueProperty}) <= today() + "7 days"
- date(${dueProperty}).date() >= today()
- date(${dueProperty}).date() <= today() + "7 days"
- and:
- date(${scheduledProperty}) >= today()
- date(${scheduledProperty}) <= today() + "7 days"
- date(${scheduledProperty}).date() >= today()
- date(${scheduledProperty}).date() <= today() + "7 days"
order:
${orderYaml}
sort:
Expand Down
Loading