Date, parsing & validation
The Date type, constructing dates, getting today's date, and validating year/month/day combinations.
type Date struct { Year, Month, Day int }A Bikram Sambat calendar date. Month is 1-based — 1 is Baisakh, 12 is Chaitra. A Date zero
value or one built directly from a struct literal isn't guaranteed valid unless constructed with
NewDate or returned by this package.
const MinBSYear = 1979
const MaxBSYear = 2100The inclusive bounds of the BS years this package supports, corresponding to the Gregorian range
1922-04-13 to 2044-04-13. Referenced throughout this reference as MinBSYear..MaxBSYear.
func NewDate(year, month, day int) (Date, error)Constructs and validates a Date. Returns an error wrapping ErrInvalidYear, ErrInvalidMonth
or ErrInvalidDay if the components don't form a real Bikram Sambat calendar date in the
supported range.
func Parse(s string) (Date, error)Parses a date in "YYYY-MM-DD" format — the same format Date.String produces. Returns an error
wrapping ErrInvalidFormat if s isn't shaped like a date, or the usual validation errors if
it's shaped correctly but not a real date.
func MustParse(s string) DateLike Parse, but panics instead of returning an error. Meant for cases like package-level
variable initialization with a literal, known-good date string — most callers should use Parse.
func TodayBS() (Date, error)Returns today's date in Nepal, converted to Bikram Sambat. Returns an error wrapping
ErrOutOfRange if today's date falls outside the supported range — i.e. this code running
before MinBSYear or after MaxBSYear's corresponding Gregorian date.
TodayBS always means today in Nepal (UTC+05:45), not wherever the calling process happens
to be running — it ignores the server's configured timezone entirely. This matters because cloud
VMs and containers commonly default to UTC: for roughly 5h45m of every day, Nepal has already
moved into the next calendar day while a UTC server hasn't, so a naive time.Now()-based
implementation would report yesterday's BS date as "today" for part of every day. TodayBS
accounts for this so callers don't have to.
func (d Date) Valid() boolReports whether d is a real Bikram Sambat calendar date in the supported range.
func (d Date) String() string // "YYYY-MM-DD"Formats d as an ISO-like string, zero-padded.
Validation
func IsValid(year, month, day int) boolReports whether year, month and day form a real Bikram Sambat calendar date within the supported range — checked against the actual number of days in that month, not just a generic 1–31 shape check.
func IsSupportedBSYear(year int) boolReports whether year is within MinBSYear..MaxBSYear.
func DaysInMonth(year, month int) (int, error)Returns the number of days in the given Bikram Sambat month (29, 30, 31 or 32, depending on the
year and month). Returns an error wrapping ErrInvalidYear or ErrInvalidMonth if out of range.
func DaysInYear(year int) (int, error)Returns the total number of days in the given Bikram Sambat year (364–367, depending on the
year). Returns an error wrapping ErrInvalidYear if out of range.
Example
d, err := bs.NewDate(2083, 6, 6)
d2, err := bs.Parse("2083-06-06")
// d == d2
birthday := bs.MustParse("2060-06-15") // panics if malformed — use a literal only
today, err := bs.TodayBS()
fmt.Println(d.String()) // "2083-06-06"
fmt.Println(d.Valid()) // true
bs.IsValid(2083, 9, 32) // false — Poush 2083 only has 30 days
bs.IsSupportedBSYear(2101) // false — outside MinBSYear..MaxBSYear
days, _ := bs.DaysInMonth(2083, 6) // 31
total, _ := bs.DaysInYear(2083) // 365MustParse panics on invalid input — only use it with a compile-time-known literal string,
never with user input or anything from an external source. Use Parse for that.