class Calendar { constructor({ selected, startDate, endDate, range, } = {}) { // 当前日期 this.date = this.getDateObj(new Date()) // 当前初入日期 // 打点信息 this.selected = selected || []; // 起始时间 this.startDate = startDate // 终止时间 this.endDate = endDate // 是否范围选择 this.range = range // 多选状态 this.cleanMultipleStatus() // 每周日期 this.weeks = {} this.lastHover = false } /** * 设置日期 * @param {Object} date */ setDate(date) { const selectDate = this.getDateObj(date) this.getWeeks(selectDate.fullDate) } /** * 清理多选状态 */ cleanMultipleStatus() { this.multipleStatus = { before: '', after: '', data: [] } } setStartDate(startDate) { this.startDate = startDate } setEndDate(endDate) { this.endDate = endDate } getPreMonthObj(date) { date = fixIosDateFormat(date) date = new Date(date) const oldMonth = date.getMonth() date.setMonth(oldMonth - 1) const newMonth = date.getMonth() if (oldMonth !== 0 && newMonth - oldMonth === 0) { date.setMonth(newMonth - 1) } return this.getDateObj(date) } getNextMonthObj(date) { date = fixIosDateFormat(date) date = new Date(date) const oldMonth = date.getMonth() date.setMonth(oldMonth + 1) const newMonth = date.getMonth() if (newMonth - oldMonth > 1) { date.setMonth(newMonth - 1) } return this.getDateObj(date) } /** * 获取指定格式Date对象 */ getDateObj(date) { date = fixIosDateFormat(date) date = new Date(date) return { fullDate: getDate(date), year: date.getFullYear(), month: addZero(date.getMonth() + 1), date: addZero(date.getDate()), day: date.getDay() } } /** * 获取上一个月日期集合 */ getPreMonthDays(amount, dateObj) { const result = [] for (let i = amount - 1; i >= 0; i--) { const month = dateObj.month - 1 result.push({ date: new Date(dateObj.year, month, -i).getDate(), month, disable: true }) } return result } /** * 获取本月日期集合 */ getCurrentMonthDays(amount, dateObj) { const result = [] const fullDate = this.date.fullDate for (let i = 1; i <= amount; i++) { const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}` const isToday = fullDate === currentDate // 获取打点信息 const info = this.selected && this.selected.find((item) => { if (this.dateEqual(currentDate, item.date)) { return item } }) // 日期禁用 let disableBefore = true let disableAfter = true if (this.startDate) { disableBefore = dateCompare(this.startDate, currentDate) } if (this.endDate) { disableAfter = dateCompare(currentDate, this.endDate) } let multiples = this.multipleStatus.data let multiplesStatus = -1 if (this.range && multiples) { multiplesStatus = multiples.findIndex((item) => { return this.dateEqual(item, currentDate) }) } const checked = multiplesStatus !== -1 result.push({ fullDate: currentDate, year: dateObj.year, date: i, multiple: this.range ? checked : false, beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after), afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after), month: dateObj.month, disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare( currentDate, this.endDate)), isToday, userChecked: false, extraInfo: info }) } return result } /** * 获取下一个月日期集合 */ _getNextMonthDays(amount, dateObj) { const result = [] const month = dateObj.month + 1 for (let i = 1; i <= amount; i++) { result.push({ date: i, month, disable: true }) } return result } /** * 获取当前日期详情 * @param {Object} date */ getInfo(date) { if (!date) { date = new Date() } return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate) } /** * 比较时间是否相等 */ dateEqual(before, after) { before = new Date(fixIosDateFormat(before)) after = new Date(fixIosDateFormat(after)) return before.valueOf() === after.valueOf() } /** * 比较真实起始日期 */ isLogicBefore(currentDate, before, after) { let logicBefore = before if (before && after) { logicBefore = dateCompare(before, after) ? before : after } return this.dateEqual(logicBefore, currentDate) } isLogicAfter(currentDate, before, after) { let logicAfter = after if (before && after) { logicAfter = dateCompare(before, after) ? after : before } return this.dateEqual(logicAfter, currentDate) } /** * 获取日期范围内所有日期 * @param {Object} begin * @param {Object} end */ geDateAll(begin, end) { var arr = [] var ab = begin.split('-') var ae = end.split('-') var db = new Date() db.setFullYear(ab[0], ab[1] - 1, ab[2]) var de = new Date() de.setFullYear(ae[0], ae[1] - 1, ae[2]) var unixDb = db.getTime() - 24 * 60 * 60 * 1000 var unixDe = de.getTime() - 24 * 60 * 60 * 1000 for (var k = unixDb; k <= unixDe;) { k = k + 24 * 60 * 60 * 1000 arr.push(this.getDateObj(new Date(parseInt(k))).fullDate) } return arr } /** * 获取多选状态 */ setMultiple(fullDate) { if (!this.range) return let { before, after } = this.multipleStatus if (before && after) { if (!this.lastHover) { this.lastHover = true return } this.multipleStatus.before = fullDate this.multipleStatus.after = '' this.multipleStatus.data = [] this.multipleStatus.fulldate = '' this.lastHover = false } else { if (!before) { this.multipleStatus.before = fullDate this.multipleStatus.after = undefined; this.lastHover = false } else { this.multipleStatus.after = fullDate if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus .after); } else { this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus .before); } this.lastHover = true } } this.getWeeks(fullDate) } /** * 鼠标 hover 更新多选状态 */ setHoverMultiple(fullDate) { //抖音小程序点击会触发hover事件,需要避免一下 // #ifndef MP-TOUTIAO if (!this.range || this.lastHover) return const { before } = this.multipleStatus if (!before) { this.multipleStatus.before = fullDate } else { this.multipleStatus.after = fullDate if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); } else { this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); } } this.getWeeks(fullDate) // #endif } /** * 更新默认值多选状态 */ setDefaultMultiple(before, after) { this.multipleStatus.before = before this.multipleStatus.after = after if (before && after) { if (dateCompare(before, after)) { this.multipleStatus.data = this.geDateAll(before, after); this.getWeeks(after) } else { this.multipleStatus.data = this.geDateAll(after, before); this.getWeeks(before) } } } /** * 获取每周数据 * @param {Object} dateData */ getWeeks(dateData) { const { year, month, } = this.getDateObj(dateData) const preMonthDayAmount = new Date(year, month - 1, 1).getDay() const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData)) const currentMonthDayAmount = new Date(year, month, 0).getDate() const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData)) const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData)) const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays] const weeks = new Array(6) for (let i = 0; i < calendarDays.length; i++) { const index = Math.floor(i / 7) if (!weeks[index]) { weeks[index] = new Array(7) } weeks[index][i % 7] = calendarDays[i] } this.calendar = calendarDays this.weeks = weeks } } function getDateTime(date, hideSecond) { return `${getDate(date)} ${getTime(date, hideSecond)}` } function getDate(date) { date = fixIosDateFormat(date) date = new Date(date) const year = date.getFullYear() const month = date.getMonth() + 1 const day = date.getDate() return `${year}-${addZero(month)}-${addZero(day)}` } function getTime(date, hideSecond) { date = fixIosDateFormat(date) date = new Date(date) const hour = date.getHours() const minute = date.getMinutes() const second = date.getSeconds() return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}` } function addZero(num) { if (num < 10) { num = `0${num}` } return num } function getDefaultSecond(hideSecond) { return hideSecond ? '00:00' : '00:00:00' } function dateCompare(startDate, endDate) { startDate = new Date(fixIosDateFormat(startDate)) endDate = new Date(fixIosDateFormat(endDate)) return startDate <= endDate } function checkDate(date) { const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g return date.match(dateReg) } //ios低版本15及以下,无法匹配 没有 ’秒‘ 时的情况,所以需要在末尾 秒 加上 问号 const dateTimeReg = /^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])( [0-5]?[0-9]:[0-5]?[0-9](:[0-5]?[0-9])?)?$/; function fixIosDateFormat(value) { if (typeof value === 'string' && dateTimeReg.test(value)) { value = value.replace(/-/g, '/') } return value } export { Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat }