
September 09, 2026
13 min read
By Kokil Thapa | Last reviewed: September 2026
Nepal-facing Laravel apps must handle the Bikram Sambat Calendar in Laravel Applications without corrupting business logic. Users think in BS dates on invoices, court filings, HR records, and booking forms. Your database should stay on Gregorian timestamps for sorting, reporting, and third-party APIs. The hard part is conversion at the edges — input, display, PDFs, and exports — while month lengths and leap rules stay correct year to year.
This guide covers storage strategy, conversion services, Eloquent casts, form validation, API design, and production bugs I've seen on legal-tech and booking portals. If you only need a quick sanity check, compare output against the Nepali date converter tool before you ship.
Why do Laravel applications in Nepal need Bikram Sambat calendar support?
Bikram Sambat (BS) is Nepal's official civil calendar. Government forms, bank vouchers, salary slips, and legal documents reference BS dates first. An English-only date picker creates friction and data-entry errors. Users type impossible dates like 32 Baisakh because the UI never enforced month length.
On legal-tech portals I've shipped — court marriage guides, notary workflows, divorce information sites — date fields are not cosmetic. A wrong BS date on a certificate request or appointment slot breaks trust fast. The same applies to trekking bookings, payroll tools, and any system where staff verbally confirm dates in Nepali.
Laravel 12 and Laravel 13 both work fine for this pattern. PHP 8.3 or higher is enough. You do not need a separate calendar database table unless you are building a public holiday engine. Most apps need conversion, display, and validation only.
Teams often ask whether to rewrite the whole app for Nepali dates. You should not. Follow the same modern Laravel architecture you already use. Keep domain logic on Carbon and SQL date types. Treat BS as a presentation and capture concern at boundaries.
How should you store Bikram Sambat dates in a Laravel database?
Store canonical dates as DATE or DATETIME in MySQL 8.4 LTS or MySQL 9.7. PostgreSQL 18 works the same way with native date columns. Never store BS strings like 2081-02-15 as your only source of truth. Sorting, range queries, and foreign integrations all break when month lengths shift between years.
Recommended schema pattern
Schema::create('appointments', function (Blueprint $table) {
$table->id();
$table->date('scheduled_on'); // canonical AD date
$table->string('scheduled_on_bs', 10)->nullable(); // optional audit snapshot
$table->timestamps();
}); The optional scheduled_on_bs column is an audit snapshot, not the authority. Write it only after successful conversion. If rules change or you fix a converter bug, recompute from scheduled_on. On a production Laravel application for a law firm portal, I keep BS snapshots on generated PDF metadata only.
Timezone and midnight edge cases
Nepal Standard Time is UTC+5:45. Laravel's config/app.php timezone should be Asia/Kathmandu for Nepal-only apps. For multi-country eCommerce, store UTC in the database and localise in the UI. A booking at BS midnight can shift AD date if you convert in the wrong zone. Always convert BS calendar dates as date-only values without time when the business meaning is a civil day.
Redis 8.10 cache keys for "today in BS" should expire at Kathmandu midnight, not UTC midnight. Scheduled tasks that roll daily reports must use now('Asia/Kathmandu') as the reference. See PostgreSQL for Laravel developers if you use timestamptz columns across regions.
How do you convert between Bikram Sambat and Gregorian dates in Laravel?
Centralise conversion in one service class. Do not scatter conversion calls inside Blade templates or random controllers. Register it as a singleton in a service provider so tests and APIs share the same logic.
Service class skeleton
namespace App\Services;
use Carbon\Carbon;
use InvalidArgumentException;
class BikramSambatConverter
{
public function toAd(int $year, int $month, int $day): Carbon
{
if (! $this->isValidBsDate($year, $month, $day)) {
throw new InvalidArgumentException('Invalid Bikram Sambat date.');
}
// Delegate to your chosen conversion table / library
[$gy, $gm, $gd] = $this->convertBsToGregorian($year, $month, $day);
return Carbon::createFromDate($gy, $gm, $gd, 'Asia/Kathmandu');
}
public function toBs(Carbon $date): array
{
return $this->convertGregorianToBs(
$date->year,
$date->month,
$date->day
);
}
public function formatBs(Carbon $date, string $locale = 'en'): string
{
$bs = $this->toBs($date);
return sprintf('%04d-%02d-%02d', $bs['year'], $bs['month'], $bs['day']);
}
} You can implement convertBsToGregorian() with a maintained PHP library or an internal lookup table updated when Nepal publishes official calendar changes. Whichever you pick, lock reference vectors in tests. Compare against the Nepali date converter for manual QA, not as your runtime dependency.
Custom Eloquent cast
Expose a BS accessor while keeping AD storage transparent to the rest of the app. Laravel documents custom casts in the Eloquent mutators and casting guide.
namespace App\Casts;
use App\Services\BikramSambatConverter;
use Carbon\Carbon;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class BikramSambatDate implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes): ?array
{
if ($value === null) {
return null;
}
$converter = app(BikramSambatConverter::class);
return $converter->toBs(Carbon::parse($value));
}
public function set($model, string $key, $value, array $attributes): array
{
if ($value === null) {
return [$key => null];
}
$converter = app(BikramSambatConverter::class);
$carbon = $converter->toAd($value['year'], $value['month'], $value['day']);
return [$key => $carbon->toDateString()];
}
} Use this cast on virtual or dedicated JSON columns when you must accept BS payloads from legacy imports. For normal columns, keep native date casts on the AD field and format BS in resources or view models.
| Approach | Best for | Trade-off |
|---|---|---|
| AD column + formatter | Most CRUD apps, APIs, reports | Requires converter service |
| AD column + BS snapshot | Legal PDFs, audit trails | Snapshot can drift; treat as display-only |
| BS string as primary key | None in Laravel production apps | Sorting and integrations fail |
| Dual columns both authoritative | Never | Guaranteed inconsistency |
How do you build BS date pickers and validation in Laravel forms?
Server-side validation is non-negotiable. JavaScript pickers improve UX, but users can POST forged values. Validate month length per BS year before conversion. Month 1–12 names differ between Nepali and English labels; keep integers in POST data.
Form Request example
namespace App\Http\Requests;
use App\Services\BikramSambatConverter;
use Illuminate\Foundation\Http\FormRequest;
class StoreAppointmentRequest extends FormRequest
{
public function rules(): array
{
return [
'bs_year' => ['required', 'integer', 'min:2000', 'max:2100'],
'bs_month' => ['required', 'integer', 'min:1', 'max:12'],
'bs_day' => ['required', 'integer', 'min:1', 'max:32'],
];
}
public function withValidator($validator): void
{
$validator->after(function ($validator) {
$converter = app(BikramSambatConverter::class);
if (! $converter->isValidBsDate(
(int) $this->bs_year,
(int) $this->bs_month,
(int) $this->bs_day
)) {
$validator->errors()->add('bs_day', 'Invalid Bikram Sambat date.');
}
});
}
public function scheduledOnAd(): \Carbon\Carbon
{
return app(BikramSambatConverter::class)->toAd(
(int) $this->bs_year,
(int) $this->bs_month,
(int) $this->bs_day
);
}
} In Blade, pass month names from a config array or lang files. For dynamic UIs, Livewire pairs well with BS widgets because server state revalidates on each action. See the Laravel Livewire tutorial for beginners if you are wiring interactive pickers.
- Render BS year, month, and day selects or a Nepali date-picker widget.
- POST integers, not formatted Nepali Unicode strings, unless you normalise first.
- Validate with
FormRequestbefore touching Eloquent. - Convert to AD once; persist the Carbon date string.
- Flash old BS values back on validation failure so users do not retype.
On the Court Marriage In Nepal project and similar legal guides, date fields feed PDF summaries. We show BS prominently and AD in smaller type for embassy-facing copies. That dual display reduces support calls.
Write feature tests that cover month-end boundaries. Baisakh can have 31 or 32 days depending on the year. Tests belong beside other domain rules — see Laravel feature testing best practices for structure.
How do you expose Bikram Sambat dates in Laravel APIs and exports?
API consumers outside Nepal often expect ISO-8601 AD timestamps. Nepali mobile apps and partner systems may want BS parts. Return both, clearly labelled, without making either ambiguous.
public function toArray($request): array
{
$converter = app(BikramSambatConverter::class);
$bs = $converter->toBs($this->scheduled_on);
return [
'scheduled_on' => $this->scheduled_on->toDateString(),
'scheduled_on_iso' => $this->scheduled_on->toIso8601String(),
'scheduled_on_bs' => [
'year' => $bs['year'],
'month' => $bs['month'],
'day' => $bs['day'],
'formatted' => $converter->formatBs($this->scheduled_on),
],
];
} Version your API if you add BS fields later. Document that scheduled_on remains the canonical AD field for sorting. Follow patterns from building RESTful APIs with Laravel and Laravel API best practices.
Excel exports for HR and payroll should include BS columns because finance staff reconcile in Nepali. Use Laravel Excel for spreadsheets, but compute BS in PHP — not with spreadsheet formulas your staff cannot audit. The Nepal salary calculator audience expects the same date clarity on payslip portals.
For client portals like Mijar Law Associates or Notary Nepal, JSON responses power dashboards and document lists. Consistent BS formatting across endpoints matters more than exotic serialisation.
What are common Bikram Sambat calendar bugs in production Laravel apps?
Most failures are boring. They come from duplicated converters, missing tests, and timezone drift — not from Laravel itself.
- Double conversion: Controller converts BS to AD, then a model mutator converts again. Store AD once.
- Fixed 30-day months: Hard-coded month lengths fail in Ashadh, Kartik, and leap-adjusted years.
- UTC midnight rollover: A BS date typed late evening shifts AD when parsed with UTC default.
- Stale library tables: Official Nepal calendar adjustments require updating lookup data, not app code.
- Locale mix-ups: Displaying Nepali month names while sorting English abbreviations confuses filters.
- PDF vs DB mismatch: PDF generated BS from a formatter that differs from the API resource.
Schedule an annual review before Dashain-heavy release windows. Business teams notice wrong public-holiday labels before developers notice off-by-one AD dates. If you maintain sister sites on shared infrastructure, pin the converter version in Composer and deploy it with your normal GitLab CI pipeline.
PHP's native DateTime handles Gregorian rules well. It does not understand BS months. That is expected. Your converter owns Bikram Sambat logic; Carbon owns arithmetic once you have AD.
Booking systems such as Adventure Third Pole Trek mix tourist AD expectations with local BS operations. Separate admin views by audience instead of forcing one date format everywhere.
If you need full Nepal localisation — payments, NPR formatting, SSF calculators, document workflows — treat calendar support as one module in a broader build. Custom software development in Nepal and enterprise application development engagements usually bundle BS dates with auth, reporting, and compliance fields from day one.
Key Takeaways
- Store Gregorian
DATEorDATETIMEin MySQL or PostgreSQL; never rely on BS strings alone for logic. - Centralise BS ↔ AD conversion in one injected service with reference-date tests.
- Validate BS month length server-side in Form Requests before saving Eloquent models.
- Return both AD and BS in APIs — canonical AD for sorting, BS parts for local UI.
- Set
Asia/Kathmandutimezone deliberately and treat civil dates as date-only values. - Review converter data yearly and match edge cases against a trusted Nepali date reference.
People Also Ask
Should I store Bikram Sambat or Gregorian dates in my Laravel database?
Store Gregorian dates as the canonical value. SQL indexes, Carbon helpers, and foreign APIs expect AD. Format Bikram Sambat on read and accept BS on write through a converter. Optional BS snapshot columns are fine for PDF audit trails if AD remains authoritative.
Which PHP or Laravel package handles Nepali Bikram Sambat dates?
Several community PHP libraries ship BS lookup tables. Pick one maintained package, wrap it behind your own BikramSambatConverter service, and pin the version in Composer. Avoid calling package helpers directly from Blade or controllers so you can swap implementations without a rewrite.
How do I validate Nepali dates in Laravel forms?
Accept integer year, month, and day fields. Run a custom validation rule that checks day against the month's real length for that BS year. Only after validation passes should you convert to AD and persist. Client-side pickers improve UX but never replace server rules.
Do Laravel APIs need to return Bikram Sambat dates?
Return both formats when your users or partner apps operate in Nepal. Keep ISO AD fields for interoperability. Add a structured scheduled_on_bs object for local clients. Document which field is canonical to prevent double conversion bugs downstream.
Build Nepal-ready Laravel software with correct calendar support
Bikram Sambat Calendar in Laravel Applications is not a front-end cosmetic task. It touches validation, database design, APIs, PDFs, and test coverage. Get the storage model right, isolate conversion, and test month boundaries the way you test payment callbacks — quietly, before users find the edge cases.
If you are planning a portal, booking engine, or legal-tech workflow that must speak Nepali dates fluently, I can help architect and ship it. See web development in Nepal, API development in Nepal, and related work on Nepal Divorce Services. For ongoing fixes after launch, support and maintenance in Nepal and testing and optimization cover the long tail of calendar edge cases.
Contact us to discuss your Laravel project, conversion requirements, and go-live checklist.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

