UNPKG

@subrotosaha/bangla-date

Version:

A simple utility package for string manipulation in JavaScript.

660 lines (659 loc) 27.4 kB
import { formatBanglaDateToMatchTemplate, numberToNumber, } from "../utils/index.js"; class BanglaDate { constructor(gregorianDate, language = "en") { this.language = language; this.gregorianDate = new Date(gregorianDate.getTime()); const gYear = this.gregorianDate.getUTCFullYear(); const pohelaBoishakh = new Date(Date.UTC(gYear, 3, 14)); const isBeforePohelaBoishakh = this.gregorianDate.getTime() < pohelaBoishakh.getTime(); this.banglaYear = (isBeforePohelaBoishakh ? gYear - 1 : gYear) - 593; const refYear = isBeforePohelaBoishakh ? gYear - 1 : gYear; const refDate = new Date(Date.UTC(refYear, 3, 14)); const dayDiff = Math.floor((this.gregorianDate.getTime() - refDate.getTime()) / (1000 * 60 * 60 * 24)); const monthLengths = [ 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, BanglaDate.isLeapYear(refYear + 1) ? 30 : 29, // Falgun leap handling 30, ]; let remainingDays = dayDiff; let monthIndex = 0; while (monthIndex < 12 && remainingDays >= monthLengths[monthIndex]) { remainingDays -= monthLengths[monthIndex]; monthIndex++; } this.banglaMonthIndex = monthIndex; this.banglaDay = remainingDays + 1; this.date = numberToNumber(`${this.banglaYear}-${this.banglaMonthIndex + 1}-${this.banglaDay} ${this.gregorianDate.getHours()}:${this.gregorianDate.getMinutes()}:${this.gregorianDate.getSeconds()}.${this.gregorianDate.getMilliseconds()} ${this.language === "bn" ? "সার্বজনীন সময়" : this.language === "hi" ? "सार्वभौमिक समय" : "UTC"}`, this.language); } // **Static Methods**: now() { return this.date; } parse(dateString) { const [day, monthName, yearWithBS] = dateString.split(" "); const banglaMonthNames = { Boishakh: 0, Jyoishtho: 1, Asharh: 2, Shrabon: 3, Bhadro: 4, Ashwin: 5, Kartik: 6, Ogrohayon: 7, Poush: 8, Magh: 9, Falgun: 10, Chaitra: 11, }; const monthIndex = banglaMonthNames[monthName]; const dayOfMonth = parseInt(day); const yearInBS = parseInt(yearWithBS); const gregorianYear = yearInBS + 593; const pohelaBoishakh = new Date(Date.UTC(gregorianYear, 3, 14)); const monthLengths = [ 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, BanglaDate.isLeapYear(gregorianYear + 1) ? 30 : 29, 30, ]; let dayOffset = 0; for (let i = 0; i < monthIndex; i++) { dayOffset += monthLengths[i]; } dayOffset += dayOfMonth - 1; const gDate = new Date(pohelaBoishakh.getTime() + dayOffset * (1000 * 60 * 60 * 24)); const banglaDate = new BanglaDate(gDate, this.language); return banglaDate.date; } static isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } // **Accessor Methods**: getDate() { switch (this.language) { case "bn": return numberToNumber(this.banglaDay, "bn"); // Gregorian date case "hi": return numberToNumber(this.banglaDay, "hi"); // Bengali date default: return this.banglaDay.toString(); // Default to Bengali date for unsupported languages } } getDay() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getDay(), "bn"); // Bengali day case "hi": return numberToNumber(this.gregorianDate.getDay(), "hi"); // Sanskrit day default: return this.gregorianDate.getDay().toString(); // Default to Gregorian day for unsupported languages } } getFullYear() { switch (this.language) { case "bn": return numberToNumber(this.banglaYear, "bn"); // Bengali year case "hi": return numberToNumber(this.banglaYear, "hi"); // Sanskrit year default: return this.banglaYear.toString(); // Default to Bengali year for unsupported languages } } getHours() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getHours(), "bn"); // Bengali hours case "hi": return numberToNumber(this.gregorianDate.getHours(), "hi"); // Sanskrit hours default: return this.gregorianDate.getHours().toString(); // Default to Gregorian hours for unsupported languages } } getMilliseconds() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getMilliseconds(), "bn"); // Bengali milliseconds case "hi": return numberToNumber(this.gregorianDate.getMilliseconds(), "hi"); // Sanskrit milliseconds default: return this.gregorianDate.getMilliseconds().toString(); // Default to Gregorian milliseconds for unsupported languages } } getMinutes() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getMinutes(), "bn"); // Bengali minutes case "hi": return numberToNumber(this.gregorianDate.getMinutes(), "hi"); // Sanskrit minutes default: return this.gregorianDate.getMinutes().toString(); // Default to Gregorian minutes for unsupported languages } } getMonth() { switch (this.language) { case "bn": return numberToNumber(this.banglaMonthIndex + 1, "bn"); // Bengali month case "hi": return numberToNumber(this.banglaMonthIndex + 1, "hi"); // Sanskrit month default: return (this.banglaMonthIndex + 1).toString(); // Default to Bengali month for unsupported languages } } getSeconds() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getSeconds(), "bn"); // Bengali seconds case "hi": return numberToNumber(this.gregorianDate.getSeconds(), "hi"); // Sanskrit seconds default: return this.gregorianDate.getSeconds().toString(); // Default to Gregorian seconds for unsupported languages } } getTime() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getTime(), "bn"); // Bengali time case "hi": return numberToNumber(this.gregorianDate.getTime(), "hi"); // Sanskrit time default: return this.gregorianDate.getTime().toString(); // Default to Gregorian time for unsupported languages } } getTimezoneOffset() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getTimezoneOffset(), "bn"); // Bengali timezone offset case "hi": return numberToNumber(this.gregorianDate.getTimezoneOffset(), "hi"); // Sanskrit timezone offset default: return this.gregorianDate.getTimezoneOffset().toString(); // Default to Gregorian timezone offset for unsupported languages } } getUTCDate() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCDate(), "bn"); // Bengali UTC date case "hi": return numberToNumber(this.gregorianDate.getUTCDate(), "hi"); // Sanskrit UTC date default: return this.gregorianDate.getUTCDate().toString(); // Default to Gregorian UTC date for unsupported languages } } getUTCDay() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCDay(), "bn"); // Bengali UTC day case "hi": return numberToNumber(this.gregorianDate.getUTCDay(), "hi"); // Sanskrit UTC day default: return this.gregorianDate.getUTCDay().toString(); // Default to Gregorian UTC day for unsupported languages } } getUTCFullYear() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCFullYear(), "bn"); // Bengali UTC full year case "hi": return numberToNumber(this.gregorianDate.getUTCFullYear(), "hi"); // Sanskrit UTC full year default: return this.gregorianDate.getUTCFullYear().toString(); // Default to Gregorian UTC full year for unsupported languages } } getUTCHours() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCHours(), "bn"); // Bengali UTC hours case "hi": return numberToNumber(this.gregorianDate.getUTCHours(), "hi"); // Sanskrit UTC hours default: return this.gregorianDate.getUTCHours().toString(); // Default to Gregorian UTC hours for unsupported languages } } getUTCMilliseconds() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCMilliseconds(), "bn"); // Bengali UTC milliseconds case "hi": return numberToNumber(this.gregorianDate.getUTCMilliseconds(), "hi"); // Sanskrit UTC milliseconds default: return this.gregorianDate.getUTCMilliseconds().toString(); // Default to Gregorian UTC milliseconds for unsupported languages } } getUTCMinutes() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCMinutes(), "bn"); // Bengali UTC minutes case "hi": return numberToNumber(this.gregorianDate.getUTCMinutes(), "hi"); // Sanskrit UTC minutes default: return this.gregorianDate.getUTCMinutes().toString(); // Default to Gregorian UTC minutes for unsupported languages } } getUTCMonth() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCMonth(), "bn"); // Bengali UTC month case "hi": return numberToNumber(this.gregorianDate.getUTCMonth(), "hi"); // Sanskrit UTC month default: return this.gregorianDate.getUTCMonth().toString(); // Default to Gregorian UTC month for unsupported languages } } getUTCSeconds() { switch (this.language) { case "bn": return numberToNumber(this.gregorianDate.getUTCSeconds(), "bn"); // Bengali UTC seconds case "hi": return numberToNumber(this.gregorianDate.getUTCSeconds(), "hi"); // Sanskrit UTC seconds default: return this.gregorianDate.getUTCSeconds().toString(); // Default to Gregorian UTC seconds for unsupported languages } } getYear() { switch (this.language) { case "bn": return numberToNumber(this.banglaYear, "bn"); // Bengali year case "hi": return numberToNumber(this.banglaYear, "hi"); // Sanskrit year default: return (this.gregorianDate.getFullYear() - 1900).toString(); } } // **Formatted Output**: getMonthName() { const monthNames = { en: [ "Boishakh", "Jyoishtho", "Asharh", "Shrabon", "Bhadro", "Ashwin", "Kartik", "Ogrohayon", "Poush", "Magh", "Falgun", "Chaitra", ], bn: [ "বৈশাখ", "জ্যৈষ্ঠ", "আষাঢ়", "শ্রাবণ", "ভাদ্র", "আশ্বিন", "কার্তিক", "অগ্রহায়ণ", "পৌষ", "মাঘ", "ফাল্গুন", "চৈত্র", ], hi: [ "बैशाख", "ज्येष्ठ", "आषाढ", "श्रावण", "भाद्रपद", "आश्विन", "कार्तिक", "अग्राहयण", "पौष", "माघ", "फाल्गुन", "चैत", ], }; return monthNames[this.language][this.banglaMonthIndex]; } getWeekDay() { const weekDays = { en: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ], bn: [ "রবিবার", "সোমবার", "মঙ্গলবার", "বুধবার", "বৃহস্পতিবার", "শুক্রবার", "শনিবার", ], hi: [ "रविवार", "सोमवार", "मंगलवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार", ], }; const gDay = this.gregorianDate.getDay(); return weekDays[this.language][gDay]; } // **toLocaleString() with language formatting**: toLocaleDateString(locales, options) { // If no locales are provided, fall back to the object's language const currentLocale = locales !== null && locales !== void 0 ? locales : this.language; // Supported locales prefixes: "en", "bn", "hi", and their variants (like "en-US", "bn-BD", "hi-IN") const validLocales = ["en", "bn", "hi"]; // Check if the provided locale is a string (or array of strings) const isValidLocale = Array.isArray(currentLocale) ? currentLocale.some((locale) => validLocales.some((valid) => locale.startsWith(valid))) : validLocales.some((valid) => currentLocale.startsWith(valid)); if (!isValidLocale) { throw new Error(`Locale ${currentLocale} is not supported. Supported locales are: ${validLocales.join(", ")}, or any variant of them (e.g., en-US, bn-BD, hi-IN).`); } // Define digit maps for supported locales const digitsMap = { en: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], bn: ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"], hi: ["०", "१", "२", "३", "४", "५", "६", "७", "८", "९"], }; const ampmMap = { en: ["AM", "PM", "GMT", "UTC", "PST", "EST", "CET", "BST"], bn: [ "পূর্বাহ্ণ", "অপরাহ্ণ", "জিএমটি", "ইউটিসি", "পিএসটি", "ইএসটি", "সিইটি", "বিএসটি", "জিএমটি", ], hi: [ "पूर्वाह्न", "अपराह्न", "जीएमटी", "यूटीसी", "पीएसटी", "ईएसटी", "सीईटी", "बीएसटी", "जीएमटी", ], }; // Helper function to localize digits based on the selected locale const localeKey = currentLocale .toString() .split("-")[0]; const localizeNumber = (num) => { return num .toString() .split("") .map((d) => { var _a; const digitIndex = parseInt(d, 10); return isNaN(digitIndex) ? d : (_a = digitsMap[localeKey][digitIndex]) !== null && _a !== void 0 ? _a : d; }) .join(""); }; // Format the date using the provided options const nDate = new BanglaDate(new Date(this.gregorianDate)).date; let formattedDate = formatBanglaDateToMatchTemplate(nDate, new Intl.DateTimeFormat(currentLocale.toString().includes("en") ? currentLocale : "en-US", options).format(this.gregorianDate)); // Localize the formatted date by replacing digits with the appropriate locale digits formattedDate = formattedDate .split("") .map((char) => (/\d/.test(char) ? localizeNumber(char) : char)) .join(""); formattedDate = formattedDate .split(" ") .map((word) => { // Normalize input by stripping periods and making uppercase const normalized = word.replace(/\./g, "").toUpperCase(); const index = ampmMap["en"].indexOf(normalized) > 0 ? ampmMap["en"].indexOf(normalized) : ampmMap["en"].indexOf(normalized.replace(/[^A-Za-z]/g, "")); if (index !== -1) { return (ampmMap[localeKey][index] + (localeKey !== "en" ? word.replace(/[A-Za-z]/g, "") : "")); } return word; // Return unchanged if no match }) .join(" "); //return new BanglaDate(new Date(formattedDate.split(", ")[0])).date; return formattedDate; } // Helper function to format numbers formatNumber(num) { return num.toString().padStart(2, "0"); } getAMPM(hour) { const h = parseInt(hour.toString(), 10); return h >= 12 ? this.language === "bn" ? "অপরাহ্ণ" : this.language === "hi" ? "अपराह्न" : "PM" : this.language === "bn" ? "পূর্বাহ্ণ" : this.language === "hi" ? "पूर्वाह्न" : "AM"; } // Main format function format(formatString) { const year = this.banglaYear; const month = this.banglaMonthIndex + 1; // Month index starts from 0 const day = this.banglaDay; const hours = this.getHours(); const minutes = this.getMinutes(); const seconds = this.getSeconds(); const replacements = { WWWW: this.getWeekDayFormat("long"), WWW: this.getWeekDayFormat("short"), WW: `0${this.gregorianDate.getDay().toString()}`, W: this.gregorianDate.getDay().toString(), era: this.language === "bn" ? "খ্রিস্টাব্দ" : "AD", YYYY: this.formatNumber(year), YY: this.formatNumber(year % 100), MMMM: this.getFormatedMonthName("long"), MMM: this.getFormatedMonthName("short"), MM: this.formatNumber(month), M: month.toString(), DD: this.formatNumber(day), D: day.toString(), HH: this.formatNumber(hours), H: hours.toString(), mm: this.formatNumber(minutes), m: minutes.toString(), ss: this.formatNumber(seconds), s: seconds.toString(), "AM/PM": this.getAMPM(hours), }; return numberToNumber(formatString.replace(/WWWW|WWW|WW|W|YYYY|YY|MMMM|MMM|MM|M|DD|D|HH|H|mm|m|ss|s|AM\/PM|era/g, (match) => replacements[match] || match), this.language); } // Function to get month name in Bangla getFormatedMonthName(format = "long") { const monthNames = { long: [ "বৈশাখ", "জ্যৈষ্ঠ", "আষাঢ়", "শ্রাবণ", "ভাদ্র", "আশ্বিন", "কার্তিক", "অগ্রাহায়ণ", "পৌষ", "মাঘ", "ফাল্গুন", "চৈত্র", ], short: [ "বৈশা", "জ্যৈ", "আষা", "শ্রা", "ভা", "আশ্বি", "কার", "অগ্র", "পৌ", "মা", "ফাল", "চৈ", ], }; return monthNames[format][this.banglaMonthIndex]; } toLocaleString(locales, options) { // If no locales are provided, fall back to the object's language const currentLocale = locales !== null && locales !== void 0 ? locales : this.language; // Supported locales prefixes: "en", "bn", "hi", and their variants (like "en-US", "bn-BD", "hi-IN") const validLocales = ["en", "bn", "hi"]; // Check if the provided locale is a string (or array of strings) const isValidLocale = Array.isArray(currentLocale) ? currentLocale.some((locale) => validLocales.some((valid) => locale.startsWith(valid))) : validLocales.some((valid) => currentLocale.startsWith(valid)); if (!isValidLocale) { throw new Error(`Locale ${currentLocale} is not supported. Supported locales are: ${validLocales.join(", ")}, or any variant of them (e.g., en-US, bn-BD, hi-IN).`); } // Define digit maps for supported locales const digitsMap = { en: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], bn: ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"], hi: ["०", "१", "२", "३", "४", "५", "६", "७", "८", "९"], }; const ampmMap = { en: ["AM", "PM", "GMT", "UTC", "PST", "EST", "CET", "BST"], bn: [ "পূর্বাহ্ণ", "অপরাহ্ণ", "জিএমটি", "ইউটিসি", "পিএসটি", "ইএসটি", "সিইটি", "বিএসটি", "জিএমটি", ], hi: [ "पूर्वाह्न", "अपराह्न", "जीएमटी", "यूटीसी", "पीएसटी", "ईएसटी", "सीईटी", "बीएसटी", "जीएमटी", ], }; // Helper function to localize digits based on the selected locale const localeKey = currentLocale .toString() .split("-")[0]; const localizeNumber = (num) => { return num .toString() .split("") .map((d) => { var _a; const digitIndex = parseInt(d, 10); return isNaN(digitIndex) ? d : (_a = digitsMap[localeKey][digitIndex]) !== null && _a !== void 0 ? _a : d; }) .join(""); }; // Format the date using the provided options const nDate = new BanglaDate(new Date(this.gregorianDate)).date; let formattedDate = formatBanglaDateToMatchTemplate(nDate, new Intl.DateTimeFormat(currentLocale.toString().includes("en") ? currentLocale : "en-US", options).format(this.gregorianDate)); // Localize the formatted date by replacing digits with the appropriate locale digits formattedDate = formattedDate .split("") .map((char) => (/\d/.test(char) ? localizeNumber(char) : char)) .join(""); formattedDate = formattedDate .split(" ") .map((word) => { // Normalize input by stripping periods and making uppercase const normalized = word.replace(/\./g, "").toUpperCase(); const index = ampmMap["en"].indexOf(normalized) > 0 ? ampmMap["en"].indexOf(normalized) : ampmMap["en"].indexOf(normalized.replace(/[^A-Za-z]/g, "")); if (index !== -1) { return (ampmMap[localeKey][index] + (localeKey !== "en" ? word.replace(/[A-Za-z]/g, "") : "")); } return word; // Return unchanged if no match }) .join(" "); //return new BanglaDate(new Date(formattedDate.split(", ")[0])).date; console.log(formattedDate); return formattedDate; } getWeekDayFormat(format = "long") { const weekDays = { long: { en: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ], bn: [ "রবিবার", "সোমবার", "মঙ্গলবার", "বুধবার", "বৃহস্পতিবার", "শুক্রবার", "শনিবার", ], hi: [ "रविवार", "सोमवार", "मंगलवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार", ], }, short: { en: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], bn: ["রবি", "সোম", "মঙ্গল", "বুধ", "বৃহঃ", "শুক্র", "শনি"], hi: ["रवि", "सोम", "मंगल", "बुध", "गुरु", "शुक्र", "शनि"], }, }; const gDay = this.gregorianDate.getDay(); return weekDays[format][this.language][gDay]; } } export default BanglaDate;