Arithmetic & ranges
Adding/subtracting days and months, comparing spans, and finding month/year boundaries.
Days
func (d Date) AddDays(n int) (Date, error)Returns the date n calendar days after d (or before, if n is negative). Returns an error
wrapping ErrInvalidYear/ErrInvalidMonth/ErrInvalidDay if d itself is invalid, or
ErrOutOfRange if the result falls outside the supported range.
func (d Date) SubDays(n int) (Date, error)Returns the date n calendar days before d. Same errors as AddDays.
func (d Date) NextDay() (Date, error)The day after d — a thin wrapper over AddDays(1).
func (d Date) PreviousDay() (Date, error)The day before d — a thin wrapper over SubDays(1).
func (d Date) DayOfWeek() (time.Weekday, error)The day of the week d falls on, derived through its equivalent Gregorian date.
func DaysBetween(a, b Date) (int, error)The number of calendar days from a to b: positive if b is after a, negative if b is before a, zero if equal.
d, _ := bs.NewDate(2083, 6, 6)
next, _ := d.AddDays(10) // 2083-06-16
prev, _ := d.SubDays(10) // 2083-05-27
nd, _ := d.NextDay() // 2083-06-07
pd, _ := d.PreviousDay() // 2083-06-05
weekday, _ := d.DayOfWeek() // Tuesday
other, _ := bs.NewDate(2083, 6, 16)
diff, _ := bs.DaysBetween(d, other) // 10Months
func (d Date) NextMonth() (Date, error)The date one Bikram Sambat month after d, in the same day-of-month — clamped to the target month's last day if it's shorter, rather than rolling over into the month after. Returns the usual validation errors for an invalid receiver.
func (d Date) PreviousMonth() (Date, error)The date one Bikram Sambat month before d, with the same clamping behavior as NextMonth.
This clamping is deliberate. Go's own time.Time.AddDate(0, 1, 0) has a well-known gotcha where
Jan 31 + one month rolls into March, since February doesn't have 31 days. NextMonth/PreviousMonth
avoid that: day 32 in a 32-day month becomes day 31 in a 31-day target month, not day 1 of the
month after.
d, _ := bs.NewDate(2083, 6, 6)
next, _ := d.NextMonth() // 2083-07-06
prev, _ := d.PreviousMonth() // 2083-05-06
// Ashadh (month 3) 2083 has 32 days; Shrawan (month 4) has only 31.
last, _ := bs.NewDate(2083, 3, 32)
clamped, _ := last.NextMonth() // 2083-04-31, not 2083-05-01Month and year boundaries
func (d Date) StartOfMonth() (Date, error)Day 1 of d's month.
func (d Date) EndOfMonth() (Date, error)The last day of d's month.
func (d Date) StartOfYear() (Date, error)Baisakh 1 of d's year.
func (d Date) EndOfYear() (Date, error)The last day of Chaitra of d's year.
func (d Date) DayOfYear() (int, error)d's 1-based ordinal day within its year (1 for Baisakh 1, up to 365 or 366 for the last day of Chaitra).
d, _ := bs.NewDate(2083, 6, 6)
som, _ := d.StartOfMonth() // 2083-06-01
eom, _ := d.EndOfMonth() // 2083-06-31
soy, _ := d.StartOfYear() // 2083-01-01
eoy, _ := d.EndOfYear() // 2083-12-30 (Chaitra 2083 has 30 days)
day, _ := d.DayOfYear() // 162Age
func Age(birthBS, todayBS Date) (years, months, days int, err error)Computes calendar age from birthBS to todayBS (see TodayBS) — real Y/M/D calendar math with
month/day borrowing, not just a raw day count divided by 365. Returns an error wrapping
ErrInvalidDateOrder if birthBS is after todayBS.
birth := bs.MustParse("2060-06-15")
today := bs.MustParse("2083-06-06") // 9 days before the 23rd birthday
years, months, days, err := bs.Age(birth, today)
// years == 22, months == 11, days == 22