UNPKG

ph-utils

Version:

js 开发工具集,前后端都可以使用(commonjs和es module)

219 lines (218 loc) 6.63 kB
/** * node 和 web 端日期处理工具类 */ // 配置日期格式的正则表达式 const REGEX_FORMAT = /yy(?:yy)?|([HMmds])\1?|(S)?/g; // 由于 Date.parse() 不能正确解析 yyyy-dd-mm 格式的日期, 所以匹配手动解析 const REGEX_PARSE = /^(\d{4})-?(\d{1,2})-?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d{1,3})?$/; const ofArgs = { start: [0, 0, 1, 0, 0, 0, 0], end: [0, 11, -2, 23, 59, 59, 999], }; const units = { Date: ["date", "Date", "day", "Day", "D", "d"], Month: ["Month", "month", "m"], Year: ["Year", "year", "y"], Hours: ["Hours", "hours", "H"], Minutes: ["Minutes", "Minute", "minute", "minutes", "M"], Seconds: ["Seconds", "seconds", "Second", "second", "s"], Milliseconds: [ "Milliseconds", "Millisecond", "milliseconds", "illisecond", "S", ], }; /** * 不足位数, 前位补 0 * @param s 日期数字 * @param l 截取位数 * @returns {string} 补0后的日期数字 */ function p(s, l = 2) { /* * 由于年份最多为4为,所以前面先添3个0 * slice() 从后开始提前字符串 */ return `000${s}`.slice(l * -1); } /** * 将单位转换为首字母大写, 例如:hours -> Hours * @param unit hours * @returns */ function getUnit(unit) { let period = null; for (const [key, value] of Object.entries(units)) { if (value.includes(unit)) { period = key; break; } } if (period == null) { throw new Error(`Invalid unit: ${unit}`); } return period; } /** * 获取指定日期某个月的最后一天 * @param date 日期 * @param month 月份, 如果不传, 则当前月的最后一天 * @returns */ function getLastDayOfMonth(date, month) { // 获取下个月的第一天 const lastDate = new Date(date.getFullYear(), (month || date.getMonth()) + 1, 1); // 将下个月的第一天的日期减去一天,得到当前月的最后一天 lastDate.setDate(lastDate.getDate() - 1); // 返回最后一天的日期 return lastDate.getDate(); } /** * 将日期格式化为指定形式的字符串 * @param date 日期 * @param pattern 格式化字符串 yyyy - 年, mm - 月, dd - 日, HH - 小时, MM - 分钟, ss - 秒, S - 毫秒, 默认: yyyy-mm-dd HH:MM:ss */ export function format(date, pattern = "yyyy-mm-dd HH:MM:ss") { // eslint-disable-next-line date = parse(date); const d = date.getDate(); const y = date.getFullYear(); const m = date.getMonth(); const H = date.getHours(); const M = date.getMinutes(); const s = date.getSeconds(); const flags = { yy: p(y), yyyy: y, m: m + 1, mm: p(m + 1), d: d, dd: p(d), H: H, HH: p(H), M: M, MM: p(M), s: s, ss: p(s), S: p(date.getMilliseconds(), 3), }; if (pattern != null) { return pattern.replace(REGEX_FORMAT, (flag) => { if (flag in flags) { return flags[flag]; } return flag; }); } return String(date.getTime()); } /** * 将指定的参数解析为日期对象(Date) * 参考 dayjs 实现, 也可以参考 https://github.com/nomiddlename/date-format * @param date 待解析的日期参数 */ export function parse(date) { if (date == null) return new Date(); if (typeof date === "string" && !/Z$/i.test(date)) { const d = date.match(REGEX_PARSE); if (d) { return new Date(d[1], d[2] - 1, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, d[7] || 0); } } if (typeof date === "number") { return new Date(date <= 9999999999 ? date * 1000 : date); } return new Date(date); } /** * 设置日期的开始或者结束的点 * @param date 日期,能够被 parse 解析的日期 * @param unit 单位,Date|date, 默认为 Date * @param isEnd true则为 endOf */ export function dateOf(date, unit, isEnd = false) { /* 如果是设置某一天的开始时刻, 就需要将时、分、秒、毫秒设置为0,依次类推设置 */ const periods = [ "Year", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds", ]; let index = periods.indexOf(getUnit(unit || "Date")); const clone = parse(date); index++; const setValues = ofArgs[isEnd === true ? "end" : "start"]; for (const len = periods.length; index < len; index++) { let value = setValues[index]; if (value === -2) { // 设置为某个月的最后一天的日期 value = getLastDayOfMonth(clone); } Date.prototype["set" + periods[index]].apply(clone, [ setValues[index], ]); } return clone; } /** * 设置日期的开始的点 * @param date 日期,能够被 parse 解析的日期 * @param unit 单位,Date|date, 默认为 Date * @returns */ export function startOf(date, unit) { return dateOf(date, unit); } /** * 设置日期的结束点 * @param date 日期,能够被 parse 解析的日期 * @param unit 单位,Date|date, 默认为 Date * @returns */ export function endOf(date, unit) { return dateOf(date, unit, true); } /** * 获取时间戳 * @param ctime 时间 * @param pre 精度, s - 精确到秒, ms - 精确到毫秒, 默认: s * @returns */ export function timestamp(ctime, pre = "s") { let tm = parse(ctime).getTime(); return pre === "s" ? Math.floor(tm / 1000) : tm; } /** * 日期加上指定时间后的日期 * @param date 指定的日期 * @param num 需要添加的数字, 如果这个参数传递一个小于0的数字,则就是日期减去相应的数字 * @param unit 需要添加的单位,date - 加减天数 * @param fmt 可选参数,如果传递了格式化的单位,则返回格式化后的日期, 格式化字符串 yyyy - 年, mm - 月, dd - 日, HH - 小时, MM - 分钟, ss - 秒 * @returns {Date | string} 如果传递了 fmt 参数,则返回 string,否则返回 Date */ export function add(date, num, unit, fmt) { let sdate = new Date(); if (date != null) { sdate = parse(date); } // eslint-disable-next-line unit = getUnit(unit); let fn = "set" + unit; let gn = "get" + unit; // @ts-ignore let oldValue = Date.prototype[gn].apply(sdate); // @ts-ignore Date.prototype[fn].apply(sdate, [oldValue + num]); if (typeof fmt === "string") { return format(sdate, fmt); } else { return sdate; } }