Date Fields and Date Calculations¶
pytaskwarrior accepts date strings for task fields. Returned dates are parsed
into Python datetime objects on TaskOutputDTO.
Two backends, two date engines
The default TC adapter (
TaskWarrior()with notask_cmd) resolves date strings via a pure-Python engine. It supports ISO 8601, the most common named synonyms (today,eom,eow, day names…), ISO durations, and compact relative expressions (now+3d,eom-1w).The CLI adapter (
TaskWarrior(task_cmd="task")) delegates to thetaskbinary, which supports everything the TC adapter does plus month names (november), day ordinals (1st),later/someday, DOM-relative dates (due-7d), and many more extended synonyms. Expressions marked CLI-only in this page requiretask_cmd="task".
Date Fields¶
TaskInputDTO — input fields (strings)¶
| Field | Description |
|---|---|
due |
Latest date by which the task must be completed |
scheduled |
Earliest date the task can be started |
wait |
Task is hidden from pending list until this date |
until |
Task auto-deletes on this date (use with care) |
All four fields accept the same date formats listed below. They are str | None.
from taskwarrior import TaskWarrior, TaskInputDTO
tw = TaskWarrior()
task = TaskInputDTO(
description="Send birthday card to Alice",
due="2026-11-08",
scheduled="2026-11-04", # earliest I can work on it
wait="2026-11-01", # hidden until November 1st (ISO — works with both adapters)
until="2026-11-10", # auto-deletes if not done by then
)
tw.add_task(task)
TaskOutputDTO — returned fields (datetime objects)¶
| Field | Description |
|---|---|
due |
Due date as datetime \| None |
scheduled |
Scheduled date as datetime \| None |
wait |
Wait date as datetime \| None |
until |
Until date as datetime \| None |
entry |
Creation timestamp (read-only) |
start |
When the task was started (read-only) |
end |
When the task was completed or deleted (read-only) |
modified |
Last modification timestamp (read-only) |
task = tw.get_task(uuid)
if task.due:
days_left = (task.due - datetime.now()).days
print(f"Due in {days_left} days")
if task.scheduled and task.scheduled > datetime.now():
print("Task is not yet ready to start")
Accepted Date Formats¶
ISO-8601¶
The most explicit format. Recommended for programmatic use.
task = TaskInputDTO(description="Meeting", due="2026-06-15")
task = TaskInputDTO(description="Meeting", due="2026-06-15T09:30:00")
task = TaskInputDTO(description="Meeting", due="2026-06-15T09:30:00+02:00") # with timezone
Common ISO patterns:
| Pattern | Example | Meaning |
|---|---|---|
YYYY-MM-DD |
2026-06-15 |
Date, time 00:00:00 local |
YYYY-MM-DDThh:mm:ss |
2026-06-15T09:30:00 |
Date + time, local |
YYYY-MM-DDThh:mm:ssZ |
2026-06-15T09:30:00Z |
Date + time, UTC |
YYYY-MM-DDThh:mm:ss+hh:mm |
2026-06-15T09:30:00+02:00 |
Date + time, with offset |
YYYY-Www |
2026-W24 |
First day of ISO week |
YYYY-MM |
2026-06 |
First day of month |
Duration / Offset Expressions¶
TaskWarrior accepts ISO 8601 duration strings as relative offsets from now.
| Expression | Meaning |
|---|---|
P1D |
1 day from now |
P1W |
1 week from now |
P2W |
2 weeks from now |
P1M |
1 month from now |
P1Y |
1 year from now |
PT2H |
2 hours from now |
P1DT4H |
1 day and 4 hours from now |
task = TaskInputDTO(description="Follow-up", due="P2W") # due in 2 weeks
task = TaskInputDTO(description="Reminder", wait="P3D") # hidden for 3 days
Named Synonyms¶
Human-friendly date names.
Supported by the default TC adapter¶
Relative days:
| Synonym | Meaning |
|---|---|
now |
Current date and time |
today / sod |
Today at 00:00:00 |
eod |
Today at 23:59:59 |
yesterday |
Yesterday at 00:00:00 |
tomorrow |
Tomorrow at 00:00:00 |
Days of the week — resolves to the next occurrence of that day:
task = TaskInputDTO(description="Weekly review", due="friday")
task = TaskInputDTO(description="Stand-up", due="monday")
# Full names or abbreviated: "mon", "tue", "wed", "thu", "fri", "sat", "sun"
Boundaries (subset):
| Synonym | Meaning |
|---|---|
eow |
End of current week (Sun 23:59:59) |
eom |
End of current month (23:59:59) |
eoy |
End of current year (23:59:59) |
Relative expressions (arithmetic on the above):
# TC adapter resolves these correctly
task = TaskInputDTO(description="Deadline", due="eom-1w") # 1 week before end of month
task = TaskInputDTO(description="Follow-up", due="now+3d") # 3 days from now
task = TaskInputDTO(description="Reminder", due="today+2w") # 2 weeks from today
CLI-only synonyms (require task_cmd="task")¶
The expressions below are resolved by the task binary and return None
(silently ignored) when used with the default TC adapter. Use ISO 8601 dates
instead, or switch to TaskWarrior(task_cmd="task").
Month / quarter / year boundaries:
| Synonym | Meaning |
|---|---|
som / eom (already covered above) |
— |
sonm / eonm |
Start / end of next month |
sopm / eopm |
Start / end of previous month |
sow / eow (already covered above) |
— |
soww / eoww |
Start / end of current work week (Mon–Fri) |
sonw / eonw |
Start / end of next week |
sopw / eopw |
Start / end of previous week |
soq / eoq |
Start / end of current quarter |
sonq / eonq |
Start / end of next quarter |
soy / sony / eony |
Start / end of current or next year |
Month names — resolves to the 1st of the next month with that name (CLI-only):
# CLI-only — use ISO date with TC adapter
# WRONG with TC adapter: task = TaskInputDTO(description="...", wait="november")
# CORRECT with TC adapter:
task = TaskInputDTO(description="Holiday prep", wait="2026-11-01")
Day ordinals — next occurrence of that day-of-month (CLI-only):
# CLI-only — use ISO date with TC adapter
# WRONG with TC adapter: task = TaskInputDTO(description="Pay rent", due="1st")
# CORRECT with TC adapter:
task = TaskInputDTO(description="Pay rent", due="2026-07-01")
next <weekday> (CLI-only):
# CLI-only — use the weekday name directly for "next occurrence":
# WRONG with TC adapter: due="next monday"
# CORRECT with TC adapter: due="monday" (already means next occurrence)
task = TaskInputDTO(description="Review", due="monday")
Special:
| Synonym | Availability |
|---|---|
later / someday |
CLI-only — far future (9999-12-30) |
easter / goodfriday |
CLI-only |
Relative Expressions (DOM-based) — CLI-only¶
Defining dates relative to other date fields (e.g. due-7d for scheduled)
is evaluated by the task binary and is not supported by the TC adapter.
# CLI-only (requires task_cmd="task"):
task = TaskInputDTO(
description="Project deliverable",
due="2026-09-30",
scheduled="due-7d", # 1 week before due — CLI only
wait="due-14d", # 2 weeks before due — CLI only
until="due+3d", # 3 days after due — CLI only
)
# TC adapter equivalent — compute the dates in Python:
from datetime import date, timedelta
due = date(2026, 9, 30)
task = TaskInputDTO(
description="Project deliverable",
due=due.isoformat(),
scheduled=(due - timedelta(weeks=1)).isoformat(),
wait=(due - timedelta(weeks=2)).isoformat(),
until=(due + timedelta(days=3)).isoformat(),
)
tw.add_task(task)
Note: Even with the CLI adapter, if you later change due, the other dates are not recalculated automatically. Update them explicitly with tw.modify_task(...).
task_calc() — Evaluating Date Expressions¶
Use task_calc() to resolve a date expression to an ISO datetime string.
TC adapter — resolves via pure Python (subset of expressions):
tw = TaskWarrior()
print(tw.task_calc("eom")) # e.g. "2026-02-28T23:59:59"
print(tw.task_calc("friday")) # e.g. "2026-03-06T00:00:00"
print(tw.task_calc("now+2w")) # e.g. "2026-03-13T09:15:00"
print(tw.task_calc("P1M")) # e.g. "2026-03-28T09:15:00"
print(tw.task_calc("2026-06-15 + 30d")) # "2026-07-15T00:00:00"
Raises TaskWarriorError for unsupported expressions (month names, day ordinals, etc.).
CLI adapter — delegates to task calc, supports full range:
tw_cli = TaskWarrior(task_cmd="task")
print(tw_cli.task_calc("next monday")) # supported in CLI mode
print(tw_cli.task_calc("november")) # resolves to next Nov 1st
task_date_validator() — Validating Date Strings¶
Use task_date_validator() to check whether a string is a valid date expression.
tw.task_date_validator("2026-06-15") # True — valid ISO date
tw.task_date_validator("friday") # True — valid synonym
tw.task_date_validator("eom") # True — valid synonym
tw.task_date_validator("P2W") # True — valid ISO duration
tw.task_date_validator("now+3d") # True — valid relative
tw.task_date_validator("next monday") # False — CLI-only, not supported by TC adapter
tw.task_date_validator("november") # False — CLI-only
tw.task_date_validator("invalid-date") # False — not recognized
Typical use: validate user-supplied input before creating a task.
user_input = input("Due date: ")
if tw.task_date_validator(user_input):
task = TaskInputDTO(description="Task", due=user_input)
tw.add_task(task)
else:
print(f"'{user_input}' is not a valid date expression.")
Filtering Tasks by Date¶
Use filter tokens in get_tasks(). The TC adapter supports field.before:,
field.after:, field.by:, field.not: operators and virtual tags like
+OVERDUE, +DUETODAY, +DUE, +SCHEDULED.
# Tasks due today (use virtual tag — not due:today which is CLI-only)
tw.get_tasks("+DUETODAY")
# Tasks due this week
tw.get_tasks("due.before:eow")
# Tasks due in the next 7 days
tw.get_tasks("due.before:now+7d")
# Overdue tasks
tw.get_tasks("+OVERDUE")
# Tasks with any due date (Python post-filter — due.any: not supported by TC adapter)
all_tasks = tw.get_tasks()
tasks_with_due = [t for t in all_tasks if t.due is not None]
# Tasks with no due date (Python post-filter)
tasks_without_due = [t for t in all_tasks if t.due is None]
# Tasks due in a specific month
tw.get_tasks("due.after:2026-03-01 due.before:2026-04-01")
CLI adapter supports the full filter syntax including
due:today,due.any:,due.none:, andor/andboolean operators.
Semantic Summary of the Four Date Fields¶
Timeline ──────────────────────────────────────────────────────────►
[wait] ──► task becomes visible
[scheduled] ──► task becomes READY
... work on it ...
[due] ──► OVERDUE
[until] ──► auto-DELETE
| Field | Task is hidden? | Task is ready? | Urgency effect |
|---|---|---|---|
wait |
Yes, until date | — | None while waiting |
scheduled |
No | Only after date | Elevated when ready |
due |
No | — | Increases as deadline approaches |
until |
No | — | None (hard expiry) |