/**
- 时间格式化
- @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;
}