UNPKG

brahma-muhurat

Version:

High-precision Brahma Muhurat calculator for JavaScript and TypeScript

385 lines (337 loc) 9.74 kB
/** * Time utility functions for date/time handling and formatting */ const moment = require('moment-timezone'); const { DateTime } = require('luxon'); const _unusedDateTime = DateTime; // Referenced to avoid ESLint unused var warning /** * Parse various date input formats * @param {string|Date|moment} input - Date input in various formats * @returns {Date} Parsed date object */ function parseDateInput(input) { if (input instanceof Date) { return input; } if (moment.isMoment(input)) { return input.toDate(); } if (typeof input === 'string') { // Try various formats const formats = [ 'YYYY-MM-DD', 'YYYY-MM-DD HH:mm:ss', 'DD/MM/YYYY', 'MM/DD/YYYY', 'DD-MM-YYYY', 'YYYY/MM/DD' ]; for (const format of formats) { const parsed = moment(input, format, true); if (parsed.isValid()) { return parsed.toDate(); } } // Try ISO format and natural language parsing const parsed = moment(input); if (parsed.isValid()) { return parsed.toDate(); } } throw new Error(`Invalid date format: ${input}`); } /** * Format date/time for display * @param {Date} date - Date to format * @param {string} timezone - Target timezone * @param {string} format - Format string (optional) * @returns {string} Formatted date string */ function formatDateTime(date, timezone, format = 'YYYY-MM-DD HH:mm:ss z') { return moment(date).tz(timezone).format(format); } /** * Format time only (HH:mm:ss) * @param {Date} date - Date to format * @param {string} timezone - Target timezone * @returns {string} Formatted time string */ function formatTime(date, timezone) { return moment(date).tz(timezone).format('HH:mm:ss'); } /** * Format date only (YYYY-MM-DD) * @param {Date} date - Date to format * @param {string} timezone - Target timezone * @returns {string} Formatted date string */ function formatDate(date, timezone) { return moment(date).tz(timezone).format('YYYY-MM-DD'); } /** * Convert between timezones * @param {Date} date - Source date * @param {string} fromTimezone - Source timezone * @param {string} toTimezone - Target timezone * @returns {Date} Converted date */ function convertTimezone(date, fromTimezone, toTimezone) { return moment.tz(date, fromTimezone).tz(toTimezone).toDate(); } /** * Get timezone offset in minutes * @param {string} timezone - Timezone name * @param {Date} date - Date for which to get offset (optional) * @returns {number} Offset in minutes */ function getTimezoneOffset(timezone, date = new Date()) { return moment.tz(date, timezone).utcOffset(); } /** * Check if timezone is valid * @param {string} timezone - Timezone name to validate * @returns {boolean} True if valid timezone */ function isValidTimezone(timezone) { return !!moment.tz.zone(timezone); } /** * Get all available timezones * @returns {Array<string>} Array of timezone names */ function getSupportedTimezones() { return moment.tz.names(); } /** * Get timezones for a specific country * @param {string} countryCode - ISO country code (e.g., 'IN', 'US') * @returns {Array<string>} Array of timezone names for the country */ function getCountryTimezones(countryCode) { return moment.tz.names().filter(tz => tz.includes(countryCode.toUpperCase())); } /** * Get Indian timezones * @returns {Array<string>} Array of Indian timezone names */ function getIndianTimezones() { return [ 'Asia/Kolkata', 'Asia/Calcutta' // Legacy name ]; } /** * Calculate duration between two dates * @param {Date} startDate - Start date * @param {Date} endDate - End date * @param {string} unit - Unit for duration ('minutes', 'hours', 'days') * @returns {number} Duration in specified unit */ function calculateDuration(startDate, endDate, unit = 'minutes') { return moment(endDate).diff(moment(startDate), unit); } /** * Add time to a date * @param {Date} date - Base date * @param {number} amount - Amount to add * @param {string} unit - Unit ('minutes', 'hours', 'days', etc.) * @returns {Date} New date with time added */ function addTime(date, amount, unit) { return moment(date).add(amount, unit).toDate(); } /** * Subtract time from a date * @param {Date} date - Base date * @param {number} amount - Amount to subtract * @param {string} unit - Unit ('minutes', 'hours', 'days', etc.) * @returns {Date} New date with time subtracted */ function subtractTime(date, amount, unit) { return moment(date).subtract(amount, unit).toDate(); } /** * Get start of day for given date and timezone * @param {Date} date - Date * @param {string} timezone - Timezone * @returns {Date} Start of day */ function getStartOfDay(date, timezone) { return moment.tz(date, timezone).startOf('day').toDate(); } /** * Get end of day for given date and timezone * @param {Date} date - Date * @param {string} timezone - Timezone * @returns {Date} End of day */ function getEndOfDay(date, timezone) { return moment.tz(date, timezone).endOf('day').toDate(); } /** * Check if date is today in given timezone * @param {Date} date - Date to check * @param {string} timezone - Timezone * @returns {boolean} True if date is today */ function isToday(date, timezone) { const today = moment.tz(timezone); const checkDate = moment.tz(date, timezone); return today.isSame(checkDate, 'day'); } /** * Get day of year (1-366) * @param {Date} date - Date * @returns {number} Day of year */ function getDayOfYear(date) { return moment(date).dayOfYear(); } /** * Get week of year * @param {Date} date - Date * @returns {number} Week of year */ function getWeekOfYear(date) { return moment(date).week(); } /** * Check if year is leap year * @param {number} year - Year to check * @returns {boolean} True if leap year */ function isLeapYear(year) { return moment([year]).isLeapYear(); } /** * Get number of days in month * @param {Date} date - Date in the month * @returns {number} Number of days in month */ function getDaysInMonth(date) { return moment(date).daysInMonth(); } /** * Format duration in a human-readable way * @param {number} minutes - Duration in minutes * @returns {string} Human-readable duration */ function formatDuration(minutes) { const hours = Math.floor(minutes / 60); const mins = Math.round(minutes % 60); if (hours > 0) { return `${hours}h ${mins}m`; } else { return `${mins}m`; } } /** * Convert Julian Day Number to Date * @param {number} jdn - Julian Day Number * @returns {Date} Converted date */ function julianToDate(jdn) { // Julian Day Number conversion const a = jdn + 32044; const b = Math.floor((4 * a + 3) / 146097); const c = a - Math.floor((146097 * b) / 4); const d = Math.floor((4 * c + 3) / 1461); const e = c - Math.floor((1461 * d) / 4); const m = Math.floor((5 * e + 2) / 153); const day = e - Math.floor((153 * m + 2) / 5) + 1; const month = m + 3 - 12 * Math.floor(m / 10); const year = 100 * b + d - 4800 + Math.floor(m / 10); return new Date(year, month - 1, day); } /** * Convert Date to Julian Day Number * @param {Date} date - Date to convert * @returns {number} Julian Day Number */ function dateToJulian(date) { const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const a = Math.floor((14 - month) / 12); const y = year + 4800 - a; const m = month + 12 * a - 3; return day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) - 32045; } /** * Validate date range * @param {Date} date - Date to validate * @param {Date} minDate - Minimum allowed date (optional) * @param {Date} maxDate - Maximum allowed date (optional) * @returns {boolean} True if date is in valid range */ function validateDateRange(date, minDate, maxDate) { const momentDate = moment(date); if (minDate && momentDate.isBefore(minDate)) { return false; } if (maxDate && momentDate.isAfter(maxDate)) { return false; } return true; } /** * Get relative time description * @param {Date} date - Date to compare * @param {Date} baseDate - Base date for comparison (optional, defaults to now) * @returns {string} Relative time description */ function getRelativeTime(date, baseDate = new Date()) { return moment(date).from(moment(baseDate)); } /** * Parse time string (HH:mm:ss or HH:mm) * @param {string} timeString - Time in string format * @returns {Object} Parsed time object {hours, minutes, seconds} */ function parseTime(timeString) { const parts = timeString.split(':'); if (parts.length < 2 || parts.length > 3) { throw new Error('Invalid time format. Use HH:mm or HH:mm:ss'); } const hours = parseInt(parts[0], 10); const minutes = parseInt(parts[1], 10); const seconds = parts.length === 3 ? parseInt(parts[2], 10) : 0; if (hours < 0 || hours > 23) { throw new Error('Hours must be between 0 and 23'); } if (minutes < 0 || minutes > 59) { throw new Error('Minutes must be between 0 and 59'); } if (seconds < 0 || seconds > 59) { throw new Error('Seconds must be between 0 and 59'); } return { hours, minutes, seconds }; } module.exports = { parseDateInput, formatDateTime, formatTime, formatDate, convertTimezone, getTimezoneOffset, isValidTimezone, getSupportedTimezones, getCountryTimezones, getIndianTimezones, calculateDuration, addTime, subtractTime, getStartOfDay, getEndOfDay, isToday, getDayOfYear, getWeekOfYear, isLeapYear, getDaysInMonth, formatDuration, julianToDate, dateToJulian, validateDateRange, getRelativeTime, parseTime };