Tutorial

This tutorial walks through the everyday tasks: creating BS dates, converting to and from the Gregorian calendar, formatting in English and Nepali, arithmetic, and time zones.

Creating dates

sambat.date takes a BS year, month (1 = Baishakh … 12 = Chaitra) and day. Months have 29 to 32 days, so day=32 is valid in long months:

>>> from sambat import date
>>> date(2083, 3, 32)
sambat.date(2083, 3, 32)
>>> date(2083, 3, 32).days_in_month()
32
>>> date(2083, 4, 32)
Traceback (most recent call last):
    ...
ValueError: day must be in 1..31 for BS 2083-04, not 32

Dates outside the published calendar raise ValueError with an explanation:

>>> import sambat
>>> sambat.MINYEAR, sambat.MAXYEAR
(1975, 2083)
>>> date(2090, 1, 1)
Traceback (most recent call last):
    ...
ValueError: year 2090 is out of range; sambat supports BS 1975..2083 (later years had no officially published calendar when this version of sambat was released; upgrading sambat may add them)

Converting

>>> import datetime
>>> date.from_gregorian(datetime.date(2026, 4, 14))
sambat.date(2083, 1, 1)
>>> date(2083, 1, 1).to_gregorian()
datetime.date(2026, 4, 14)

toordinal() returns the same day number as the standard library, so you can also convert through ordinals:

>>> date.fromordinal(datetime.date(2026, 10, 1).toordinal())
sambat.date(2083, 6, 15)

Today

date.today() and datetime.now() use the machine’s local time zone, exactly like the standard library. On a server running in UTC that can be the wrong day for Nepal, so sambat provides explicit helpers:

>>> today = sambat.today_np()  # the current date in Asia/Kathmandu
>>> now = sambat.now_np()      # an aware datetime in Asia/Kathmandu
>>> now.tzinfo
sambat.NEPAL_TZ

Formatting

strftime supports the usual directives, with BS meanings for the date ones:

>>> d = date(2083, 6, 15)
>>> d.strftime("%Y-%m-%d (%A, %B %d)")
'2083-06-15 (Thursday, Ashwin 15)'
>>> d.strftime("day %j of the year, week %V")
'day 171 of the year, week 25'

Pass locale=NE for Devanagari names and digits:

>>> from sambat.locale import NE
>>> d.strftime("%Y साल %B %d गते, %A", locale=NE)
'२०८३ साल असोज १५ गते, बिहीबार'

The %O modifier renders any numeric field with Devanagari digits, whatever the locale:

>>> d.strftime("%OY/%Om/%Od")
'२०८३/०६/१५'

See Format directives for every directive.

Parsing

>>> date.fromisoformat("2083-06-15")
sambat.date(2083, 6, 15)
>>> date.strptime("15 Asoj 2083", "%d %B %Y")
sambat.date(2083, 6, 15)
>>> date.strptime("२०८३ आश्विन १५", "%Y %B %d", locale=NE)
sambat.date(2083, 6, 15)

Parsing accepts ASCII and Devanagari digits and the common spellings of each month (Ashwin, Asoj, Aswin, असोज, आश्विन, …).

Arithmetic

Adding a timedelta works exactly as with the standard library:

>>> d + datetime.timedelta(days=17)
sambat.date(2083, 7, 1)
>>> date(2083, 7, 1) - date(2083, 1, 1)
datetime.timedelta(days=187)

For calendar months and years, use sambat.delta:

>>> from sambat.delta import relativedelta, diff
>>> date(2083, 3, 32) + relativedelta(months=1)  # clamped: Shrawan has 31 days
sambat.date(2083, 4, 31)
>>> diff(date(2056, 4, 12), date(2083, 6, 15))
relativedelta(years=+27, months=+2, days=+3)

Date and time with time zones

sambat.datetime accepts any tzinfo. sambat.NEPAL_TZ models Nepal’s offset history without needing the tzdata package:

>>> from sambat import NEPAL_TZ, datetime as bs_datetime
>>> meeting = bs_datetime(2083, 6, 15, 9, 30, tzinfo=NEPAL_TZ)
>>> meeting.isoformat()
'2083-06-15T09:30:00+05:45'
>>> meeting.astimezone(sambat.UTC)
sambat.datetime(2083, 6, 15, 3, 45, tzinfo=datetime.timezone.utc)

Calendars

sambat.calendar mirrors the standard library’s calendar module:

>>> from sambat import calendar
>>> print(calendar.month(2083, 6))
    Ashwin 2083
Mo Tu We Th Fr Sa Su
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31


DualTextCalendar prints the Gregorian day next to each BS day, the way Nepali wall calendars do. The command line exposes it as sambat cal --dual.