1. 前言
需要做一个场次预定的小程序,需要H5和微信小程序两端。在开发中有很多时间需要进行计算处理。返回的时间格式多种多样,还有用作倒计时结束的时间戳等,如何进行统一处理,就是一个需要解决的问题。
2. 将秒转换为 MM:SS 格式
- 这是直接拷贝另一个项目同事的代码,分析一下代码;
- 判断出入的秒数,其实这里应该判断小于等于0时直接返回 00:00;
- 然后将秒数转换为整数;
- 计算分钟数,判断如果小于10就补0;
- 计算秒数,判断如果小于10就补0;
- 最后拼接字符串返回 MM:SS 格式的字符串。
/**
* @description 传入秒 转成时分秒 90.00s =>
*/
export const secondsToTime = (seconds) => {
// console.log('seconds',seconds);
if(seconds == 0) return '00:00'
let result = parseInt(seconds);
let m = Math.floor((result / 60) % 60) < 10 ? '0' + Math.floor((result / 60) % 60) : Math.floor((result / 60) % 60);
let s = Math.floor(result % 60) < 10 ? '0' + Math.floor(result % 60) : Math.floor(result % 60);
return `${m}:${s}`;
}
3. 不同时间字符串的格式化
- 将 YYYY-mm-dd HH:MM:SS 转化为 mm-dd;
- 将 YYYY-mm-dd HH:MM:SS 转化为 HH:MM;
- 将 HH:MM:SS 转化为 HH:MM;
- 将结束毫秒级时间戳转换为分秒的数字。
// 日期处理 将 YYYY-mm-dd HH:MM:SS 转化为 mm-dd
function dateFormat(date){
date = date.replace(/-/g, '/');
date = +new Date(date);
return _dateFormat(date, 'mm-dd')
}
// 选中获取时段 将 YYYY-mm-dd HH:MM:SS 转化为 HH:MM
function chooseTime(time){
let [ date, timeStr ] = time.split(' ');
return hourFormat(timeStr);
}
// 时间时分格式化 将 HH:MM:SS 转化为 HH:MM
function hourFormat(time){
let [hour, minute] = time.split(':');
return `${hour}:${minute}`;
}
// 支付倒计时 将结束毫秒级时间戳转换为分秒的数字
function getLimitPayTime(limit_pay_time){
let limit_pay_time = (limit_pay_time - +new Date()) / 1000;
if(limit_pay_time <= 0){
return {
minute: 0,
second: 0
}
}
return {
minute: Math.floor(limit_pay_time / 60),
second: limit_pay_time % 60
}
}
4. 格式化
// 日期格式化
export const _dateFormat = (date = +new Date(), fmt = `YYYY-mm-dd HH:MM:SS`) => {
if(util.isString(date)){
date = date.replace(/-/g, '/');
}
if (!+new Date(date)) return date;
date = new Date(date);
const opts = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString(), // 秒
};
return _format(opts, fmt);
};
// 格式优化
export const _format = (opts = {}, fmt = `YYYY-mm-dd HH:MM:SS`) => {
let ret;
Object.keys(opts).forEach((key) => {
ret = new RegExp(`(${key})`).exec(fmt);
if (ret)
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opts[key] : opts[key].padStart(ret[1].length, "0")
);
});
return fmt;
}
4.1 解决【将 YYYY-mm-dd HH:MM:SS 转化为 mm-dd】
- 传入 time 模拟 2024-08-16 20:47:30。
_dateFormat(time, 'mm-dd')
2. 运行结果
4.2 解决【将 YYYY-mm-dd HH:MM:SS 转化为 HH:MM】
- 传入 time 模拟 2024-08-16 20:47:30。
_dateFormat(time,'HH:MM')
2. 运行结果
4.3 解决【将 HH:MM:SS 转化为 HH:MM】
- 传入 time 模拟 20:47:30。
_dateFormat(`2024-01-01 ${time}`,'HH:MM')
2. 运行结果
4.4 解决【将结束毫秒级时间戳转换为分秒的数字】
- 传入 time 是 limit_dt - (+new Date()) 毫秒级时间戳。
_dateFormat(time, 'MM:SS')
2. 运行结果
5. 解决后的倒计时分秒获取
// 倒计时时间获取操作
function countdownHandle(limit_dt){
let time = limit_dt - (+new Date());
let [minute, second] = [0, 0];
if(time > 0){
[minute, second] = _dateFormat(time, 'MM:SS').split(':').map(Number);
}
return {minute, second};
}
6. 总结
- 解决问题三的办法,就是由于只需要获取后边的小时和分,所以可以直接写死一个年月日,拼接一个完整的时间字符串,然后获取这个完整时间字符串的时分;解决办法主要是借助了固定年月日拼接一个完整的时间字符串,不会影响最后获取时分字符串。
- 解决问题四的办法,就是时间戳也是从0开始,因此可以利用这一点,将剩余时间【也就是倒计时时间戳】直接传唤为完整时间字符串,再获取字符串中的分秒,作为我们倒计时的结果。但是需要注意,因为初始时间是1970-01-01 08:00:00,因此此种处理办法只能获取分秒的倒计时时间戳,不能获取小时和天的时间戳。
- 错误示例:
3. 注意问题四虽然可以使用此方案解决,但是需要注意时间不能大于59分钟,因为大于会时间进制,增加一小时,导致获取错误。
- 错误示例:
7. 思考
那么有没有通过这种方法完美实现天、时、分、秒的倒计时呢?可以看到,上边这种方法是解决了我当前项目中出现的所有时间格式化问题,但是还是会出现一些超出限制的意外问题,就比如最后的倒计时,当然,也有可能还有其他问题,只是目前我还没发现。所以目前思考可以用这个方法怎么补全最后出现倒计时小时开始就不能准确获取的问题。
8. 解决思路
使用一个基准时间,然后加上倒计时时间戳,然后再格式化转换!
8.1 实现结果
可以看到,当小时时间大于24时,可以满足我们的要求,但是小于24小时的时候,就会出现错误,出现这个问题的原因还是时间进制的问题,也就是说在我们倒计时出现大于时间进制的时候,比如我们要出现【80:30】80分30秒的倒计时时,这种方式还是不能直接处理,还是需要我们判断转换。但是最少这种方式简化了当前我项目中所有出现时间格式化问题的处理。一个方法,并不能解决所有的问题,思考更多的解决办法,有利于找到更加简便的、快捷的处理问题的思路。