How to Display Obsidian’s Native Calendar Modal All the Time?

Obsidian has a native calendar modal—screenshot below taken from Properties.

Is there a way to display that modal all the time (in a side bar) so it can be used as a calendar / date picker for daily notes etc? I could then get rid of the Calendar plugin, which hasn’t been updated since April 2021. :weary_cat:

Other than using another calendar/daily note related plugin providing such a view (other than Liam Cain’s Calendar), I don’t think that’s possible :thinking:

I mean, the date or date/time picker you can get when using Properties is solely used for that specific purpose: Picking a date or date & time to add as a value for the relevant key in Properties :blush: .

1 Like

As I thought. It seems odd to me that Obsidian clearly has an underlying calendar interface—or access to one, perhaps through the OS, if such a thing is possible—but that at the moment it is only available in limited places. Obsidian has a core plugin for daily notes but not a core calendar to complement the daily notes. I know there is a FR for this, but was also hoping that I might have overlooked a way of accessing the calendar used in Properties, and a way to repurpose it.

I know I could fashion something with Bases, but that would be a faff with its current features.

And I worry that Liam’s Calendar will one day stop working with Obsidian’s many advances.

:star_struck:

I don’t know about the possibility of directly using Obsidian’s datepicker, but I wrote time ago a dataviewjs snippet that generates a view for the current month, in form of markdown table, making each day a wikilink to the associated daily note.

This is the snippet:

async function getDailyNotesConfig() {
    try {
        const configPath = app.vault.adapter.path.join(app.vault.configDir, 'daily-notes.json');
        const configExists = await app.vault.adapter.exists(configPath);
        if (configExists) {
            const configContent = await app.vault.adapter.read(configPath);
            return JSON.parse(configContent);
        }
    } catch (e) {
        console.log('No daily notes config:', e);
    }
}

const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const first = new Date(y, m, 1);
const last = new Date(y, m + 1, 0);
const totalDays = last.getDate();
const today = now.getDate();

const locale = navigator.language || 'en-US';
const monthName = now.toLocaleString(locale, {month:'long'});

// Create title
dv.header(2, `📅 ${monthName.charAt(0).toUpperCase() + monthName.slice(1)} ${y}`);

// Get first day of week from Moment.js locale (used by Obsidian)
const moment = window.moment;
const firstDayOfWeek = moment.localeData()._week.dow; // 0=Sunday, 1=Monday

// Generate weekdays dynamically based on locale and start day preference
const dows = [];
const baseDate = new Date(2024, 0, 7); // Jan 7, 2024 (Sunday)
for (let i = 0; i < 7; i++) {
    const dayIndex = (firstDayOfWeek + i) % 7;
    const day = new Date(2024, 0, 7 + dayIndex); // Start from Sunday and offset
    const dayName = day.toLocaleDateString(locale, { weekday: 'short' });
    dows.push(dayName);
}

// Adjust startMonIdx calculation based on first day of week setting
const rawStartMonIdx = first.getDay(); // 0=Sunday, 1=Monday, etc.
const startMonIdx = (rawStartMonIdx - firstDayOfWeek + 7) % 7;

let table = '| ' + dows.join(' | ') + ' |\n';
table += '| ' + '---:|'.repeat(7) + '\n';

// Create calendar as markdown table
getDailyNotesConfig().then(config => {
    let week = new Array(7).fill('');
    for (let i = 0; i < startMonIdx; i++) {
        week[i] = '';
    }
    let currentWeekDay = startMonIdx;
    for (let day = 1; day <= totalDays; day++) {
        const date = new Date(y, m, day);
        const dailyNotePath = window.moment(date).format(config.format || 'YYYY-MM-DD');
        const fullPath = config.folder ? config.folder + '/' + dailyNotePath : dailyNotePath;
        
        // Create markdown link
        let cellContent;
        if (day === today) {
            cellContent = `**[[${fullPath}\\|${day}]]**`; // Día actual en negrita
        } else {
            cellContent = `[[${fullPath}\\|${day}]]`;
        }
        
        week[currentWeekDay] = cellContent;
        currentWeekDay++;
        if (currentWeekDay === 7 || day === totalDays) {
            table += '| ' + week.join(' | ') + ' |\n';
            week = new Array(7).fill('');
            currentWeekDay = 0;
        }
    }
    
    dv.paragraph(table);
});

The table is a bit too big to put it in a side pane, but you can also use this css snippet:

.calendar-compact,
.workspace-leaf .calendar-compact,
.workspace-leaf-content .calendar-compact {
    font-size: 70% !important;
}

.calendar-compact *,
.workspace-leaf .calendar-compact *,
.workspace-leaf-content .calendar-compact * {
    font-size: inherit !important;
}

.calendar-compact th,
.calendar-compact td {
    padding: 0.3em 0.05em !important;
    text-align: center !important;
    line-height: 1.2 !important;
}

.calendar-compact a {
    text-decoration: none !important;
}

.calendar-compact strong a {
    background-color: var(--interactive-accent) !important;
    color: var(--text-on-accent) !important;
    font-weight: bold !important;
    padding: 0.2em 0.4em !important;
}

After activating the css snippet, you have tu put the property cssclasses in the note, with the value calendar-compact

This is how it looks in the side pane:

The month and week days names are automatically localized to your language. The “today” cell is highlighted.

Limitations

  • It only shows the current month. It’s not possible to navigate to other months.
  • Clicking in a date opens the daily note, but if the calendar is in the side pane, the daily note will be open there, which is not wanted. Use Ctrl+click (Cmd+click) to open it in the main pane.
1 Like

This calendar you are talking about is not actually Obsidian’s native modal, but simply html date input, rendered by the browser (or, in this case, by Electron). It is almost impossible to do something about it, because it’s view and behavior is hardcoded. So no, it can not be used to make some different calendar view.

1 Like

Many thanks, @JLDiaz and @reaty :star_struck:

Grateful for the DVJS idea. I have recently removed Dataview from my vault and replaced it with Bases. Dataview is old and being replaced by Datacore—as I am sure you must already know—although I can’t help but wonder if either plugin will be maintained in the long term, as I think most users will default to Bases as a core plugin and that interest in DV and DC will dwindle (of course, I might be wrong). But for me, I am trying to remove all community plugins from my vault: burned too many times by plugins that have been abandoned.

Thanks for the explanation about the html date input. There disappears my hope of repurposing it and removing the ageing Calendar plugin. Kind of frustrating that the date input is only accessible in some use cases. Will just have to hope that Obsidian adds a core Calendar plugin soon.

:crossed_fingers:

Oh, happy day …

Dataview isn’t yet obsolete and Bases still a brand new core feature, so removing Dataview now sounds just too premature to me.

Datacore has been in the works for some time but it didn’t release in public ever, which isn’t a good indicator for a reliable tool to add in a day to day usage, imo.
I believe, community plugins are generally more mature (defined by the submitting author) so better to stick to classic resources than to switch too quickly to new shiny things.

Finally, Bases is nice but I don’t see yet the same potential as with Dataview.

1 Like