export type TimePeriodUnit = 'day' | 'week' | 'month' | 'year' | 'custom' export const timePeriodUnitOptions: { label: string; value: TimePeriodUnit }[] = [ { label: '日', value: 'day' }, { label: '周', value: 'week' }, { label: '月', value: 'month' }, { label: '年', value: 'year' }, { label: '自定义', value: 'custom' } ] const datePickerTypeMap: Record = { day: 'date', week: 'date', month: 'month', year: 'year', custom: 'date' } const datePickerFormatMap: Record = { day: 'YYYY-MM-DD', week: 'YYYY-MM-DD', month: 'YYYY-MM', year: 'YYYY', custom: 'YYYY-MM-DD' } const padTimeValue = (value: number, length = 2) => String(value).padStart(length, '0') export const formatTimePeriodDateTime = (date: Date) => { const year = date.getFullYear() const month = padTimeValue(date.getMonth() + 1) const day = padTimeValue(date.getDate()) const hour = padTimeValue(date.getHours()) const minute = padTimeValue(date.getMinutes()) const second = padTimeValue(date.getSeconds()) const millisecond = padTimeValue(date.getMilliseconds(), 3) return `${year}-${month}-${day} ${hour}:${minute}:${second}.${millisecond}` } export const getTimePeriodPickerType = (unit: TimePeriodUnit) => datePickerTypeMap[unit] export const getTimePeriodPickerFormat = (unit: TimePeriodUnit) => datePickerFormatMap[unit] export const resolveTimePeriodUnitLabel = (unit: TimePeriodUnit) => { return timePeriodUnitOptions.find(item => item.value === unit)?.label ?? '' } export const buildTimePeriodRange = (unit: TimePeriodUnit, date: Date): string[] => { const year = date.getFullYear() const month = date.getMonth() const day = date.getDate() if (unit === 'day') { return [ formatTimePeriodDateTime(new Date(year, month, day, 0, 0, 0, 0)), formatTimePeriodDateTime(new Date(year, month, day, 23, 59, 59, 999)) ] } if (unit === 'week') { const dayOfWeek = date.getDay() const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek const weekStart = new Date(year, month, day + mondayOffset, 0, 0, 0, 0) const weekEnd = new Date( weekStart.getFullYear(), weekStart.getMonth(), weekStart.getDate() + 6, 23, 59, 59, 999 ) return [formatTimePeriodDateTime(weekStart), formatTimePeriodDateTime(weekEnd)] } if (unit === 'year') { return [ formatTimePeriodDateTime(new Date(year, 0, 1, 0, 0, 0, 0)), formatTimePeriodDateTime(new Date(year, 11, 31, 23, 59, 59, 999)) ] } return [ formatTimePeriodDateTime(new Date(year, month, 1, 0, 0, 0, 0)), formatTimePeriodDateTime(new Date(year, month + 1, 0, 23, 59, 59, 999)) ] } export const shiftTimePeriod = (unit: TimePeriodUnit, date: Date, offset: number) => { const nextDate = new Date(date) if (unit === 'day') { nextDate.setDate(nextDate.getDate() + offset) return nextDate } if (unit === 'year') { nextDate.setFullYear(nextDate.getFullYear() + offset) return nextDate } if (unit === 'week') { nextDate.setDate(nextDate.getDate() + offset * 7) return nextDate } // 月份切换以 1 日为锚点,避免 31 日切到短月份时发生日期溢出。 nextDate.setDate(1) nextDate.setMonth(nextDate.getMonth() + offset) return nextDate }