时间的各种格式化集合

176 阅读1分钟

/**

  • 时间格式化
  • @param {String} fmt 格式yyyy-MM-dd hh:mm:ss.S 或t 时间戳
  • @param {Date|String|Number} time 时间,支持+5 day -1 hour等时间段
  • @param {Boolean} isFull time 为时间段时 是否完整天或小时
  • @param {Date|String|Number} fromTime 为时间段时 计算的基准时间
  • @returns {Date|String|Number} */
export function timeF(
 fmt = "yyyy-MM-dd hh:mm:ss",
 time = new Date(),
 isFull = true,
 fromTime = new Date()
) {
 const _fmt = fmt;
 let date;
 if (typeof time === "string") {
   if (/^(((\+|-)\d+)|\d+) (day|hour)+$/.test(time)) {
     let [num, type] = String(time).split(" ");
     const n = Number(num);
     if (type === "day") {
       time = +timeF("t", fromTime) + n * 864 * 1e5;
       if (isFull) {
         time =
           timeF("yyyy/MM/dd", time) + (n >= 0 ? " 23:59:59" : " 00:00:00");
       }
     } else if (type === "hour") {
       time = +timeF("t", fromTime) + n * 36 * 1e5;
       if (isFull) {
         time = timeF("yyyy/MM/dd hh:", time) + (n >= 0 ? "59:59" : "00:00");
       }
     }
   } else {
     time = time.replace(/-/g, "/");
   }
 } else if (typeof time === "number" && time.toString().length === 10) {
   time = time * 1000;
 }
 date = new Date(time);
 if (fmt === "date") {
   return date;
 }
 let o = {
   "M+": date.getMonth() + 1, //月份
   "d+": date.getDate(), //日
   "h+": date.getHours(), //小时
   "m+": date.getMinutes(), //分
   "s+": date.getSeconds(), //秒
   t: date.getTime(), //时间戳
   "q+": Math.floor((date.getMonth() + 3) / 3), //季度
   S: fixZero(date.getMilliseconds(), 3) //毫秒
 };
 if (/(y+)/.test(fmt))
   fmt = fmt.replace(
     RegExp.$1,
     (date.getFullYear() + "").substr(4 - RegExp.$1.length)
   );
 for (let k in o)
   if (new RegExp("(" + k + ")").test(fmt))
     fmt = fmt.replace(
       RegExp.$1,
       RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
     );
 return _fmt === "t" ? Number(fmt) : fmt;
}

/**

  • 获取日期所在周起止时间
  • @param {Date|String|Number} time 对比时间
  • @param {Boolean} sundayFrist 一周的第一天true 周日 false周一
  • @returns {Object} */
export function getTimeWeek(time, fromTime, fmt, sundayFrist = true) {
 // @ts-ignore
 let newTime = timeF("date", time, true, fromTime);
 // @ts-ignore
 let dayCode = newTime.getDay();

 let curTime = timeF(fmt || "yyyy-MM-dd", newTime);
 let startTime = timeF(
   fmt || "yyyy-MM-dd 00:00:00",
   `-${sundayFrist ? dayCode : dayCode - 1} day`,
   true,
   newTime
 );
 let endTime = timeF(
   fmt || "yyyy-MM-dd 23:59:59",
   `+${sundayFrist ? 6 - dayCode : 7 - dayCode} day`,
   true,
   newTime
 );

 return {
   curTime,
   startTime,
   endTime,
   days: [
     timeF("yyyy-MM-dd", startTime),
     timeF("yyyy-MM-dd", "+1 day", true, startTime),
     timeF("yyyy-MM-dd", "+2 day", true, startTime),
     timeF("yyyy-MM-dd", "+3 day", true, startTime),
     timeF("yyyy-MM-dd", "+4 day", true, startTime),
     timeF("yyyy-MM-dd", "+5 day", true, startTime),
     timeF("yyyy-MM-dd", "+6 day", true, startTime)
   ]
 };
}

/**

  • 获取日期所在月起止时间
  • @param {Date|String|Number} time 对比时间 */
export function getTimeMonth(time, fromTime, fmt) {
 const newTime = timeF("date", time, true, fromTime);
 const monthLast = timeF("date", newTime);
 const startTime = timeF(fmt || "yyyy-MM-01 00:00:00", monthLast);
 // @ts-ignore
 monthLast.setMonth(monthLast.getMonth() + 1, 0);
 const endTime = timeF(fmt || "yyyy-MM-dd 23:59:59", monthLast);
 const ym = String(endTime).slice(0, 8);
 const endDay = new Date(monthLast).getDate();
 const days = [];
 let day = 1;
 while (day <= endDay) {
   days.push(ym + String(day).padStart(2, "0"));
   day++;
 }

 time = timeF("date", time);
 return {
   curTime: timeF(fmt || "yyyy-MM-dd", newTime),
   startTime,
   endTime,
   days
 };
}

/**

  • 获取上个月 下个月 起止时间
  • @param {String} type next prev
  • @returns {Object} */
export function getNextMonth(type = "next", fromTime, curFmt) {
 const monthNext = timeF("date", fromTime);
 // @ts-ignore
 monthNext.setMonth(monthNext.getMonth() + (type === "next" ? 1 : -1));
 return getTimeMonth(monthNext, undefined, curFmt);
}

/**

  • atime是否fromTime的近几天/几小时前或后的时间
  • @param {string} time +5 day,-1 hour等时间段
  • @param {Date|String|Number} atime 对比时间
  • @param {Date|String|Number} fromTime 当前时间
  • @param {Boolean} isFull time 为时间段时 是否完整天或小时
  • @returns {Boolean} */
export function isRecentTime(
 time = "+1 day",
 atime,
 isFull = true,
 fromTime = new Date()
) {
 const _btime1 = timeF("t", "+0 " + time.split(" ")[1], isFull, fromTime);
 const _btime2 = timeF("t", time, isFull, fromTime);
 const _atime = timeF("t", "+0 " + time.split(" ")[1], isFull, atime);
 return (+_btime2 - +_atime) * (+_atime - +_btime1) >= 0;
}

/**

  • 时间处理成N分钟的倍数(向下取整)
  • @param {string} [str] 标准时间格式yyyy-MM-dd hh:mm:ss
  • @param {Number} [num] 间隔的分钟
  • @returns {string} */
export function timeStrF(str, num = 5) {
 str = str || String(timeF());
 return str.replace(
   /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(.*)/,
   (_, y, M, d, h, m, s) => {
     const _m = parseInt(String(m / num)) * num;
     return `${y}-${M}-${d} ${h}:${_m < 10 ? "0" : ""}${_m}:00`;
   }
 );
}

/**

  • 时间长短
  • @param {number} time 毫秒数
  • @param {string} fmt 格式,例如 {y}年{d}天{h}小时{m}分{s}秒
  • @param {object} options
  • @param {boolean} [options.clear] 清理前面的0值
  • @param {string} [options.last] 最后一位处理方式,floor:向下取整,ceil:向上取整,round:四舍五入,fix1:保留1位(前面值都是0时候生效)
  • @returns {object} */
export function timeL(time, fmt = "{y}年{d}天{h}小时{m}分{s}秒", options = {}) {
 if (!time) {
   return { t: "" };
 }
 const { clear = true, last = "floor" } = options;
 let o = {
   "{y}": 365 * 24 * 60 * 60 * 1000, //年
   "{d}": 24 * 60 * 60 * 1000, //日
   "{h}": 60 * 60 * 1000, //小时
   "{m}": 60 * 1000, //分
   "{s}": 1000 //秒
 };
 const reg = new RegExp(Object.keys(o).join("|"), "g");
 let fmt_last;
 let first_num = -1;
 let fmt_num = 0;
 fmt.replace(reg, (f) => ((fmt_last = f), ""));
 let data = {};
 let a = Number(time);
 const fun = (num) =>
   last === "fix1" ? Number(num.toFixed(1)) : Math[last](num);
 let str = fmt.replace(reg, (f, i) => {
   // 是否有非0值
   const noVal = first_num == -1;
   let v =
     f === "{s}"
       ? Math.ceil(a / o[f])
       : fmt_last === f && noVal
       ? fun(a / o[f])
       : Math.floor(a / o[f]);
   a %= o[f];
   if (clear && ((v !== 0 && noVal) || fmt_last === f)) {
     first_num = i - fmt_num;
   }
   if (clear && first_num != -1) {
     data[f.replace(/[{}]/g, "")] = v;
   }
   if (first_num == -1) {
     fmt_num += 2;
   }
   return v;
 });
 str = str.slice(first_num);
 data["t"] = str;
 return data;
}

/**

  • 时间戳转为多久之前
  • @param {Number} dateTime 时间戳
  • @param {String | Boolean} format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
  • 如果为布尔值false,无论什么时间,都返回多久以前的格式 */
export function timeFrom(dateTime = null, format = "yyyy.MM.dd") {
 dateTime = +timeF("t", dateTime);
 let timer = (Number(new Date()) - dateTime) / 1000;
 // 如果小于15分钟,则返回"刚刚",其他以此类推
 let tips = "";
 switch (true) {
   case timer < 15 * 60:
     tips = "刚刚";
     break;
   case timer >= 15 * 60 && timer < 3600:
     tips = Math.floor(timer / 60) + "分钟前";
     break;
   case timer >= 3600 && timer < 86400:
     tips = Math.floor(timer / 3600) + "小时前";
     break;
   case timer >= 86400 && timer < 2592000:
     tips = Math.floor(timer / 86400) + "天前";
     break;
   default:
     // 如果format为false,则无论什么时间戳,都显示xx之前
     if (format === false) {
       if (timer >= 2592000 && timer < 365 * 86400) {
         tips = Math.floor(timer / (86400 * 30)) + "个月前";
       } else {
         tips = Math.floor(timer / (86400 * 365)) + "年前";
       }
     } else {
       tips = String(timeF(String(format), dateTime));
     }
 }
 return tips;
}