UNPKG

yao-dateutils

Version:

Date工具:时间计算、时间取整,格式化字符串类似JAVA的SimpleDateFormat,如"yyyy-MM-dd HH:mm:ss.SSS a"

501 lines (463 loc) 17.9 kB
/** * 日期工具类 */ const str_toLength = Symbol(); class DateUtils { /** * 字符串长度控制方法 * @param {string} str 字符串 * @param {Number} length 目标长度 * @param {string} fillstring 填充字符 * @returns {string} 返回目标长度的字符串 */ static [str_toLength](str, length, fillstring = '0') { if (!str) { str = fillstring; } if ('string' !== typeof (str)) { str = str.toString(); } if (str.length < length) while (str.length < length) { str = fillstring + str; } if (str.length > length) { str = str.substring(str.length - length, str.length); } return str; } // === 时间格式化 ======================================================================================= /** * 格式化日期时间 * @param {Date} date 日期时间对象 * @param {string} format 格式化字符串 * yyyy:年份(如2019); * yy:短年份(如19); * MM:月份,10以下用0补位; * M:月份(1~12); * dd:日子,10以下用0补位; * d:日子(0~31); * HH:小时,10以下用0补位; * H:小时(0~23); * hh:小时,10以下用0补位; * h:小时(0~11); * mm:分钟,10以下用0补位; * m:分钟(0~59); * ss:秒,10以下用0补位; * s:秒(0~59); * SSS:毫秒,100以下用0补位; * S:毫秒(0~999); * a:am或pm * @returns {string} 日期字符串 */ static format(date, format) { if (!date) { return null; } let o = { // 年份 "yyyy": date.getFullYear(), "yy": DateUtils[str_toLength](date.getFullYear(), 2), // 月份 "MM": DateUtils[str_toLength](date.getMonth() + 1, 2), "M": date.getMonth() + 1, // 日 "dd": DateUtils[str_toLength](date.getDate(), 2), "d": date.getDate(), // 小时(24) "HH": DateUtils[str_toLength](date.getHours(), 2), "H": date.getHours(), // 小时(12) "hh": DateUtils[str_toLength](date.getHours() % 12, 2), "h": date.getHours() % 12, // 分 "mm": DateUtils[str_toLength](date.getMinutes(), 2), "m": date.getMinutes(), // 秒 "ss": DateUtils[str_toLength](date.getSeconds(), 2), "s": date.getSeconds(), // 秒 "SSS": DateUtils[str_toLength](date.getMilliseconds(), 3), "S": date.getMilliseconds(), // 上午|下午 "a": date.getHours() < 12 ? 'am' : 'pm', }; for (let k in o) { let reg = new RegExp(k, 'g'); let ms = reg.exec(format); if (ms && ms.length) for (let i = 0; i < ms.length; i++) { let p = ms[i]; let v = o[k]; format = format.replace(p, v); } } return format; } /** * 将字符串转换成日期 * @param {string} datestr 日期时间字符串 * @param {string} format 格式化字符串 * yyyy:年份(如2019); * yy:短年份(如19); * MM:月份; * dd:日子; * HH:小时(0~23); * hh:小时(0~11); * mm:分钟; * ss:秒; * SSS:毫秒; * a:am或pm * @returns {Date} 日期时间对象 */ static parse(datestr, format = "yyyy-MM-dd HH:mm:ss") { if (!datestr) { return null; } let fullYearPos = format.indexOf("yyyy"); let shortYearPos = format.indexOf("yy"); let monthPos = format.indexOf("MM"); let dayhPos = format.indexOf("dd"); let hourPos = format.indexOf("hh"); let HOURPos = format.indexOf("HH"); let minutePos = format.indexOf("mm"); let secondsPos = format.indexOf("ss"); let mSecondsPos = format.indexOf("SSS"); let aPos = format.indexOf("a"); let fullYear = fullYearPos != -1 ? datestr.substring(fullYearPos, fullYearPos + 4) : null; let shortYear = shortYearPos != -1 ? datestr.substring(shortYearPos, shortYearPos + 2) : null; let month = monthPos != -1 ? datestr.substring(monthPos, monthPos + 2) : null; let day = dayhPos != -1 ? datestr.substring(dayhPos, dayhPos + 2) : null; let minute = minutePos != -1 ? datestr.substring(minutePos, minutePos + 2) : null; let seconds = secondsPos != -1 ? datestr.substring(secondsPos, secondsPos + 2) : null; let mSeconds = mSecondsPos != -1 ? datestr.substring(mSecondsPos, mSecondsPos + 3) : null; let a = aPos != -1 ? datestr.substring(aPos, aPos + 2) : null; let hour = hourPos != -1 ? datestr.substring(hourPos, hourPos + 2) : null; let HOUR = HOURPos != -1 ? datestr.substring(HOURPos, HOURPos + 2) : null; let d4 = /^\d{4}$/; let d2 = /^\d{2}$/; let d3 = /^\d{3}$/; let aa = /^[ap]m$/; if ( !(!fullYear || d4.test(fullYear)) || !(!shortYear || d2.test(shortYear)) || !(!month || d2.test(month)) || !(!day || d2.test(day)) || !(!hour || d2.test(hour)) || !(!HOUR || d2.test(HOUR)) || !(!minute || d2.test(minute)) || !(!seconds || d2.test(seconds)) || !(!mSeconds || d3.test(mSeconds)) || !(!a || aa.test(a)) ) { return null; } fullYear = parseInt(fullYear ? fullYear : (shortYear ? '20' + shortYear : 1970)); month = parseInt(month ? month : 1); day = parseInt(day ? day : 1); hour = parseInt(hour ? hour : 0); HOUR = parseInt(HOUR ? HOUR : (hour < 12 && a === 'pm') ? hour + 12 : hour); minute = parseInt(minute ? minute : 0); seconds = parseInt(seconds ? seconds : 0); mSeconds = parseInt(mSeconds ? mSeconds : 0); let date = new Date(); date.setFullYear(fullYear); date.setMonth(month - 1); date.setDate(day); date.setHours(HOUR); date.setMinutes(minute); date.setSeconds(seconds); date.setMilliseconds(mSeconds); return date; } // === 时间取整 ======================================================================================= /** * 时间向外取整到月(如:2019-4-16 10:32:38 > 2019-5-1 00:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static ceil2month(date) { let _date = DateUtils.floor2month(date); _date.setMonth(_date.getMonth() + 1); return _date; } /** * 时间向内取整到月(如:2019-4-16 10:32:38 > 2019-4-1 00:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static floor2month(date) { let _date = new Date(date.getTime()); _date.setMilliseconds(0); _date.setSeconds(0); _date.setMinutes(0); _date.setHours(0); _date.setDate(1); return _date; } /** * 时间进行“四舍五入”取整到月(如:2019-4-14 10:32:38 > 2019-4-1 00:00:00, 2019-4-16 10:32:38 > 2019-5-1 00:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static round2month(date) { let _date1 = DateUtils.floor2month(date); let _date2 = DateUtils.ceil2month(date); if ((_date2.getTime() - date.getTime()) <= (date.getTime() - _date1.getTime())) { return _date2; } else { return _date1; } } /** * 时间向外取整到日期(如:2019-01-01 01:01:01 > 2019-01-02 00:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static ceil2day(date) { let _date = DateUtils.floor2day(date); _date.setDate(_date.getDate() + 1); return _date; } /** * 时间向内取整到日期(如:2019-01-01 01:01:01 > 2019-01-01 00:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static floor2day(date) { let _date = new Date(date.getTime()); _date.setMilliseconds(0); _date.setSeconds(0); _date.setMinutes(0); _date.setHours(0); return _date; } /** * 时间“四舍五入”取整到日期(如:2019-01-01 01:01:01 > 2019-01-01 00:00:00, 2019-01-01 12:01:01 > 2019-01-02 00:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static round2day(date) { let _date1 = DateUtils.floor2day(date); let _date2 = DateUtils.ceil2day(date); if ((_date2.getTime() - date.getTime()) <= (date.getTime() - _date1.getTime())) { return _date2; } else { return _date1; } } /** * 时间向外取整到小时(如:2019-01-01 01:01:01 > 2019-01-01 02:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static ceil2hour(date) { let _date = DateUtils.floor2hour(date); _date.setHours(_date.getHours() + 1); return _date; } /** * 时间向内取整到小时(如:2019-01-01 01:01:01 > 2019-01-01 01:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static floor2hour(date) { let _date = new Date(date.getTime()); _date.setMilliseconds(0); _date.setSeconds(0); _date.setMinutes(0); return _date; } /** * 时间“四舍五入”取整到小时(如:2019-01-01 01:01:01 > 2019-01-01 01:00:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static round2hour(date) { let _date1 = DateUtils.floor2hour(date); let _date2 = DateUtils.ceil2hour(date); if ((_date2.getTime() - date.getTime()) <= (date.getTime() - _date1.getTime())) { return _date2; } else { return _date1; } } /** * 时间向外取整到分钟(如:2019-01-15 01:01:01 > 2019-01-15 01:01:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static ceil2minute(date) { let _date = DateUtils.floor2minute(date); _date.setMinutes(_date.getMinutes() + 1); return _date; } /** * 时间向内取整到分钟(如:2019-01-15 01:01:01 > 2019-01-15 01:01:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static floor2minute(date) { let _date = new Date(date.getTime()); _date.setMilliseconds(0); _date.setSeconds(0); return _date; } /** * 时间“四舍五入”取整到分钟(如:2019-01-15 01:01:01 > 2019-01-15 01:01:00) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static round2minute(date) { let _date1 = DateUtils.floor2minute(date); let _date2 = DateUtils.ceil2minute(date); if ((_date2.getTime() - date.getTime()) <= (date.getTime() - _date1.getTime())) { return _date2; } else { return _date1; } } /** * 时间向外取整到秒(如:2019-01-15 01:01:01.231 > 2019-01-15 01:01:02.000) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static ceil2second(date) { let _date = DateUtils.floor2second(date); _date.setSeconds(_date.getSeconds() + 1); return _date; } /** * 时间向内取整到秒(如:2019-01-15 01:01:01.231 > 2019-01-15 01:01:01.000) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static floor2second(date) { let _date = new Date(date.getTime()); _date.setMilliseconds(0); return _date; } /** * 时间“四舍五入”取整到秒(如:2019-01-15 01:01:01.231 > 2019-01-15 01:01:01.000) * @param {Date} date 日期时间 * @returns {Date} 取整后的日期时间 */ static round2second(date) { let _date1 = DateUtils.floor2second(date); let _date2 = DateUtils.ceil2second(date); if ((_date2.getTime() - date.getTime()) <= (date.getTime() - _date1.getTime())) { return _date2; } else { return _date1; } } // === 时间计算 ======================================================================================= /** * 给日期时间增加天数(如:2019-01-01 01:01:01 . addDay(1) > 2019-01-02 01:01:01) * @param {Date} date 日期时间 * @param {number} day 天数 * @returns {Date} 增加天数后的日期时间 */ static addDay(date, day) { return new Date(date.getTime() + day * 86400 * 1000); } /** * 给日期时间增加小时数(如:2019-01-01 01:01:01 . addHour(1) > 2019-01-01 02:01:01) * @param {Date} date 日期时间 * @param {number} hour 小时数 * @returns {Date} 增加小时数后的日期时间 */ static addHour(date, hour) { return new Date(date.getTime() + hour * 3600 * 1000); } /** * 给日期时间增加分钟数(如:2019-01-01 01:01:01 . addMinute(1) > 2019-01-01 01:02:01) * @param {Date} date 日期时间 * @param {number} minute 分钟数 * @returns {Date} 增加分钟数后的日期时间 */ static addMinute(date, minute) { return new Date(date.getTime() + minute * 60 * 1000); } /** * 给日期时间增加秒数(如:2019-01-01 01:01:01 . addSecond(1) > 2019-01-01 01:01:02) * @param {Date} date 日期时间 * @param {number} sec 秒数 * @returns {Date} 增加秒数后的日期时间 */ static addSecond(date, sec) { return new Date(date.getTime() + sec * 1000); } /** * 给日期时间增加秒数(如:2019-01-01 01:01:01.000 . addMillisecond(1) > 2019-01-01 01:01:02.001) * @param {Date} date 日期时间 * @param {number} msec 毫秒数 * @returns {Date} 增加毫秒数后的日期时间 */ static addMillisecond(date, msec) { return new Date(date.getTime() + msec); } // === 时间对比 ======================================================================================= /** * 返回 日期1 减去 日期2 的日期差(totalxxx为小数时向外取整,如计算得出totaldays==3.1,则totaldays实际返回值为4) * @param {Date} date1 日期1 * @param {Date} date2 日期2 * @returns {Object} {days:相差天数, hours:余下的小时数, minutes:余下的分钟数, seconds:余下的秒数, milliseconds:余下的毫秒数, totaldays:总相差天数, totalhours:总共相差小时数, totalminutes:总共相差分钟数, totalseconds:总共相差秒数, totalmilliseconds:总共相差毫秒数} */ static subtract(date1, date2) { let time = date1.getTime() - date2.getTime(); let mday = 24 * 60 * 60 * 1000; let mhour = 60 * 60 * 1000; let mminute = 60 * 1000; let mseconds = 1000; return { days: parseInt(time / mday), hours: parseInt(time % mday / mhour), minutes: parseInt(time % mday % mhour / mminute), seconds: parseInt(time % mday % mhour % mminute / mseconds), milliseconds: parseInt(time % mday % mhour % mminute % mseconds), totaldays: Math.ceil(time / mday), totalhours: Math.ceil(time / mhour), totalminutes: Math.ceil(time / mminute), totalseconds: Math.ceil(time / mseconds), totalmilliseconds: time }; } // === 周期计算 ======================================================================================= /** * 将一段时间均匀拆分成顺序时间点数组(返回的数组长度等于count) * @param {Number} count 返回时间点个数; * @param {Date} start 开始时间,如果开始时间大于结束时间,则返回从大到小的列表 * @param {Date} end 结束时间,如果结束时间大于开始时间,则返回从小到大的列表(默认为当前时间点) * @returns {Array} 连续时间刻度的数组 */ static splitPeriodTime(count, start, end = new Date()) { if (count <= 0) { return []; } let subtractValue = DateUtils.subtract(end, start); let timeItem = subtractValue.totalmilliseconds / (count - 1); let arr = [new Date(start.getTime())]; while (arr.length < count - 1) { let t = start.getTime() + timeItem * arr.length; arr.push(new Date(t)) } if (count > 1) { arr.push(new Date(end.getTime())); } return arr; } /** * 获得周期内某一进度点的时间:把时间周期切分成100等分,取得progress所在进度的时间 * @param {Number} progress 进度点,范围[0~1)的符点数,精度为两位小数 * @param {} start 开始时间 * @param {*} end 结束时间(默认为当前时间点) */ static getProgressTime(progress, start, end = new Date()) { let idx = parseInt(progress * 100); if (idx < 0 || idx >= 100) { throw Error('progress must be number and in [0, 1)'); } let arr = DateUtils.splitPeriodTime(100, start, end); return arr[idx]; } } module.exports = DateUtils;