Bringing the Nepali calendar to KDE Plasma
Plasma’s clock can show a second calendar under every date — Chinese, Hebrew, Islamic, Indian, Ethiopian. Starting with 6.8 it can also show Bikram Sambat, the official calendar of Nepal. This is how that works, and why it’s mostly a data problem.
A calendar you can’t compute
Gregorian dates follow rules: 30 days hath September, leap years every four years with a couple of exceptions. You can write the whole thing as arithmetic.
Bikram Sambat doesn’t work like that. Its twelve months run anywhere from 29 to 32 days, and the lengths change from year to year. They come from astronomical calculation and are fixed in the official calendar (पात्रो) published in Nepal each year. There is no formula that reproduces them — the only reliable source is the published table.
So the core of the feature isn’t an algorithm. It’s getting trustworthy data into the codebase in a form that’s cheap to query.
A century in two arrays
I took the day counts for every month from BS 2000 to BS 2099 — roughly 1943 to 2043 — from the official calendar published by Kathmandu Metropolitan City, along with the Gregorian date each year begins. In C++ that becomes two constexpr arrays:
// Days in each month, BS 2000–2099.
constexpr std::array<std::array<quint8, 12>, 100> s_daysPerMonth{{
{30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31}, // BS 2000
{31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30}, // BS 2001
...
}};
// Days from Baishakh 1, BS 2000 (14 April 1943) to Baishakh 1 of each year.
constexpr std::array<int, 100> s_yearStartDays{0, 365, 730, 1095, 1461, ...};
Each month length fits in a byte, so the whole century is about 1.6 KB, baked into the binary. No data files to install, nothing to parse at startup, no network.
Converting a date
Given a Gregorian date, count the days since the epoch, find the year whose start is the last one not after that count, then walk through that year’s months:
const qint64 days = s_epoch.daysTo(date);
std::size_t i = 0;
while (i + 1 < s_yearCount && days >= s_yearStartDays[i + 1])
++i;
int offset = days - s_yearStartDays[i];
int month = 0;
while (month < 12 && offset >= s_daysPerMonth[i][month])
offset -= s_daysPerMonth[i][month++];
return {2000 + int(i), month + 1, offset + 1};
A linear scan over a hundred entries is plenty fast for a calendar that renders a month at a time, and it keeps the code obvious to review.
That converter is the same logic and the same table, ported to JavaScript and running in your browser.
Dates the table doesn’t cover
A calendar widget lets you scroll anywhere, including years before 1943 or after 2043. Showing nothing there would look broken; silently showing a wrong date would be worse.
Outside the table, the provider falls back to the mean month length derived from the table itself and appends (approx.) to the label. Users get a sensible answer, and they’re told it’s an estimate.
Speaking the language
The label under each date uses Devanagari month names and Nepali digits — ७ पुष, २०८२ rather than “7 Poush 2082”. The format string goes through KDE’s i18n system, so translators can still reorder the parts for their language.
Fitting into Plasma
The alternate calendar plugin already had a clean extension point: each calendar system is a provider class. Adding Bikram Sambat meant
- a new
BikramSambatentry in the calendar-system enum and its display name, - a
NepaliCalendarProvidersubclass ofAbstractCalendarProviderthat implementsfromGregorian()andsubLabel(), - one line in the plugin to construct it, and one in CMake.
Five files, about three hundred lines — most of them the table. Because it doesn’t depend on ICU, it’s available on every Plasma build, not only ones compiled with ICU support.
From widget to upstream
This started as a standalone Nepali Calendar widget on the KDE Store. A widget helps the people who find and install it. Upstream, it’s simply there: anyone in Nepal who installs Plasma can turn it on in the Digital Clock’s calendar settings.
The merge request went through four commits and review before Nate Graham merged it on 1 September 2026. It closes bug 500298, a feature request open since February 2025, and ships in Plasma 6.8.