import { defaultFormatPattern, patternRegExp, weeks } from './constants'; import { createDateInstance, paddingLeftZero } from './utils'; import { LikeDate } from './model'; /** * * @param date 将要格式化的日期 * @param pattern 格式化模式,默认为:'yyyy年MM月dd日 hh时mm分ss秒' * @example * 格式化当前日期 format() * 传入时间戳 format(1607000082114) */ function format( date?: LikeDate, pattern: string = defaultFormatPattern, ): string { const dateInstance = createDateInstance(date); if (!dateInstance) { return ''; } if (typeof pattern !== 'string') { pattern = defaultFormatPattern; } return pattern.replace(patternRegExp, (match, $1): string => { const { length } = $1; const year = dateInstance.getFullYear().toString(); switch ($1.charAt(0)) { case 'y': return year.substr(year.length - length); case 'M': return paddingLeftZero(dateInstance.getMonth() + 1, length); case 'd': return paddingLeftZero(dateInstance.getDate(), length); case 'w': return String(dateInstance.getDay() === 0 ? 7 : dateInstance.getDay()); case 'W': return weeks[dateInstance.getDay()]; case 'h': return paddingLeftZero(dateInstance.getHours(), length); case 'm': return paddingLeftZero(dateInstance.getMinutes(), length); case 's': return paddingLeftZero(dateInstance.getSeconds(), length); default: return ''; } }); } /** * 比较两个日期 * date1 = date2 return 0 * date1 > date2 return 1 * date1 < date2 return -1 * @param {*} date1 日期一 * @param {*} date2 日期二 */ function compare(date1: LikeDate, date2: LikeDate): number { const firstTimestamp = createDateInstance(date1)?.getTime(); const secondTimestamp = createDateInstance(date2)?.getTime(); if (!firstTimestamp || !secondTimestamp) return Number.NaN; if (firstTimestamp - secondTimestamp === 0) { return 0; } return firstTimestamp - secondTimestamp > 0 ? 1 : -1; } /** * 计算2日期之间的天数 * @param date1 日期一 * @param date2 日期二 */ function countDays(date1: LikeDate, date2: LikeDate): number { const firstTimestamp = createDateInstance(date1)?.getTime(); const secondTimestamp = createDateInstance(date2)?.getTime(); if (!firstTimestamp || !secondTimestamp) return Number.NaN; return Math.abs(firstTimestamp - secondTimestamp) / (24 * 60 * 60 * 1000); } /** * 是否是闰年 * @param {*} year 年份 */ function isLeapYear(year: number): boolean { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } /** * 获取某月的天数 * @param {*} month 月份,从1开始,取值为1~12 * @param {*} year 年份,可选,用于判断是否为闰年,默认为当前年 */ function getDaysOfMonth( month: number, year = new Date().getFullYear(), ): number { const days = [ 31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ]; return days[month - 1]; } /** * 获取昨天日期 * @param {*} pattern 格式化模式,可选,形式同format函数第二个参数,不传则返回日期对象 */ function getYesterday(pattern?: string): string | Date { const date = new Date(); date.setDate(date.getDate() - 1); if (pattern) { return format(date, pattern); } return date; } /** * 获取明天日期 * @param {*} pattern 格式化模式,可选,形式同format函数第二个参数,不传则返回日期对象 */ function getTomorrow(pattern?: string): string | Date { const date = new Date(); date.setDate(date.getDate() + 1); if (pattern) { return format(date, pattern); } return date; } /** * 根据生日获取年龄 * @param birthday 生日 * @param strict 是否严格计算,默认为true * @returns age 年龄 * @description 传入生日无法转换成日期时,会返回 -1 * @description 禁止严格计算时,只计算年份的差值;开启严格计算时,会根据年月日严格计算 */ function getAgeByBirthday(birthday: LikeDate, strict = true): number { const birthDate = createDateInstance(birthday); const nowDate = new Date(); if (!birthDate) return -1; const yearDiff = nowDate.getFullYear() - birthDate.getFullYear(); const monthDiff = nowDate.getMonth() - birthDate.getMonth(); const dayDiff = nowDate.getDate() - birthDate.getDate(); if (!strict) return yearDiff; const age = monthDiff < 0 || (monthDiff === 0 && dayDiff < 0) ? yearDiff - 1 : yearDiff; return age < 0 ? 0 : age; } function isValid(date: LikeDate) { return createDateInstance(date) !== null; } export { format, compare, countDays, isLeapYear, getDaysOfMonth, getYesterday, getTomorrow, getAgeByBirthday, isValid, };