- Fix RangeSetBuilder ordering crash: inline and fenced-block decorations
are now merged and sorted before being added, instead of two unsorted
passes (crashed whenever a fenced block preceded inline code in a note).
- Add explicit @codemirror/state and @codemirror/view devDependencies
(previously only transitive via @codemirror/language).
- Add Reading View support for inline `date-calc:` spans via
registerMarkdownPostProcessor (previously Live Preview only), mirroring
the approach used by Dataview's inline queries.
- Fix verbose=false being silently truthy (non-empty string) in inline
key=value config, which meant it never actually disabled verbose output.
- Fix diff type auto-inference: from/to was dead code (countdown's check
always matched first); reordered so from+to or start+end infer diff.
- Implement documented but missing birthday label support: cfg.label,
falling back to frontmatter name ("Jane's age:"), then "Age:".
- Split main.ts (777 lines) into src/ modules per AGENTS.md conventions.
- Fix duplicated command-palette prefixes, move inline JS styles to
styles.css, fix package.json author, drop orphaned showArrow setting.
Verified: unit tests against the real bundled logic (mocked obsidian
module), a reproduction of the RangeSetBuilder crash against the real
@codemirror/state package, and live end-to-end testing in Obsidian via
CDP/Playwright (Tchernobyl vault).
5.4 KiB
Date Calculator
An Obsidian plugin that adds dynamic date calculations to your notes using date-calc fenced code blocks and inline code.
Todo
- Add custom language (default to Obsidian language, overridable)
Features
Fenced Code Blocks
Add date-calc code blocks to your notes for rich date calculations:
type: birthday
birthday: 1992-08-16
Inline Code
Use inline code for quick calculations: date-calc: birthday=1992-08-16
Rendering modes: Inline code and fenced blocks both render in Reading view and Live Preview mode. In Source mode, you'll see the literal date-calc: code until you switch to Reading view or Live Preview.
Supported Calculation Types
Birthday (birthday)
Calculates age and time until next birthday, with an optional custom label and automatic personalization from your note's frontmatter.
Fields:
birthday(orbirthdate,date): Birth date in YYYY-MM-DD formatlabel(optional): Custom label (defaults to "Age:")
Frontmatter Support: If not provided in the code block, the plugin reads birthday/birthdate from the note's frontmatter. If no label is set, a frontmatter name property becomes the default label automatically (e.g. name: John → "John's age:").
Examples:
type: birthday
birthday: 1992-08-16
type: birthday
birthday: 2000-05-21
label: "John's age:"
Countdown (countdown or until)
Shows time remaining until a target date.
Fields:
to(ordate,until): Target date/timefrom(optional): Starting date/time (defaults to now)label(optional): Prefix label for the output
Examples:
type: countdown
label: New Year
to: 2025-12-31 23:59
type: countdown
label: Sprint ends
to: 2025-10-15 17:00
from: 2025-10-01 09:00
Since (since)
Shows time elapsed since an event (or time until if the event is in the future).
Fields:
since(orfrom,date): Event date/time
Example:
type: since
since: 2024-12-20
Difference (diff)
Calculates the time difference between two specific dates.
Fields:
from(orstart): Start date/timeto(orend): End date/time
Examples:
type: diff
from: 2024-02-29
to: 2025-03-01
type: diff
from: 2025-09-19 08:00
to: 2025-09-19 16:30
Inline Usage
You can use inline code for quick calculations:
date-calc: birthday=1992-08-16→ Birthday summarydate-calc: to=2025-12-31 label="New Year"→ Countdowndate-calc: since=2024-12-20→ Time since eventdate-calc: from=2025-09-19 to=2025-09-20→ Date difference
YAML Format: Inline code also accepts YAML/inline-map format:
date-calc: {type: birthday, birthday: 1992-08-16}
Frontmatter Integration: For inline birthday calculations, if no date is provided, the plugin will use the note's frontmatter birthday/birthdate property.
Date Formats
- Timezone: All calculations use your local timezone
- Birthday Calculations: Normalized to local midnight to avoid timezone inconsistencies
Configuration Options
Verbose Output
Control output verbosity globally via settings or per-calculation:
Global: Settings → Date Calc → Verbose output
Per-calculation override:
type: countdown
to: 2026-12-31
verbose: true
Inline: date-calc: countdown to=2026-12-31 verbose=true
verbose: true→ "Countdown: 1 year, 2 months, 15 days"verbose: false→ "1y 2mo 15d"
Hide While Editing
Settings → "Hide result while cursor inside" prevents rendered output from showing while you're editing the code, keeping the raw syntax visible.
Date Formats
| Format | Example | Use Case |
|---|---|---|
| Date only | 2026-12-31 |
Birthdays, countdowns |
| Date + time | 2026-12-31 23:59 |
Precise countdowns |
| ISO 8601 | 2026-12-31T23:59:00 |
Also supported |
All dates use your local timezone. Birthday calculations normalize to midnight to avoid timezone edge cases.
Field Reference
Birthday
birthday/birthdate/date— Birth dateverbose— Override output format (optional)
Countdown
to/until/date— Target date/timefrom— Start date (defaults to now)label— Custom prefixverbose— Override output format
Since
since/from/date— Event date/timeverbose— Override output format
Diff
from/start— Start date/timeto/end— End date/timeverbose— Override output format
Type Aliases
For convenience, use these shortcuts:
birthday=bdaycountdown=untildiff=difference
Inline Syntax Formats
All three formats work:
Key=value: date-calc: birthday=1992-08-16
YAML-like: date-calc: type: birthday, birthday: 1992-08-16
Compact: date-calc: {type: birthday, birthday: 1992-08-16}
Custom Styling
Target these CSS classes in your snippets:
/* Fenced block results */
.date-calc-block {
color: var(--text-accent);
font-weight: 500;
}
/* Inline code results */
.date-calc-inline {
background: var(--background-secondary);
padding: 2px 6px;
border-radius: 3px;
}
Commands
- Toggle debug — Log decoration activity to console
- Toggle verbose — Switch global verbose mode