bangla-date-utils
Version:
A utility package for converting and formatting dates in the Bangla calendar system with support for Bangla numerals.
409 lines (385 loc) • 12.2 kB
text/typescript
// Constants for Bangla calendar
export const BANGLA_MONTHS = [
"বৈশাখ", // Boishakh
"জ্যৈষ্ঠ", // Jyoishtho
"আষাঢ়", // Asharh
"শ্রাবণ", // Shrabon
"ভাদ্র", // Bhadro
"আশ্বিন", // Ashwin
"কার্তিক", // Kartik
"অগ্রহায়ণ", // Ogrohayon
"পৌষ", // Poush
"মাঘ", // Magh
"ফাল্গুন", // Falgun
"চৈত্র", // Choitro
]
export const BANGLA_SEASONS = [
"গ্রীষ্ম", // Grishmo (Summer)
"বর্ষা", // Borsha (Rainy)
"শরৎ", // Shorot (Autumn)
"হেমন্ত", // Hemonto (Late Autumn)
"শীত", // Sheet (Winter)
"বসন্ত", // Boshonto (Spring)
]
export const BANGLA_WEEKDAYS = [
"রবিবার", // Sunday
"সোমবার", // Monday
"মঙ্গলবার", // Tuesday
"বুধবার", // Wednesday
"বৃহস্পতিবার", // Thursday
"শুক্রবার", // Friday
"শনিবার", // Saturday
]
// Bangla date structure
export interface BanglaDate {
year: number
month: number // 1-12
date: number // 1-31
monthName: string
season: string
}
/**
* Determines if the given Bangla year is a leap year
* @param year Bangla year
* @returns boolean indicating if it's a leap year
*/
export const isBanglaLeapYear = (year: number): boolean => {
// Convert Bangla year to Gregorian year (approximate)
const gregorianYear = year - 593
// Gregorian leap year calculation
return (gregorianYear % 4 === 0 && gregorianYear % 100 !== 0) || gregorianYear % 400 === 0
}
/**
* Get the number of days in a Bangla month
* @param month Bangla month (1-12)
* @param year Bangla year
* @returns number of days in the month
*/
export const getDaysInBanglaMonth = (month: number, year: number): number => {
// Bangla months have either 30 or 31 days
// Falgun (11th month) has 29 days in non-leap years and 30 days in leap years
if (month === 11) {
return isBanglaLeapYear(year) ? 30 : 29
}
// Chaitra (12th month) has 30 days
if (month === 12) {
return 30
}
// Other months alternate between 31 and 30 days
return month % 2 === 1 ? 31 : 30
}
/**
* Convert Gregorian date to Bangla date
* @param date Gregorian date
* @returns BanglaDate object
*/
export const convertGregorianToBangla = (date: Date): BanglaDate => {
const gregorianDate = date.getDate()
const gregorianMonth = date.getMonth() + 1 // 1-12
const gregorianYear = date.getFullYear()
let banglaDate: number
let banglaMonth: number
let banglaYear: number
// Bangla new year starts around April 14
// This is a simplified calculation - a more accurate one would account for leap years
if (gregorianMonth < 4 || (gregorianMonth === 4 && gregorianDate < 14)) {
// Jan to mid-April: Bangla year is Gregorian year - 594
banglaYear = gregorianYear - 594
} else {
// Mid-April to Dec: Bangla year is Gregorian year - 593
banglaYear = gregorianYear - 593
}
// Approximate mapping of Gregorian to Bangla dates
// This is a simplified version - a more accurate version would use astronomical calculations
if (gregorianMonth === 4) {
// April
if (gregorianDate < 14) {
banglaMonth = 12 // Chaitra
banglaDate = gregorianDate + 17
} else {
banglaMonth = 1 // Boishakh
banglaDate = gregorianDate - 13
}
} else if (gregorianMonth === 5) {
// May
if (gregorianDate < 15) {
banglaMonth = 1 // Boishakh
banglaDate = gregorianDate + 17
} else {
banglaMonth = 2 // Jyoishtho
banglaDate = gregorianDate - 14
}
} else if (gregorianMonth === 6) {
// June
if (gregorianDate < 15) {
banglaMonth = 2 // Jyoishtho
banglaDate = gregorianDate + 17
} else {
banglaMonth = 3 // Asharh
banglaDate = gregorianDate - 14
}
} else if (gregorianMonth === 7) {
// July
if (gregorianDate < 16) {
banglaMonth = 3 // Asharh
banglaDate = gregorianDate + 16
} else {
banglaMonth = 4 // Shrabon
banglaDate = gregorianDate - 15
}
} else if (gregorianMonth === 8) {
// August
if (gregorianDate < 16) {
banglaMonth = 4 // Shrabon
banglaDate = gregorianDate + 16
} else {
banglaMonth = 5 // Bhadro
banglaDate = gregorianDate - 15
}
} else if (gregorianMonth === 9) {
// September
if (gregorianDate < 16) {
banglaMonth = 5 // Bhadro
banglaDate = gregorianDate + 16
} else {
banglaMonth = 6 // Ashwin
banglaDate = gregorianDate - 15
}
} else if (gregorianMonth === 10) {
// October
if (gregorianDate < 16) {
banglaMonth = 6 // Ashwin
banglaDate = gregorianDate + 15
} else {
banglaMonth = 7 // Kartik
banglaDate = gregorianDate - 15
}
} else if (gregorianMonth === 11) {
// November
if (gregorianDate < 15) {
banglaMonth = 7 // Kartik
banglaDate = gregorianDate + 16
} else {
banglaMonth = 8 // Ogrohayon
banglaDate = gregorianDate - 14
}
} else if (gregorianMonth === 12) {
// December
if (gregorianDate < 15) {
banglaMonth = 8 // Ogrohayon
banglaDate = gregorianDate + 16
} else {
banglaMonth = 9 // Poush
banglaDate = gregorianDate - 14
}
} else if (gregorianMonth === 1) {
// January
if (gregorianDate < 14) {
banglaMonth = 9 // Poush
banglaDate = gregorianDate + 17
} else {
banglaMonth = 10 // Magh
banglaDate = gregorianDate - 13
}
} else if (gregorianMonth === 2) {
// February
if (gregorianDate < 13) {
banglaMonth = 10 // Magh
banglaDate = gregorianDate + 18
} else {
banglaMonth = 11 // Falgun
banglaDate = gregorianDate - 12
}
} else {
// March
if (gregorianDate < 15) {
banglaMonth = 11 // Falgun
banglaDate = gregorianDate + 16
} else {
banglaMonth = 12 // Chaitra
banglaDate = gregorianDate - 14
}
}
// Get season based on Bangla month
let seasonIndex = Math.floor((banglaMonth - 1) / 2)
if (seasonIndex > 5) seasonIndex = 5
return {
year: banglaYear,
month: banglaMonth,
date: banglaDate,
monthName: BANGLA_MONTHS[banglaMonth - 1],
season: BANGLA_SEASONS[seasonIndex],
}
}
/**
* Convert Bangla date to Gregorian date
* @param banglaDate Bangla date (day)
* @param banglaMonth Bangla month (1-12)
* @param banglaYear Bangla year
* @returns JavaScript Date object
*/
export const convertBanglaToGregorian = (banglaDate: number, banglaMonth: number, banglaYear: number): Date => {
let gregorianYear = banglaYear + 593
let gregorianMonth = 0 // 0-11 for JavaScript Date
let gregorianDate = 0
// Approximate mapping of Bangla to Gregorian dates
// This is a simplified version - a more accurate version would use astronomical calculations
if (banglaMonth === 1) {
// Boishakh (mid-April to mid-May)
if (banglaDate <= 18) {
gregorianMonth = 3 // April
gregorianDate = banglaDate + 13
} else {
gregorianMonth = 4 // May
gregorianDate = banglaDate - 18
}
} else if (banglaMonth === 2) {
// Jyoishtho (mid-May to mid-June)
if (banglaDate <= 17) {
gregorianMonth = 4 // May
gregorianDate = banglaDate + 14
} else {
gregorianMonth = 5 // June
gregorianDate = banglaDate - 17
}
} else if (banglaMonth === 3) {
// Asharh (mid-June to mid-July)
if (banglaDate <= 16) {
gregorianMonth = 5 // June
gregorianDate = banglaDate + 14
} else {
gregorianMonth = 6 // July
gregorianDate = banglaDate - 16
}
} else if (banglaMonth === 4) {
// Shrabon (mid-July to mid-August)
if (banglaDate <= 16) {
gregorianMonth = 6 // July
gregorianDate = banglaDate + 15
} else {
gregorianMonth = 7 // August
gregorianDate = banglaDate - 16
}
} else if (banglaMonth === 5) {
// Bhadro (mid-August to mid-September)
if (banglaDate <= 16) {
gregorianMonth = 7 // August
gregorianDate = banglaDate + 15
} else {
gregorianMonth = 8 // September
gregorianDate = banglaDate - 16
}
} else if (banglaMonth === 6) {
// Ashwin (mid-September to mid-October)
if (banglaDate <= 15) {
gregorianMonth = 8 // September
gregorianDate = banglaDate + 15
} else {
gregorianMonth = 9 // October
gregorianDate = banglaDate - 15
}
} else if (banglaMonth === 7) {
// Kartik (mid-October to mid-November)
if (banglaDate <= 16) {
gregorianMonth = 9 // October
gregorianDate = banglaDate + 15
} else {
gregorianMonth = 10 // November
gregorianDate = banglaDate - 16
}
} else if (banglaMonth === 8) {
// Ogrohayon (mid-November to mid-December)
if (banglaDate <= 15) {
gregorianMonth = 10 // November
gregorianDate = banglaDate + 14
} else {
gregorianMonth = 11 // December
gregorianDate = banglaDate - 15
}
} else if (banglaMonth === 9) {
// Poush (mid-December to mid-January)
if (banglaDate <= 16) {
gregorianMonth = 11 // December
gregorianDate = banglaDate + 14
} else {
gregorianMonth = 0 // January
gregorianDate = banglaDate - 16
gregorianYear += 1
}
} else if (banglaMonth === 10) {
// Magh (mid-January to mid-February)
if (banglaDate <= 18) {
gregorianMonth = 0 // January
gregorianDate = banglaDate + 13
} else {
gregorianMonth = 1 // February
gregorianDate = banglaDate - 18
}
} else if (banglaMonth === 11) {
// Falgun (mid-February to mid-March)
if (banglaDate <= 16) {
gregorianMonth = 1 // February
gregorianDate = banglaDate + 12
} else {
gregorianMonth = 2 // March
gregorianDate = banglaDate - 16
}
} else {
// Chaitra (mid-March to mid-April)
if (banglaDate <= 17) {
gregorianMonth = 2 // March
gregorianDate = banglaDate + 14
} else {
gregorianMonth = 3 // April
gregorianDate = banglaDate - 17
}
}
return new Date(gregorianYear, gregorianMonth, gregorianDate)
}
/**
* Get the Bangla weekday name for a given date
* @param date JavaScript Date object
* @returns Bangla weekday name
*/
export const getBanglaWeekday = (date: Date): string => {
const dayIndex = date.getDay() // 0-6, where 0 is Sunday
return BANGLA_WEEKDAYS[dayIndex]
}
/**
* Get the current Bangla date
* @returns BanglaDate object for the current date
*/
export const getCurrentBanglaDate = (): BanglaDate => {
return convertGregorianToBangla(new Date())
}
/**
* Format a Bangla date as a string
* @param banglaDate BanglaDate object
* @param format Format string (e.g., 'full', 'medium', 'short')
* @returns Formatted Bangla date string
*/
export const formatBanglaDateString = (
banglaDate: BanglaDate,
format: "full" | "medium" | "short" = "medium",
): string => {
const { date, month, year, monthName, season } = banglaDate
// Convert numbers to Bangla numerals
const banglaNumerals = ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"]
const toBanglaNumerals = (num: number) => {
return num
.toString()
.split("")
.map((digit) => banglaNumerals[Number.parseInt(digit)])
.join("")
}
const banglaDateNum = toBanglaNumerals(date)
const banglaYear = toBanglaNumerals(year)
if (format === "full") {
return `${banglaDateNum} ${monthName} ${banglaYear} (${season})`
} else if (format === "short") {
return `${banglaDateNum}/${toBanglaNumerals(month)}/${banglaYear}`
} else {
// medium format
return `${banglaDateNum} ${monthName} ${banglaYear}`
}
}