UNPKG

gtht-miniapp-sdk

Version:

gtht-miniapp-sdk 是一套基于 Uniapp + Vue3 框架开发的兼容多端的 UI 组件库

405 lines (404 loc) 16.7 kB
import { clamp } from './number'; import { escapeRegExp } from './regexp'; /** * 判断是否为闰年。 */ export function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } const monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; /** * 获取某月的天数,月份从0开始。 */ export function getDaysInMonth(year, month) { if (month === 1) { return isLeapYear(year) ? 29 : 28; } else { return monthDays[month]; } } /** * 获取当前日期是一年中的第几天。 */ export function getDayOfYear(date) { const year = date.getFullYear(); const month = date.getMonth(); const d = date.getDate(); let days = 0; for (let m = 0; m < month; m++) { days += getDaysInMonth(year, m); } return days + d; } /** * 获取指定月份第一天是星期几,月份从0开始。 */ export function getFirstDayWeekday(year, month) { return new Date(year, month, 1).getDay(); } /** * 获取从基准日期(如1970-01-01)到指定日期的总天数。 */ export function getDaysSinceUnixEpoch(date) { return Math.floor(date.getTime() / 1000 / 60 / 60 / 24); } /** * 把日期转换为年月日数值,例如:2025年7月1号 -> 20250601。 */ export function toDateNumber(date) { return date.getFullYear() * 10000 + date.getMonth() * 100 + date.getDate(); } /** * 把日期转换为年月日字符串,,例如:2025年7月1号 -> 2025-7-1。 */ export function toDateString(date) { return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(); } /** * 把日期转换为年月数值,例如:2025年7月1号 -> 20250600。 */ export function toMonthNumber(date) { return date.getFullYear() * 10000 + date.getMonth() * 100; } /** * 计算当前月份1号前面需要显示的上个月末尾的天数。 */ export function getDaysBeforeFirstDay(year, month, weekStartsOn = 0) { const week = getFirstDayWeekday(year, month); return (week - weekStartsOn + 7) % 7; } /** * 获取当前月份最后一天之后需要显示的下个月开始的天数。 */ export function getDaysAfterLastDay(year, month, weekStartsOn = 0) { const daysBefore = getDaysBeforeFirstDay(year, month, weekStartsOn); return 42 - daysBefore - getDaysInMonth(year, month); } /** * 获取当前月份1号之前需要显示的上个月末尾的日期。 */ export function getPrevMonthTailDays(year, month, weekStartsOn = 0) { const daysBefore = getDaysBeforeFirstDay(year, month, weekStartsOn); const dates = []; for (let i = daysBefore - 1; i >= 0; i--) { dates.push(new Date(year, month, -i)); } return dates; } /** * 获取当前月份最后一天之后需要显示的下个月开始的日期。 */ export function getNextMonthHeadDays(year, month, weekStartsOn = 0) { const daysAfter = getDaysAfterLastDay(year, month, weekStartsOn); const dates = []; for (let i = 1; i <= daysAfter; i++) { dates.push(new Date(year, month + 1, i)); } return dates; } const dateTokensReg = /(YYYY|YY|MM|M|DD|D|HH|H|hh|h|mm|m|ss|s|SSS)/g; const dateGetters = { YYYY: (date) => String(date.getFullYear()).padStart(4, '0'), YY: (date) => String(date.getFullYear()).slice(-2), MM: (date) => String(date.getMonth() + 1).padStart(2, '0'), M: (date) => String(date.getMonth() + 1), DD: (date) => String(date.getDate()).padStart(2, '0'), D: (date) => String(date.getDate()), HH: (date) => String(date.getHours()).padStart(2, '0'), H: (date) => String(date.getHours()), hh: (date) => String(date.getHours() % 24).padStart(2, '0'), h: (date) => String(date.getHours() % 24), mm: (date) => String(date.getMinutes()).padStart(2, '0'), m: (date) => String(date.getMinutes()), ss: (date) => String(date.getSeconds()).padStart(2, '0'), s: (date) => String(date.getSeconds()), SSS: (date) => String(date.getMilliseconds()).padStart(3, '0'), }; /** * 根据传入的占位符返回格式化后的日期。 */ export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') { return format.replace(dateTokensReg, (match) => { return dateGetters[match](date); }); } const defaultTokenFrags = ['YYYY', 'MM', 'DD', 'HH', 'mm', 'ss', 'SSS']; const dateSetters = { YYYY: (date, year) => date.setFullYear(year), YY: (date, year) => date.setFullYear(year), MM: (date, month) => date.setMonth(month - 1), M: (date, month) => date.setMonth(month - 1), DD: (date, d) => date.setDate(d), D: (date, d) => date.setDate(d), HH: (date, hours) => date.setHours(hours), H: (date, hours) => date.setHours(hours), hh: (date, hours) => date.setHours(hours), h: (date, hours) => date.setHours(hours), mm: (date, minutes) => date.setMinutes(minutes), m: (date, minutes) => date.setMinutes(minutes), ss: (date, seconds) => date.setSeconds(seconds), s: (date, seconds) => date.setSeconds(seconds), SSS: (date, milliseconds) => date.setMilliseconds(milliseconds), }; function parseDateWithoutFormat(value) { const numbers = value.split(/\D+/).filter(Boolean); const tokens = defaultTokenFrags.slice(0, numbers.length); const date = new Date(0, 0); tokens.forEach((token, i) => { dateSetters[token](date, Number(numbers[i])); }); return date; } /** * 解析日期的字符串表示形式,并返回 Date 实例对象。 */ export function parseDate(value, format) { if (!format) { return parseDateWithoutFormat(value); } const frags = format.split(dateTokensReg); const reg = new RegExp('^' + frags .filter((_, i) => i % 2 === 0) .map((item) => escapeRegExp(item)) .join('(.*)') + '$'); const dateFrags = reg.exec(value)?.slice(1); if (!dateFrags) { return parseDateWithoutFormat(value); } const tokenFrags = frags.filter((_, i) => i % 2 !== 0); const date = new Date(0); tokenFrags.forEach((token, i) => { dateSetters[token](date, Number(dateFrags[i])); }); return date; } // 确保返回一个Date对象,如果传递字符串,则使用 parseDate 解析。 export function toDate(date, valueFormat) { if (date instanceof Date) { return date; } return parseDate(date, valueFormat); } // 限定日期范围,会返回一个新的日期。 export function minmaxDate(date, minDate, maxDate) { return new Date(clamp(date.getTime(), minDate.getTime(), maxDate.getTime())); } // 获取上一个月的日期对象。 export function getPrevMonthDate(date) { return new Date(date.getFullYear(), date.getMonth() - 1, 1); } // 获取下一个月的日期对象。 export function getNextMonthDate(date) { return new Date(date.getFullYear(), date.getMonth() + 1, 1); } /**************************************************************** * 农历 ****************************************************************/ // prettier-ignore export const lunarInfo = [ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929 0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059 0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099 0x0d520, // 2100 ]; // 1900-2100春节对应的公历日期 // prettier-ignore export const springFestivals = [ [1, 31], [2, 19], [2, 8], [1, 29], [2, 16], [2, 4], [1, 25], [2, 13], [2, 2], [1, 22], // 1900-1909 [2, 10], [1, 30], [2, 18], [2, 6], [1, 26], [2, 14], [2, 3], [1, 23], [2, 11], [2, 1], // 1910-1919 [2, 20], [2, 8], [1, 28], [2, 16], [2, 5], [1, 24], [2, 13], [2, 2], [1, 23], [2, 10], // 1920-1929 [1, 30], [2, 17], [2, 6], [1, 26], [2, 14], [2, 4], [1, 24], [2, 11], [1, 31], [2, 19], // 1930-1939 [2, 8], [1, 27], [2, 15], [2, 5], [1, 25], [2, 13], [2, 2], [1, 22], [2, 10], [1, 29], // 1940-1949 [2, 17], [2, 6], [1, 27], [2, 14], [2, 3], [1, 24], [2, 12], [1, 31], [2, 18], [2, 8], // 1950-1959 [1, 28], [2, 15], [2, 5], [1, 25], [2, 13], [2, 2], [1, 21], [2, 9], [1, 30], [2, 17], // 1960-1969 [2, 6], [1, 27], [2, 15], [2, 3], [1, 23], [2, 11], [1, 31], [2, 18], [2, 7], [1, 28], // 1970-1979 [2, 16], [2, 5], [1, 25], [2, 13], [2, 2], [2, 20], [2, 9], [1, 29], [2, 17], [2, 6], // 1980-1989 [1, 27], [2, 15], [2, 4], [1, 23], [2, 10], [1, 31], [2, 19], [2, 7], [1, 28], [2, 16], // 1990-1999 [2, 5], [1, 24], [2, 12], [2, 1], [1, 22], [2, 9], [1, 29], [2, 18], [2, 7], [1, 26], // 2000-2009 [2, 14], [2, 3], [1, 23], [2, 10], [1, 31], [2, 19], [2, 8], [1, 28], [2, 16], [2, 5], // 2010-2019 [1, 25], [2, 12], [2, 1], [1, 22], [2, 10], [1, 29], [2, 17], [2, 6], [1, 26], [2, 13], // 2020-2029 [2, 3], [1, 23], [2, 11], [1, 31], [2, 19], [2, 8], [1, 28], [2, 15], [2, 4], [1, 24], // 2030-2039 [2, 12], [2, 1], [1, 22], [2, 10], [1, 30], [2, 17], [2, 6], [1, 26], [2, 14], [2, 2], // 2040-2049 [1, 23], [2, 11], [2, 1], [2, 19], [2, 8], [1, 28], [2, 15], [2, 4], [1, 24], [2, 12], // 2050-2059 [2, 2], [1, 21], [2, 9], [1, 29], [2, 17], [2, 5], [1, 26], [2, 14], [2, 3], [1, 23], // 2060-2069 [2, 11], [1, 31], [2, 19], [2, 7], [1, 27], [2, 15], [2, 5], [1, 24], [2, 12], [2, 2], // 2070-2079 [1, 22], [2, 9], [1, 29], [2, 17], [2, 6], [1, 26], [2, 14], [2, 3], [1, 24], [2, 10], // 2080-2089 [1, 30], [2, 18], [2, 7], [1, 27], [2, 15], [2, 5], [1, 25], [2, 12], [2, 1], [1, 21], // 2090-2099 [2, 9], // 2100 ]; export const baseLunarYear = 1900; /** * 获取农历某年闰月的月份,月份从1开始(0表示无闰月)。 */ export function getLunarLeapMonth(year) { return lunarInfo[year - baseLunarYear] & 0xf; } /** * 获取农历某年闰月的天数。 */ export function getLunarLeapMonthDays(year) { if (getLunarLeapMonth(year)) { return lunarInfo[year - baseLunarYear] & 0x10000 ? 30 : 29; } return 0; } /** * 获取农历某年的总天数。 */ export function getLunarYearDays(year) { let sum = 348; // 29天*12个月 const info = lunarInfo[year - baseLunarYear]; // 加上大月的天数 for (let i = 0x8000; i > 0x8; i >>= 1) { sum += info & i ? 1 : 0; } // 加上闰月的天数 return sum + getLunarLeapMonthDays(year); } /** * 获取农历某年某月的天数,月份从1开始。 */ export function getLunarMonthDays(year, month) { return lunarInfo[year - baseLunarYear] & (0x10000 >> month) ? 30 : 29; } /** * 公历转农历,月份从1开始(返回的闰月为负数)。 */ export function solarToLunar(year, month, day) { // 计算输入日期与基准日期的天数差 const offsetDays = Math.floor((Date.UTC(year, month - 1, day) - Date.UTC(baseLunarYear, 0, 31)) / (24 * 60 * 60 * 1000)); // 农历年、月、日初始化 let lunarYear = baseLunarYear; let lunarMonth = 1; let lunarDay = 1; let isLeapMonth = false; let daysRemaining = offsetDays; // 计算农历年 while (true) { const yearDays = getLunarYearDays(lunarYear); if (daysRemaining < yearDays) { break; } daysRemaining -= yearDays; lunarYear++; } // 计算农历月和日 const leapMonth = getLunarLeapMonth(lunarYear); let monthDays = 0; let _month = 1; for (; _month <= 12; _month++) { // 处理闰月 if (leapMonth > 0 && _month === leapMonth + 1) { monthDays = getLunarLeapMonthDays(lunarYear); if (daysRemaining < monthDays) { isLeapMonth = true; _month--; break; } daysRemaining -= monthDays; } monthDays = getLunarMonthDays(lunarYear, _month); if (daysRemaining < monthDays) { break; } daysRemaining -= monthDays; } lunarMonth = _month; lunarDay = daysRemaining + 1; return { year: lunarYear, month: lunarMonth * (isLeapMonth ? -1 : 1), day: lunarDay, }; } /** * 农历转公历(闰月需传递负数)。 */ export function lunarToSolar(year, month, day) { const springFestival = springFestivals[year - baseLunarYear]; const solarDate = new Date(year, springFestival[0] - 1, springFestival[1]); const info = lunarInfo[year - baseLunarYear]; const leapMonth = info & 0xf; let totalDays = 0; const absMonth = Math.abs(month); for (let m = 1; m < absMonth; m++) { if (m === leapMonth) { totalDays += getLunarLeapMonthDays(year); } totalDays += getLunarMonthDays(year, m); } if (month < 0) { totalDays += getLunarMonthDays(year, absMonth); } totalDays += day - 1; solarDate.setDate(solarDate.getDate() + totalDays); return { year: solarDate.getFullYear(), month: solarDate.getMonth() + 1, day: solarDate.getDate(), }; } // 农历年份的名称 // prettier-ignore export const lunarYearNames = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']; /** * 将阿拉伯数字的年份转为汉字数字年份 */ export function getLunarYearName(year) { return (String(year) .split('') .map((item) => lunarYearNames[+item]) .join('') + '年'); } // 农历月份的名称 // prettier-ignore export const lunarMonthNames = ['正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '腊']; /** * 获取农历月份名称,月份从1开始,例如:正月,十月,腊月。 */ export function getLunarMonthName(month, isLeapMonth) { return (isLeapMonth ? '闰' : '') + lunarMonthNames[month - 1] + '月'; } // 农历日期的名称 // prettier-ignore export const lunarDayNames = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']; /** * 获取农历日期名称,例如:初一,十二,廿一。 */ export function getLunarDayName(day) { return lunarDayNames[day - 1]; } // 十天干 // prettier-ignore export const heavenlyStems = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']; // 十二地支 // prettier-ignore export const earthlyBranches = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']; /** * 获取农历时辰名称,例如:子初、子正、午初,午正。 */ export function getLunarHourName(hour) { const index = Math.floor(((hour === 23 ? 0 : hour) + 1) / 2) % 12; return earthlyBranches[index] + (hour % 2 === 1 ? '初' : '正'); }