UNPKG

@subrotosaha/bangla-date

Version:

A simple utility package for string manipulation in JavaScript.

285 lines (261 loc) 7.62 kB
type NumberInWords = { [key: number]: string; }; type NumbersInWords = { en: NumberInWords; bn: NumberInWords; hi: NumberInWords; }; export const numberToWords = (num: number, language: keyof NumbersInWords = "en") => { const numbersInWords: NumbersInWords = { en: { 0: "zero", 1: "one", 2: "two", 3: "three", 4: "four", 5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine", 10: "ten", 11: "eleven", 12: "twelve", 13: "thirteen", 14: "fourteen", 15: "fifteen", 16: "sixteen", 17: "seventeen", 18: "eighteen", 19: "nineteen", 20: "twenty", 30: "thirty", 40: "forty", 50: "fifty", 60: "sixty", 70: "seventy", 80: "eighty", 90: "ninety", 100: "hundred", 1000: "thousand", }, bn: { 0: "শূন্য", 1: "এক", 2: "দুই", 3: "তিন", 4: "চার", 5: "পাঁচ", 6: "ছয়", 7: "সাত", 8: "আট", 9: "নয়", 10: "দশ", 11: "এগারো", 12: "বারো", 13: "তেরো", 14: "চোদ্দো", 15: "পনেরো", 16: "ষোলো", 17: "সতেরো", 18: "আঠারো", 19: "উনিশ", 20: "বিশ", 30: "ত্রিশ", 40: "চল্লিশ", 50: "পঞ্চাশ", 60: "ষাট", 70: "সত্তর", 80: "আশি", 90: "নব্বই", 100: "শত", 1000: "হাজার", }, hi: { 0: "शून्य", 1: "एक", 2: "दो", 3: "तीन", 4: "चार", 5: "पाँच", 6: "छह", 7: "सात", 8: "आठ", 9: "नौ", 10: "दस", 11: "ग्यारह", 12: "बारह", 13: "तेरह", 14: "चौदह", 15: "पंद्रह", 16: "सोलह", 17: "सत्रह", 18: "अठारह", 19: "उन्नीस", 20: "बीस", 30: "तीस", 40: "चालीस", 50: "पचास", 60: "साठ", 70: "सत्तर", 80: "अस्सी", 90: "नब्बे", 100: "सौ", 1000: "हज़ार", }, }; // Helper function to convert number to words for numbers below 100 const convertBelowHundred = ( num: number, language: keyof typeof numbersInWords ) => { if (num <= 20) { return numbersInWords[language][num]; } const tens = Math.floor(num / 10) * 10; const ones = num % 10; return ones ? `${numbersInWords[language][tens]} ${numbersInWords[language][ones]}` : numbersInWords[language][tens]; }; // Helper function to convert number to words for numbers below 1000 const convertBelowThousand = (num:number, language: keyof typeof numbersInWords) => { if (num < 100) return convertBelowHundred(num, language); const hundreds = Math.floor(num / 100); const remainder = num % 100; // In Bengali and Hindi, "শত" or "सौ" are used for hundreds const hundredWord = language === "bn" ? `${numbersInWords[language][hundreds]}শ` : `${numbersInWords[language][hundreds]}सौ`; return remainder ? `${hundredWord} ${convertBelowHundred(remainder, language)}` : hundredWord; }; if (num === 0) return numbersInWords[language][0]; if (num < 1000) return convertBelowThousand(num, language); // For numbers 1000 and above, handle thousands const thousands = Math.floor(num / 1000); const remainder = num % 1000; return remainder ? `${convertBelowThousand(thousands, language)} ${ numbersInWords[language][1000] } ${convertBelowThousand(remainder, language)}` : `${convertBelowThousand(thousands, language)} ${ numbersInWords[language][1000] }`; }; export const numberToNumber = ( num: number|string, language: keyof NumbersInWords = "en" ) => { const numbersInNumber: NumbersInWords = { en: { 0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9", }, bn: { 0: "০", 1: "১", 2: "২", 3: "৩", 4: "৪", 5: "৫", 6: "৬", 7: "৭", 8: "৮", 9: "৯", }, hi: { 0: "०", 1: "१", 2: "२", 3: "३", 4: "४", 5: "५", 6: "६", 7: "७", 8: "८", 9: "९", }, }; return num.toString().replace( /\d/g, (digit) => numbersInNumber[language][parseInt(digit)] ); }; export function formatBanglaDateToMatchTemplate( banglaDateStr: string, // e.g. "1431-12-30 13:39:24.403 UTC" templateStr: string // e.g. "04/12/2025, 1:39:24 PM" or "4/12/2025" ): string { // 1. Extract Bangla calendar date const [banglaDatePart, timePartRaw] = banglaDateStr.split(" "); // "1431-12-30", "13:39:24.403" const [year, month, day] = banglaDatePart.split("-"); if (!year || !month || !day) throw new Error("Invalid Bangla date"); // 2. Try to extract timezone (optional) const timezoneRegex = /(GMT[+-]?\d+|UTC|PST|EST|CET|BST)/i; const tzMatch = templateStr.match(timezoneRegex); const zoneLabel = tzMatch ? tzMatch[1].toUpperCase() : "UTC"; // fallback to UTC const timeZoneOffsets: Record<string, number> = { UTC: 0, GMT: 0, PST: -8, EST: -5, CET: 1, BST: 6, }; let offsetHours = 0; if (zoneLabel.startsWith("GMT") && /[+-]\d+/.test(zoneLabel)) { offsetHours = parseInt(zoneLabel.replace("GMT", "")); } else if (zoneLabel in timeZoneOffsets) { offsetHours = timeZoneOffsets[zoneLabel]; } else { offsetHours = 0; // unknown zone, fallback to UTC } // 3. Extract time from BanglaDate string const timePart = timePartRaw?.split(".")[0]; // "13:39:24" if (!timePart) throw new Error("Missing time in Bangla date"); const [h, m, s] = timePart.split(":").map(Number); if ([h, m, s].some(isNaN)) throw new Error("Invalid time format"); const utcDate = new Date(Date.UTC(2000, 0, 1, h, m, s)); // dummy date in UTC const localDate = new Date(utcDate.getTime() + offsetHours * 60 * 60 * 1000); // 4. Extract template type (date, time, or datetime) const isTimeOnly = /(\d{1,2}):(\d{2}):(\d{2})\s*(AM|PM)?/i.test(templateStr); const isDateOnly = /\d{1,2}\/\d{1,2}\/\d{4}/.test(templateStr) || /\d{1,2}-\d{1,2}-\d{4}/.test(templateStr); // 5. Format time if template requires time let formattedTime = ""; if (isTimeOnly || !isDateOnly) { let hour = localDate.getUTCHours(); const minute = localDate.getUTCMinutes().toString().padStart(2, "0"); const second = localDate.getUTCSeconds().toString().padStart(2, "0"); const ampm = hour >= 12 ? "PM" : "AM"; hour = hour % 12 || 12; formattedTime = `${hour}:${minute}:${second} ${ampm}`; } // 6. Format date if template requires date let formattedDate = ""; if (isDateOnly || !isTimeOnly) { formattedDate = `${month}/${day}/${year}`; } // 7. Combine date and time parts based on the template if (isDateOnly && isTimeOnly) { return `${formattedDate}, ${formattedTime} ${zoneLabel}`; } else if (isDateOnly) { return formattedDate; } else if (isTimeOnly) { return `${formattedTime} ${zoneLabel}`; } else { return `${formattedDate} ${formattedTime} ${zoneLabel}`; } }