Skip to content
shellmap

Parse a relative date like "next Friday" or "2 weeks ago"

Convert a human-readable relative-time expression ("3 days ago", "next Monday", "last quarter end") into an absolute date — for log filters, backfill ranges, scheduling, or any script that wants to accept user input the same way GitHub Actions cron does.

How to parse a relative date like "next friday" or "2 weeks ago" in each shell

Bashunix
date -d "next friday" +%Y-%m-%d

GNU `date -d STRING` has a rich relative-time parser: `next friday`, `last sunday`, `2 weeks ago`, `3 days`, `1 month -2 days`, `2026-05-17 + 3 hours`. Returns the absolute date with `+%Y-%m-%d` or any other format. The parser is in `gnulib`'s `parse-datetime.y` — same code Coreutils uses, also in `at` and `cron`. Linux-only out of the box.

Zshunix
date -d "next friday" +%Y-%m-%d
Fishunix
date -d "next friday" +%Y-%m-%d
PowerShellwindows
(Get-Date).AddDays(((5 - [int](Get-Date).DayOfWeek + 7) % 7 + 7) - (((5 - [int](Get-Date).DayOfWeek + 7) % 7) -eq 0 ? 0 : 7)) | Get-Date -Format "yyyy-MM-dd"

pwsh has NO built-in "next Friday" parser — date arithmetic is done by chaining `.AddDays(N)` / `.AddMonths(N)` / `.AddYears(N)`. For symmetric "go to next named day" use `[DayOfWeek]::Friday - (Get-Date).DayOfWeek` and add modulo 7 days. Simpler relative-times: `(Get-Date).AddDays(-14)` for "2 weeks ago", `(Get-Date).AddMonths(-1)` for "1 month ago". For complex NLP: `Install-Module -Name PsDateTime` community module or shell to `python3 -c "import dateparser; print(dateparser.parse('next friday').date())"`.

cmd.exewindows
powershell -NoProfile -Command "(Get-Date).AddDays(-14).ToString('yyyy-MM-dd')"

No native relative-date parser. Shelling to pwsh for `.AddDays(-N)` is the simple path. For NLP-style ("next friday"): `python3 -c "import dateparser; print(dateparser.parse('next friday').strftime('%Y-%m-%d'))"` if Python is installed (Windows 10+ via Microsoft Store).

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **GNU `date -d` parser quirks — "next friday" is NOT "this Friday"**. `date -d "Friday"` returns the upcoming Friday OR today (if today is Friday). `date -d "next friday"` ALWAYS returns the Friday AFTER the next one — so if today is Tuesday, "Friday" → this Friday, "next Friday" → Friday of next week. This catches everyone once. Same trap for "next month": `date -d "next month"` is the SAME calendar day next month, NOT "first of next month" (which would be `date -d "next month" -d "first day"` or `date -d "$(date +%Y-%m-15) + 1 month"` start-of-next-month idiom). Test in a REPL before shipping to cron — the parser is forgiving but unprintable.
  • **macOS / BSD `date` has a hop-style relative form, not natural-language**: `date -v -1d` (yesterday), `date -v -2w` (2 weeks ago), `date -v +1m` (1 month later), `date -v -7d -v fri` (last Friday). Units: `y`, `m`, `w`, `d`, `H`, `M`, `S`. Day names: `sun`/`mon`/`tue`/`wed`/`thu`/`fri`/`sat`. You can chain multiple `-v` flags. NO equivalent of `date -d "yesterday"` — must be `date -v -1d`. The portable workaround: `brew install coreutils` gives `gdate` which behaves like GNU `date`. Cross-platform scripts: detect with `if command -v gdate >/dev/null; then DATE=gdate; elif date --version >/dev/null 2>&1; then DATE=date; else echo "need GNU date"; exit 1; fi`.
  • **The Python `dateparser` package is the cross-platform NLP escape hatch** — `pip install dateparser` (~100 KB) gives natural-language parsing for 200+ languages: `dateparser.parse("hace 2 días")` Spanish, `dateparser.parse("来週金曜日")` Japanese, `dateparser.parse("two weeks before christmas")` English-relative-to-event. The standard-lib `datetime` cannot do this — `datetime.fromisoformat()` requires `YYYY-MM-DD`. For PRODUCTION pipelines that accept user input ("how far back?"): wrapping `dateparser` is the safest path. For internal scripts: GNU `date -d` is faster (no Python startup) and "good enough" for English natural-language.
  • **Daylight-saving transition surprise — `date -d "yesterday"` is NOT always 24 hours ago**. On the DST spring-forward day, `date -d "1 day ago"` and `date -d "24 hours ago"` differ by an HOUR. `1 day ago` walks the calendar by 1 day (handles DST correctly — yesterday-same-clock-time); `24 hours ago` subtracts 86400 seconds (wallclock-23-hours-earlier on spring-forward). For log queries this matters: `journalctl --since "1 day ago"` gives you yesterday's log; `journalctl --since "@$(($(date +%s) - 86400))"` gives you "exactly 86400 seconds ago", which may straddle DST. When in doubt: pin the timezone with `TZ=UTC date -d "1 day ago"` to get DST-free arithmetic.
  • **Anchor + offset is more legible than complex chains**: instead of `date -d "next month + 14 days - 1 hour"` (parsed left-to-right, results vary), break it: `ANCHOR=$(date -d "first day of next month" +%s); FUTURE=$(date -d "@$ANCHOR + 14 days - 1 hour" +%s); date -d "@$FUTURE"`. The intermediate seconds-since-epoch is platform-stable. pwsh equivalent: `(Get-Date -Day 1).AddMonths(1).AddDays(14).AddHours(-1)` — chained method calls in left-to-right order, far less ambiguous than a single GNU-date string. For ANYTHING shipping to cron or systemd timers (which interpret strings differently than `date -d` does): expand to absolute ISO 8601 first, NEVER pass relative-time strings to a scheduler — schedulers re-parse and round-trip semantics drift.

Related commands

Related tasks