import { computed } from 'vue' import { dayjs } from '../common/dayjs' import { isArray, isFunction, padZero } from '../common/util' import { useTranslate } from '../composables/useTranslate' import type { CalendarDayType, CalendarItem, CalendarTimeFilter, CalendarType } from './types' const { translate } = useTranslate('calendar-view') const weeks = computed(() => { return [ translate('weeks.sun'), translate('weeks.mon'), translate('weeks.tue'), translate('weeks.wed'), translate('weeks.thu'), translate('weeks.fri'), translate('weeks.sat') ] }) /** * 比较两个时间的日期是否相等 * @param {timestamp} date1 * @param {timestamp} date2 */ export function compareDate(date1: number, date2: number | null) { const dateValue1 = new Date(date1) const dateValue2 = new Date(date2 || '') const year1 = dateValue1.getFullYear() const year2 = dateValue2.getFullYear() const month1 = dateValue1.getMonth() const month2 = dateValue2.getMonth() const day1 = dateValue1.getDate() const day2 = dateValue2.getDate() if (year1 === year2) { if (month1 === month2) { return day1 === day2 ? 0 : day1 > day2 ? 1 : -1 } return month1 === month2 ? 0 : month1 > month2 ? 1 : -1 } return year1 > year2 ? 1 : -1 } /** * 判断是否是范围选择 * @param {string} type */ export function isRange(type: CalendarType) { return type.indexOf('range') > -1 } /** * 比较两个日期的月份是否相等 * @param {timestamp} date1 * @param {timestamp} date2 */ export function compareMonth(date1: number, date2: number) { const dateValue1 = new Date(date1) const dateValue2 = new Date(date2) const year1 = dateValue1.getFullYear() const year2 = dateValue2.getFullYear() const month1 = dateValue1.getMonth() const month2 = dateValue2.getMonth() if (year1 === year2) { return month1 === month2 ? 0 : month1 > month2 ? 1 : -1 } return year1 > year2 ? 1 : -1 } /** * 比较两个日期的年份是否一致 * @param {timestamp} date1 * @param {timestamp} date2 */ export function compareYear(date1: number, date2: number) { const dateValue1 = new Date(date1) const dateValue2 = new Date(date2) const year1 = dateValue1.getFullYear() const year2 = dateValue2.getFullYear() return year1 === year2 ? 0 : year1 > year2 ? 1 : -1 } /** * 获取一个月的最后一天 * @param {number} year * @param {number} month */ export function getMonthEndDay(year: number, month: number) { return 32 - new Date(year, month - 1, 32).getDate() } /** * 格式化年月 * @param {timestamp} date */ export function formatMonthTitle(date: number) { return dayjs(date).format(translate('monthTitle')) } /** * 根据下标获取星期 * @param {number} index */ export function getWeekLabel(index: number) { if (index >= 7) { index = index % 7 } return weeks.value[index] } /** * 格式化年份 * @param {timestamp} date */ export function formatYearTitle(date: number) { return dayjs(date).format(translate('yearTitle')) } /** * 根据最小日期和最大日期获取这之间总共有几个月份 * @param {timestamp} minDate * @param {timestamp} maxDate */ export function getMonths(minDate: number, maxDate: number) { const months: number[] = [] const month = new Date(minDate) month.setDate(1) while (compareMonth(month.getTime(), maxDate) < 1) { months.push(month.getTime()) month.setMonth(month.getMonth() + 1) } return months } /** * 根据最小日期和最大日期获取这之间总共有几年 * @param {timestamp} minDate * @param {timestamp} maxDate */ export function getYears(minDate: number, maxDate: number) { const years: number[] = [] const year = new Date(minDate) year.setMonth(0) year.setDate(1) while (compareYear(year.getTime(), maxDate) < 1) { years.push(year.getTime()) year.setFullYear(year.getFullYear() + 1) } return years } /** * 获取一个日期所在周的第一天和最后一天 * @param {timestamp} date */ export function getWeekRange(date: number, firstDayOfWeek: number) { if (firstDayOfWeek >= 7) { firstDayOfWeek = firstDayOfWeek % 7 } const dateValue = new Date(date) dateValue.setHours(0, 0, 0, 0) const year = dateValue.getFullYear() const month = dateValue.getMonth() const day = dateValue.getDate() const week = dateValue.getDay() const weekStart = new Date(year, month, day - ((7 + week - firstDayOfWeek) % 7)) const weekEnd = new Date(year, month, day + 6 - ((7 + week - firstDayOfWeek) % 7)) return [weekStart.getTime(), weekEnd.getTime()] } /** * 获取日期偏移量 * @param {timestamp} date1 * @param {timestamp} date2 */ export function getDayOffset(date1: number, date2: number) { return (date1 - date2) / (24 * 60 * 60 * 1000) + 1 } /** * 获取偏移日期 * @param {timestamp} date * @param {number} offset */ export function getDayByOffset(date: number, offset: number) { const dateValue = new Date(date) dateValue.setDate(dateValue.getDate() + offset) return dateValue.getTime() } export const getPrevDay = (date: number) => getDayByOffset(date, -1) export const getNextDay = (date: number) => getDayByOffset(date, 1) /** * 获取月份偏移量 * @param {timestamp} date1 * @param {timestamp} date2 */ export function getMonthOffset(date1: number, date2: number) { const dateValue1 = new Date(date1) const dateValue2 = new Date(date2) const year1 = dateValue1.getFullYear() const year2 = dateValue2.getFullYear() let month1 = dateValue1.getMonth() const month2 = dateValue2.getMonth() month1 = (year1 - year2) * 12 + month1 return month1 - month2 + 1 } /** * 获取偏移月份 * @param {timestamp} date * @param {number} offset */ export function getMonthByOffset(date: number, offset: number) { const dateValue = new Date(date) dateValue.setMonth(dateValue.getMonth() + offset) return dateValue.getTime() } /** * 获取默认时间,格式化为数组 * @param {array|string|null} defaultTime */ export function getDefaultTime(defaultTime: string[] | string | null) { if (isArray(defaultTime)) { const startTime = (defaultTime[0] || '00:00:00').split(':').map((item: string) => { return parseInt(item) }) const endTime = (defaultTime[1] || '00:00:00').split(':').map((item) => { return parseInt(item) }) return [startTime, endTime] } else { const time = (defaultTime || '00:00:00').split(':').map((item) => { return parseInt(item) }) return [time, time] } } /** * 根据默认时间获取日期 * @param {timestamp} date * @param {array} defaultTime */ export function getDateByDefaultTime(date: number, defaultTime: number[]) { const dateValue = new Date(date) dateValue.setHours(defaultTime[0]) dateValue.setMinutes(defaultTime[1]) dateValue.setSeconds(defaultTime[2]) return dateValue.getTime() } /** * 获取经过 iteratee 格式化后的长度为 n 的数组 * @param {number} n * @param {function} iteratee */ const times = (n: number, iteratee: (index: number) => CalendarItem) => { let index: number = -1 const result: CalendarItem[] = Array(n < 0 ? 0 : n) while (++index < n) { result[index] = iteratee(index) } return result } /** * 获取时分秒 * @param {timestamp}} date */ const getTime = (date: number) => { const dateValue = new Date(date) return [dateValue.getHours(), dateValue.getMinutes(), dateValue.getSeconds()] } /** * 根据最小最大日期获取时间数据,用于填入picker * @param {*} param0 */ export function getTimeData({ date, minDate, maxDate, isHideSecond, filter }: { date: number minDate: number maxDate: number isHideSecond: boolean filter?: CalendarTimeFilter }) { const compareMin = compareDate(date, minDate) const compareMax = compareDate(date, maxDate) let minHour = 0 let maxHour = 23 let minMinute = 0 let maxMinute = 59 let minSecond = 0 let maxSecond = 59 if (compareMin === 0) { const minTime = getTime(minDate) const currentTime = getTime(date) minHour = minTime[0] if (minTime[0] === currentTime[0]) { minMinute = minTime[1] if (minTime[1] === currentTime[1]) { minSecond = minTime[2] } } } if (compareMax === 0) { const maxTime = getTime(maxDate) const currentTime = getTime(date) maxHour = maxTime[0] if (maxTime[0] === currentTime[0]) { maxMinute = maxTime[1] if (maxTime[1] === currentTime[1]) { maxSecond = maxTime[2] } } } let columns: CalendarItem[][] = [] let hours = times(24, (index) => { return { label: translate('hour', padZero(index)), value: index, disabled: index < minHour || index > maxHour } }) let minutes = times(60, (index) => { return { label: translate('minute', padZero(index)), value: index, disabled: index < minMinute || index > maxMinute } }) let seconds: CalendarItem[] = [] if (filter && isFunction(filter)) { hours = filter({ type: 'hour', values: hours }) minutes = filter({ type: 'minute', values: minutes }) } if (!isHideSecond) { seconds = times(60, (index) => { return { label: translate('second', padZero(index)), value: index, disabled: index < minSecond || index > maxSecond } }) if (filter && isFunction(filter)) { seconds = filter({ type: 'second', values: seconds }) } } columns = isHideSecond ? [hours, minutes] : [hours, minutes, seconds] return columns } /** * 获取当前是第几周 * @param {timestamp} date */ export function getWeekNumber(date: number | Date) { date = new Date(date) date.setHours(0, 0, 0, 0) // Thursday in current week decides the year. date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7)) // January 4 is always in week 1. const week = new Date(date.getFullYear(), 0, 4) // Adjust to Thursday in week 1 and count number of weeks from date to week 1. // Rounding should be fine for Daylight Saving Time. Its shift should never be more than 12 hours. return 1 + Math.round(((date.getTime() - week.getTime()) / 86400000 - 3 + ((week.getDay() + 6) % 7)) / 7) } export function getItemClass(monthType: CalendarDayType, value: number | null | (number | null)[], type: CalendarType) { const classList = ['is-' + monthType] if (type.indexOf('range') > -1 && isArray(value)) { if (!value || !value[1]) { classList.push('is-without-end') } } return classList.join(' ') }