Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Calendar Blocks

Alexander KramarevAlexander Kramarev114 downloads

Renders date and date-range code blocks as calendars.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates5

Calendar Blocks is an Obsidian plugin for rendering dates and date ranges as calendars.

Examples

Single date

```date
2026.06.06
```

A minimal calendar with June 6 selected

Legend

```dates
Vacation: 7 May 2027 - 17 May
Birthday: 9 May
Conference: 19 May
```

Legend with smart year selection

Range within one month

```date
2026.06.05 - 2026.06.11
```

A minimal calendar with a range from June 5 through June 11

Range across adjacent months

```date
2026.06.05 - 2026.07.05
```

Minimal calendars with a range from June 5 through July 5

Range with omitted months

```date
2026.06.05 - 2026.10.05
```

Minimal calendars with a range from June 5 through October 5 and a wave for omitted months

Usage

Use a fenced date code block for a single date:

```date
2025.07.27
```

The dates block name is supported as an alias and has identical behavior.

Use a hyphen between two dates for a range:

```date
2025.07.27 - 2025.08.03
```

Multiple ranges and dates

Put each range or single date on its own line in the same block:

```dates
2026.06.05 - 2026.06.11
2026.06.09 - 2026.06.15
2026.06.10
2026.07.03 - 2026.08.05
```

All entries appear together. Ranges and single dates use two independent pools of the same 40-color palette, each starting with red, blue, and green in source order. The first single date and the first range are both red; adding a single date does not advance the range colors, and vice versa. A range with identical endpoints collapses into a single date: it uses a circle, a color from the single-date pool, and a circle in the legend. Each entry keeps its color across weeks and months. Overlapping ranges retain their translucent layers, so their colors blend at intersections. Single dates appear as colored circles above all ranges, regardless of line order. Blank lines are ignored; an invalid entry reports its line number and rejects the whole block.

A block accepts up to 40 entries in total; adding a 41st range or single date shows an error. Blank lines do not consume colors or count toward the limit.

Months are shown once, in chronological order, adding the endpoint months of each range and the months of single dates. Long ranges still show their first and last months, with a wave at each gap. Additional months form rows of two calendars and stack vertically in narrow panes.

Legend

Add a label followed by a colon before a range or single date:

```dates
Vacation: 1 Mar - 9 Mar
Conference: 5 Mar - 7 Mar
Birthday: 8 Mar
```

The legend appears below all calendars, with one labeled entry per line and a marker on the left. Ranges use a pill about 1.47 times as wide as a single-date circle, matching the range's color and transparency. Single dates use solid circles. Markers share a column and align to its right edge, keeping all labels aligned. Unlabeled entries are omitted from the legend but still consume a color from their type's pool. If no entries have labels, no legend is shown. Labels support plain text, including spaces and Unicode.

Supported date formats

Dates accept one- or two-digit days and months:

  • Year first: 2026.03.02, 2026-03-02, 2026/3/2.
  • Day first: 02.03.2026, 2/3/2026 (always day/month/year).
  • Month names in the system locale and Obsidian language, case-insensitive: full names, abbreviations (with or without a trailing period), and grammatical forms used in dates, such as 1 марта, 1 март, or 1 мар. in Russian. English names (2 Mar 2026, 2 March 2026) are always accepted.
  • Without a year: 2.3, 02/03, 2 Mar.

For the first entry, when a single date or both range endpoints omit their years, the plugin uses the source note's creation year (Obsidian's file creation timestamp). It does not use the current year or the last modification year. If both range years are omitted, the creation year determines the start year and the end may roll into the next year. If the source note is unavailable, specify the year of the first single date or either endpoint of the first range explicitly.

A range end without a year uses the start's year, advancing to the next year when its month/day would fall before the start. For example, 28 Dec 2005 - 1 Jan ends on January 1, 2006, independently of the note's creation year. Conversely, 28 Dec - 1 Jan 2006 starts on December 28, 2005: an omitted start year uses the end's year, moving back one year if its month/day would fall after the end. Explicit years are always respected.

For subsequent entries, a single date without a year (or the start of a range with both years omitted) uses the year that places it closest to the interval from the earliest to the latest previously resolved date in the block. Dates inside that interval have zero distance; ties choose the earliest occurrence. This takes precedence over the note creation year. Each resolved entry expands the interval, and blank lines do not reset it. A yearless February 29 uses the nearest valid leap year. Explicit years and inference from the other endpoint of the same range retain priority.

For example, Vacation: 7 May 2027 - 17 May followed by Birthday: 9 May puts all dates in 2027. With 30 Dec 2010 - 7 Jan, the range ends in 2011; a following 9 Jan resolves to 2011, while 5 Dec resolves to 2010.

For example, in a note created in 2026:

```date
1 Mar - 4 Apr
```

This selects March 1 through April 4, 2026. Formats can be mixed within a range; hyphens, en dashes and em dashes are accepted as separators. Invalid calendar dates and reversed ranges with explicit years are rejected. Ranges crossing New Year can omit the end year, for example 31 Dec 2026 - 1 Jan.

Settings

Calendars use the grid-free Minimal design with narrow weekday labels and a filled circle for a single selected date.

Enable Stretch calendar in the Calendar Blocks settings to make calendars use the full available note width. It is disabled by default, preserving the compact layout.

Show today is enabled by default. It marks the current local date with a red, hand-drawn open oval in any displayed month and refreshes after the day changes. The marker is chosen pseudorandomly from four variants with different gaps and stroke thicknesses. The current local date, the source filename (including its extension), and the date/dates block's order in the note determine the choice. Rerendering, resizing, or switching settings keeps the same variant for that combination. Block order comes from the source text, independently of render order. Turn it off to hide the mark. The editable SVG resource is src/assets/today-marker.svg; it is embedded in the plugin bundle during the build, alongside today-marker-2.svg, today-marker-3.svg, and today-marker-4.svg.

Installation

Manual installation from Releases

  1. Open the latest release and download the attached main.js, manifest.json, and styles.css files. Do not download GitHub's automatically generated source code archives.

  2. Create this directory inside your Obsidian vault:

    <vault>/.obsidian/plugins/calendar-blocks/
    
  3. Copy the three downloaded files directly into that directory. The resulting layout must be:

    <vault>/.obsidian/plugins/calendar-blocks/
    ├── main.js
    ├── manifest.json
    └── styles.css
    
  4. Reload Obsidian, open Settings → Community plugins, and enable Calendar Blocks.

Build

npm ci
npm run build

Copy the contents of build/ to:

<vault>/.obsidian/plugins/calendar-blocks/

Then reload Obsidian and enable Calendar Blocks in the community plugins settings.

Publishing

Before publishing, run npm test, npm run build, and git diff --check. Keep the version in manifest.json, package.json, and package-lock.json in sync, and record its minimum Obsidian version in versions.json. The minimum supported Obsidian version is 1.5.7, which introduced the Vault.getFileByPath API used to resolve the source note.

Create a Git tag that exactly matches the manifest version, without a v prefix (for example, 0.1.1). Pushing that tag runs CI and publishes a GitHub release with only main.js, manifest.json, and styles.css as attached assets. Append a concise, readable bullet to CHANGELOG.md when committing a change. Keep it as a flat list, with one entry per line and no version sections. CI generates the release description from added bullet lines in the changelog diff since the previous release tag, preserving file order and removing duplicates. The first release, or the first release with a changelog, includes all its entries. Both current tags (0.1.1) and legacy tags (v0.1.0) delimit the diff.

Before publishing the release, CI generates GitHub build provenance attestations for the three individual plugin assets. The signing permissions are restricted to the release job, which runs only for version tags after tests and the build succeed. Verify downloaded assets with the GitHub CLI:

gh attestation verify main.js --repo pochemuto/calendar-blocks
gh attestation verify manifest.json --repo pochemuto/calendar-blocks
gh attestation verify styles.css --repo pochemuto/calendar-blocks

The initial directory submission is made through Obsidian Community after signing in and connecting the repository owner's GitHub account. Subsequent updates use GitHub releases. See the official submission guide.

License

MIT.

Visual regression tests

npm test runs unit tests and 56 screenshot comparisons (28 cases in light and dark themes). Visual tests require a running Docker engine. The first run downloads the pinned Playwright image. Local runs and CI use the same Linux arm64 image, Chromium version, bundled Noto Sans font, locale, timezone and pixel density; no host fonts or Obsidian installation are needed.

npm ci
npm test
# Run just one suite:
npm run test:unit
npm run test:visual
# Filter visual cases:
npm run test:visual -- --grep omitted-months

Reference PNGs live in tests/test-data/visual/linux/ and belong in Git. Every pixel must match: both the color threshold and allowed differing pixel count are zero. An additional decoded RGBA comparison includes antialiased pixels that Playwright's comparator can ignore. Missing references fail a normal test run. On failure, test-results/ contains expected, actual and diff images, and npm run test:visual:report opens the HTML report. CI uploads these artifacts.

After an intentional visual change, explicitly regenerate references:

npm run test:visual:update
# Or update only the affected cases:
npm run test:visual:update -- --grep legend

Review the changed PNGs before accepting them, then rerun npm test. The input fixtures live in tests/test-data/visual/*.md. Each scenario has one Markdown file (for example, adjacent-months.md) shared by all platforms and themes. It contains one fenced date or dates block and embeds light and dark reference images for every platform directory using relative links. Screenshot paths follow <platform>/<case>-<theme>.png, for example linux/adjacent-months-light.png and linux/adjacent-months-dark.png. Open the Markdown file on GitHub to see all inputs and outputs together. The test runner automatically runs each scenario in both light and dark themes; Playwright selects the screenshot directory for the platform it runs on.

Optional fixture settings go in YAML frontmatter at the start of the file:

---
width: 280
locale: ru
stretch: true
showToday: true
---

Defaults are width 640, locale en-US, stretching disabled, and Show today enabled. The source note creation year is fixed at 2026, and the browser clock is fixed at October 26, 2026, 12:00 UTC. Marker randomness uses a fixed seed of 7 for each fixture, so today's marker produces stable screenshots. Set markerSeed in fixture frontmatter to cover another variant reproducibly. To add a scenario in both themes, add <name>.md with the input, settings and image links for all platforms and themes, then run npm run test:visual:update. There is no separate case list in code. Unit tests validate the Markdown format, all screenshot embeds and their relative paths, existing PNG targets, and a matching Markdown file for every reference image across every platform directory. Broken, missing, duplicate or swapped image links fail tests. Adding another platform requires its light and dark screenshot embeds in each existing scenario, with no duplicate input files. Keep the Docker image version in tests/visual/run.mjs aligned with the exact @playwright/test dependency. Browser or font upgrades may require reviewed reference updates.

The harness uses the production parser, renderer and stylesheet with fixed Obsidian theme variables. It covers responsive container queries, highlight layers, legends, localization, month lengths, year boundaries, stretching and all 40 selection colors. These tests exercise the shared calendar rendering; Live Preview/Reading integration and third-party Obsidian themes still need manual checking in Obsidian.

HealthExcellent
ReviewPassed
About
Render single dates and date ranges as calendar blocks inside notes, showing months once in chronological order and collapsing identical-range endpoints into single-date circles while marking long-range gaps with waves. Color-code up to 40 entries with separate pools for ranges and singles, blend overlapping translucent ranges, place single-date circles above ranges, and show a labeled legend beneath the calendars.
CalendarDatesVisualization
Details
Current version
0.1.4
Last updated
2 weeks ago
Created
5 months ago
Updates
5 releases
Downloads
114
Compatible with
Obsidian 1.5.7+
Platforms
Desktop, Mobile
License
MIT
Report bugRequest featureReport plugin
Author
Alexander KramarevAlexander Kramarevpochemuto
GitHubpochemuto
  1. Community
  2. Plugins
  3. Calendar
  4. Calendar Blocks

Related plugins

Itinerary

Make planning your trip or event easier by rendering a calendar from event information found in your notes.

Yearly Glance

Year at a glance - overview of annual events with customizable management options.

Prisma Calendar

Prisma turns any note with a date into a flexible planning system inside Obsidian. There are no rigid schemas or predefined structures — just your data, your rules, fully under your control.

Day Planner

Turn tasks from daily notes, the Tasks plugin, and calendars into time blocks on an editable timeline, with built-in time tracker.

Full Calendar Remastered

Complete Calendar HUB experience. Work with all your calendars in one place. Analyze your time and take action!

Journals

Manage your journals.

Periodic Notes

Manage your daily, weekly, and monthly notes.

Tasks Calendar Wrapper

Simple wrapper for Tasks Calendar and Tasks Timeline.

Calendarium

Craft mind-bending fantasy and sci-fi calendars.

Journal Review

Review your daily notes on their anniversaries, like "what happened today last year".