/** * @class DateTime * @description 日期处理模块 */ module.exports = class DateTime { constructor() { //默认日期展示格式 this.defaultDateFormat = 'Y-m-d H:i:s' //默认时区 this.defaultTimezone = 8 this.setTimeZone(this.defaultTimezone) } /** * 设置时区 * @param {Number} timezone 时区 */ setTimeZone(timezone) { if (timezone) { this.timezone = parseInt(timezone) } return this } /** * 获取 Date对象 * @param {Date|Time} time */ getDateObj(time) { return time ? new Date(time) : new Date() } /** * 获取毫秒/秒级时间戳 * @param {DateTime} datetime 日期 例:'2022-04-21 00:00:00' * @param {Boolean} showSenconds 是否显示为秒级时间戳 */ getTime(datetime, showSenconds) { let time = this.getDateObj(datetime).getTime() if (showSenconds) { time = Math.trunc(time / 1000) } return time } /** * 获取日期 * @param {String} dateFormat 日期格式 * @param {Time} time 时间戳 */ getDate(dateFormat, time) { return this.dateFormat(dateFormat, time) } /** * 获取日期在不同时区下的时间戳 * @param {Date|Time}} time 日期或时间戳 * @param {Object} timezone 时区 */ getTimeByTimeZone(time, timezone) { this.setTimeZone(timezone) const thisDate = time ? new Date(time) : new Date() const localTime = thisDate.getTime() const offset = thisDate.getTimezoneOffset() const utc = offset * 60000 + localTime return utc + (3600000 * this.timezone) } /** * 获取时间信息 * @param {Time} time 时间戳 * @param {Boolean} full 是否完整展示, 为true时小于10的位会自动补0 */ getTimeInfo(time, full = true) { time = this.getTimeByTimeZone(time) const date = this.getDateObj(time) const retData = { nYear: date.getFullYear(), nMonth: date.getMonth() + 1, nWeek: date.getDay() || 7, nDay: date.getDate(), nHour: date.getHours(), nMinutes: date.getMinutes(), nSeconds: date.getSeconds() } if (full) { for (const k in retData) { if (retData[k] < 10) { retData[k] = '0' + retData[k] } } } return retData } /** * 时间格式转换 * @param {String} format 展示格式如:Y-m-d H:i:s * @param {Time} time 时间戳 */ dateFormat(format, time) { const timeInfo = this.getTimeInfo(time) format = format || this.defaultDateFormat let date = format if (format.indexOf('Y') > -1) { date = date.replace(/Y/, timeInfo.nYear) } if (format.indexOf('m') > -1) { date = date.replace(/m/, timeInfo.nMonth) } if (format.indexOf('d') > -1) { date = date.replace(/d/, timeInfo.nDay) } if (format.indexOf('H') > -1) { date = date.replace(/H/, timeInfo.nHour) } if (format.indexOf('i') > -1) { date = date.replace(/i/, timeInfo.nMinutes) } if (format.indexOf('s') > -1) { date = date.replace(/s/, timeInfo.nSeconds) } return date } /** * 获取utc格式时间 * @param {Date|Time} datetime 日期或时间戳 */ getUTC(datetime) { return this.getDateObj(datetime).toUTCString() } /** * 获取ISO 格式时间 * @param {Date|Time} datetime 日期或时间戳 */ getISO(datetime) { return this.getDateObj(datetime).toISOString() } /** * 获取两时间相差天数 * @param {Time} time1 时间戳 * @param {Time} time2 时间戳 */ getDiffDays(time1, time2) { if (!time1) { return false } time2 = time2 ? time2 : this.getTime() let diffTime = time2 - time1 if (diffTime < 0) { diffTime = Math.abs(diffTime) } return Math.ceil(diffTime / 86400000) } /** * 字符串转时间戳 * @param {Object} str 字符串类型的时间戳 */ strToTime(str) { if (Array.from(str).length === 10) { str += '000' } return this.getTime(parseInt(str)) } /** * 根据设置的天数获取指定日期N天后(前)的时间戳 * @param {Number} days 天数 * @param {Date|Time} time 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳) */ getTimeBySetDays(days, time, getAll = false) { const date = this.getDateObj(time) date.setDate(date.getDate() + days) let startTime = date.getTime() if (!getAll) { const realdate = this.getDate('Y-m-d 00:00:00', startTime) startTime = this.getTimeByDateAndTimezone(realdate) } return startTime } /** * 根据设置的小时数获取指定日期N小时后(前)的时间戳 * @param {Number} hours 小时数 * @param {Date|Time} time 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定时间初始时间戳(该小时00:00的时间戳) */ getTimeBySetHours(hours, time, getAll = false) { const date = this.getDateObj(time) date.setHours(date.getHours() + hours) let startTime = date.getTime() if (!getAll) { const realdate = this.getDate('Y-m-d H:00:00', startTime) startTime = this.getTimeByDateAndTimezone(realdate) } return startTime } /** * 根据设置的周数获取指定日期N周后(前)的时间戳 * @param {Number} weeks 周数 * @param {Date|Time} time 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳) */ getTimeBySetWeek(weeks, time, getAll = false) { const date = this.getDateObj(time) const dateInfo = this.getTimeInfo(time) const day = dateInfo.nWeek const offsetDays = 1 - day weeks = weeks * 7 + offsetDays date.setDate(date.getDate() + weeks) let startTime = date.getTime() if (!getAll) { const realdate = this.getDate('Y-m-d 00:00:00', startTime) startTime = this.getTimeByDateAndTimezone(realdate) } return startTime } /** * 根据设置的月数获取指定日期N月后(前)的时间戳 * @param {Number} monthes 月数 * @param {Date|Time} time 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳) */ getTimeBySetMonth(monthes, time, getAll = false) { const date = this.getDateObj(time) date.setMonth(date.getMonth() + monthes) let startTime = date.getTime() if (!getAll) { const realdate = this.getDate('Y-m-01 00:00:00', startTime) startTime = this.getTimeByDateAndTimezone(realdate) } return startTime } /** * 根据设置的季度数获取指定日期N个季度后(前)的时间戳 * @param {Number} quarter 季度 * @param {Date|Time} time 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳) */ getTimeBySetQuarter(quarter, time, getAll = false) { const date = this.getDateObj(time) const dateInfo = this.getTimeInfo(time) date.setMonth(date.getMonth() + quarter * 3) const month = date.getMonth() + 1; let quarterN; let mm; if ([1,2,3].indexOf(month) > -1) { // 第1季度 mm = "01"; } else if ([4,5,6].indexOf(month) > -1) { // 第2季度 mm = "04"; } else if ([7,8,9].indexOf(month) > -1) { // 第3季度 mm = "07"; } else if ([10,11,12].indexOf(month) > -1) { // 第4季度 mm = "10"; } let yyyy = date.getFullYear(); let startTime = date.getTime() if (!getAll) { const realdate = this.getDate(`${yyyy}-${mm}-01 00:00:00`, startTime) startTime = this.getTimeByDateAndTimezone(realdate) } return startTime } /** * 根据设置的年数获取指定日期N年后(前)的时间戳 * @param {Number} year 月数 * @param {Date|Time} time 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳) */ getTimeBySetYear(year, time, getAll = false) { const date = this.getDateObj(time) date.setFullYear(date.getFullYear() + year) let startTime = date.getTime() if (!getAll) { const realdate = this.getDate('Y-01-01 00:00:00', startTime) startTime = this.getTimeByDateAndTimezone(realdate) } return startTime } /** * 根据时区获取指定时间的偏移时间 * @param {Date|Time} 指定的日期或时间戳 * @param {Number} timezone 时区 */ getTimeByDateAndTimezone(date, timezone) { if (!timezone) { timezone = this.timezone } const thisDate = this.getDateObj(date) const thisTime = thisDate.getTime() const offset = thisDate.getTimezoneOffset() const offsetTime = offset * 60000 + timezone * 3600000 return thisTime - offsetTime } /** * 根据指定的时间类型获取时间范围 * @param {String} type 时间类型 hour:小时 day:天 week:周 month:月 * @param {Number} offset 时间的偏移量 * @param {Date|Time} thistime 指定的日期或时间戳 * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳) */ getTimeDimensionByType(type, offset = 0, thistime, getAll = false) { let startTime = 0 let endTime = 0 switch (type) { case 'hour': { startTime = this.getTimeBySetHours(offset, thistime, getAll) endTime = getAll ? startTime : startTime + 3599999 break } case 'day': { startTime = this.getTimeBySetDays(offset, thistime, getAll) endTime = getAll ? startTime : startTime + 86399999 break } case 'week': { startTime = this.getTimeBySetWeek(offset, thistime, getAll) endTime = getAll ? startTime + 86400000 * 6 : startTime + 86400000 * 6 + 86399999 break } case 'month': { startTime = this.getTimeBySetMonth(offset, thistime, getAll) const date = this.getDateObj(this.getDate('Y-m-d H:i:s', startTime)) const nextMonthFirstDayTime = new Date(date.getFullYear(), date.getMonth() + 1, 1).getTime() endTime = getAll ? nextMonthFirstDayTime - 86400000 : this.getTimeByDateAndTimezone( nextMonthFirstDayTime) - 1 break } case 'quarter': { startTime = this.getTimeBySetQuarter(offset, thistime, getAll) const date = this.getDateObj(this.getDate('Y-m-d H:i:s', startTime)) const nextMonthFirstDayTime = new Date(date.getFullYear(), date.getMonth() + 3, 1).getTime() endTime = getAll ? nextMonthFirstDayTime - 86400000 : this.getTimeByDateAndTimezone( nextMonthFirstDayTime) - 1 break } case 'year': { startTime = this.getTimeBySetYear(offset, thistime, getAll) const date = this.getDateObj(this.getDate('Y-m-d H:i:s', startTime)) const nextFirstDayTime = new Date(date.getFullYear() + 1, 0, 1).getTime() endTime = getAll ? nextFirstDayTime - 86400000 : this.getTimeByDateAndTimezone( nextFirstDayTime) - 1 break } } return { startTime, endTime } } }