- 计时器(有requireJs时define,否则加入window或global)
(()=>{
"use strict";
const frozenErrStr = "Frozen object is not supported for this function!";
const frozenErrFn = function(){console.error(frozenErrStr);};
/**返回冻结的计时器时间对象*/
const frozenTimerObjFn = function(timerObj){
return new Proxy(timerObj,{
set: function(obj, prop, value){
frozenErrFn();
return false;
},
deleteProperty: function(target, property){
frozenErrFn();
return false;
},
defineProperty: function(target, prop, descriptor){
frozenErrFn();
return false;
},
setPrototypeOf: function(target, prototype) {
frozenErrFn();
return false;
},
preventExtensions(target) {
frozenErrFn();
return false;
},
});
}
/**
* 秒数转天时分秒
* @param timeObj 计时对象
* @param timeSec 时间间隔(秒)
* @returns timerObj ==>> {day,hour,min,sec}
*/
const diffTime = (timeObj,timeSec)=>{
//一分钟内
if(timeSec<=59){
timeObj.day=0;
timeObj.hour=0;
timeObj.min=0;
timeObj.sec=timeSec;
}
//一小时内
else if(timeSec<=3599){
timeObj.day=0;
timeObj.hour=0;
const min=Math.floor(timeSec/60);
timeObj.min=min;
timeObj.sec=timeSec%60;
}
//一天内
else if(timeSec<=86399){
timeObj.day=0;
const min=Math.floor(timeSec/60);
timeObj.sec=timeSec%60;
timeObj.hour=Math.floor(min/60);
timeObj.min=min%60;
}
//一天及以上
else{
const min=Math.floor(timeSec/60);
timeObj.sec=timeSec%60;
const hour=Math.floor(min/60);
timeObj.min=min%60;
const day=Math.floor(hour/24);
timeObj.hour=hour%24;
timeObj.day=day;
}
// const timeMin = timeSec <= 59 ? 0 : Math.floor(timeSec/60);
// const timeHour = timeSec <= 3599 ? 0 : Math.floor(timeMin/60);
// const timeDay = timeSec <= 86399 ? 0 : Math.floor(timeHour/24);
// timeObj.sec=timeSec%60;
// timeObj.min=timeMin%60;
// timeObj.hour=timeHour%24;
// timeObj.day=timeDay;
};
const newTimerObj = function(){
return {startTime:new Date().getTime(),stopTime:null,day:0,hour:0,min:0,sec:0,interval:null};
}
const timerObj2Str = timerObj=>{
const zero = "0";
return (timerObj.day>=1 ? (timerObj.day+" ").padStart(3,zero) : "") +
(timerObj.hour+":").padStart(3,zero) +
(timerObj.min+":").padStart(3,zero) +
(timerObj.sec+"").padStart(2,zero);
};
const simpleTimeFormat = date=>{
if(!date)return "";
const zero = "0";
return (date.getHours()+":").padStart(3,zero) + (date.getMinutes()+":").padStart(3,zero) + (date.getSeconds()+"").padStart(2,zero);
};
const simpleDateTimeFormat = date=>{
if(!date)return "";
const zero = "0";
return simpleTimeFormat(date) + " " + (date.getMonth()+1+"-").padStart(3,zero) + (date.getDate()+" ").padStart(3,zero) + (date.getFullYear()+"").padStart(2,zero);
}
/**
* 简单但功能完善的计时器,
* 默认创建后自动开始计时,start(date)开始计时,stop()停止计时,reset(date)复位,restart()重新计时,getTimeObj(obj)获取计时对象
* @param callback 计时时的回调函数 function(timeObj){-每秒想做的事-} timeObj为字符串或{day,hour,min,sec,startTime,stopTime},默认控制台打印格式化时间字符
* @param this4cb 回调函数内想要指向的this,默认为调用者
* @param ifObjPara4cb 为空则回调函数的参数为格式化时间字符串,不为空则为冻结对象{day,hour,min,sec}
* @param extraFixSec 额外的修正频率(大于1小于31),为空不额外再修正,不为空时,sec%extraFixSec==0时修正
* @param notStartOnCreate 为true则创建时不开始计时
* @param inTimerObj 如果传入对象,则获取一个完全可控的timerObj
*/
function simpleTimer(callback,this4cb,ifObjPara4cb,extraFixSec,notStartOnCreate,inTimerObj){
if(this4cb == null || typeof this4cb != 'object'){
this4cb = this;
}
if(inTimerObj!=null && typeof inTimerObj != "object"){
inTimerObj = {};
}
//计时对象
const timerObj = inTimerObj?Object.assign(inTimerObj,newTimerObj()):newTimerObj();
//冻结的计时对象代理
const frozenTimerObj = inTimerObj?timerObj:frozenTimerObjFn(timerObj);
//重设回调函数
timerObj.setCallback = (newCb,newThis4cb,newifObjPara4cb)=>{
if(newCb == null || typeof newCb != 'function'){
if(callback == null || typeof callback != 'function'){
this4cb = null;
ifObjPara4cb = null;
callback = timeStr => console.log(timeStr);
}else{
console.error("typeof newCb must be function!");
return false;
}
}else{
callback = newCb.bind(this4cb);
}
if(typeof newThis4cb != 'object'){
console.warn("typeof newThis4cb must be object!");
}else{
this4cb = newThis4cb;
}
if(newifObjPara4cb){
ifObjPara4cb = true;
}else{
ifObjPara4cb = false;
}
return true;
};
timerObj.setCallback(callback,this4cb,ifObjPara4cb);
/**开始到当前时间差,并更新timerObj*/
timerObj.diffTimerObj=()=>{
diffTime(timerObj,Math.floor((new Date().getTime()-timerObj.startTime)/1000));
};
/**每当sec到60时修正一次,并在此计时进位,extraFixSec时额外修正*/
let ifDiff = null;
//设置额外的时间间隔
timerObj.setExtraFixSec = (extraFixSec)=>{
if(typeof extraFixSec != "number" || extraFixSec<=1 || extraFixSec>=31){
extraFixSec = null;
}
ifDiff = extraFixSec != null ? ()=>(++timerObj.sec>=60 || (extraFixSec != null && timerObj.sec%extraFixSec == 0)) : ()=>(++timerObj.sec>=60);
return true;
};
timerObj.setExtraFixSec(extraFixSec);
//开始计时
timerObj.start = function(date){
if(this.interval!=null){
clearInterval(this.interval);
}
if(date){
this.startTime = date.getTime();
}
if(this.startTime == null){
this.startTime = new Date().getTime();
}
this.stopTime = null;
this.diffTimerObj();
if(ifObjPara4cb){
callback(frozenTimerObj);
}
else{
callback(timerObj2Str(timerObj));
}
//每秒计时一次
this.interval = setInterval(()=>{
if(ifDiff()){
timerObj.diffTimerObj();
}
if(ifObjPara4cb){
callback(frozenTimerObj);
}
else{
callback(timerObj2Str(timerObj));
}
},1000);
}.bind(timerObj);
//停止计时
timerObj.stop = ()=>{
clearInterval(timerObj.interval);
timerObj.stopTime = new Date().getTime();
};
//复位
timerObj.reset = (date)=>{
timerObj.start(date||new Date());
};
//重新计时
timerObj.restart = ()=>{
if(timerObj.stopTime!=null && timerObj.startTime!=null){
//停止时长
const time = new Date().getTime() - timerObj.stopTime;
timerObj.startTime=new Date(timerObj.startTime+time).getTime();
timerObj.start();
}else{
timerObj.start(new Date(timerObj.startTime));
}
};
//获取计时对象,当参数不为空且为对象时,将值写入该对象,否则返回frozenTimerObj
timerObj.getTimeObj = (obj)=>{
if(obj!=null && typeof obj=="object"){
obj.day = frozenTimerObj.day;
obj.hour = frozenTimerObj.hour;
obj.min = frozenTimerObj.min;
obj.sec = frozenTimerObj.sec;
obj.startTime = frozenTimerObj.startTime;
obj.stopTime = frozenTimerObj.stopTime;
}else{
obj = frozenTimerObj;
}
return obj;
};
//获取总秒数
timerObj.getSeconds = ()=>{
return timerObj.sec + timerObj.min*60 + timerObj.hour*3600 + timerObj.day*86400;
}
if(!notStartOnCreate){
//直接开始计时
timerObj.start();
}
return frozenTimerObj;
}
const retObj = Object.freeze({new:simpleTimer,frozenTimerObjFn,diffTime,newTimerObj,timerObj2Str,simpleTimeFormat,simpleDateTimeFormat});
let defineOk = false;
if(typeof define === 'function')
try {
define(retObj);
defineOk = true;
} catch (error) {}
if(!defineOk){
if(typeof window === 'object')
window.simpleTimer = retObj;
else if(typeof global == 'object')
global.simpleTimer = retObj;
}
window.simpleTimer = retObj;
})();
- 测试
//无requireJs
var myTimer = simpleTimer.new();
//有requireJs
define(['./simpleTimer'], function (simpleTimer){
simpleTimer.new();
});
- 单独的秒数转天时分秒
/**
* 秒数转天时分秒格式
* @param timer 为对象时表示{day,hour,min,sec},为数字或字符串时表示秒数
* @returns DD HH:MM:SS
*/
function sec2time(timer){
if(timer==null) return null;
let timerObj = null;
if(typeof timer == "object"){
timerObj = timer;
}else{
const timeSec = Number(timer);
if(timeSec<0 || timeSec==NaN) return null;
timerObj = {};
const timeMin = timeSec <= 59 ? 0 : Math.floor(timeSec/60);
const timeHour = timeSec <= 3599 ? 0 : Math.floor(timeMin/60);
const timeDay = timeSec <= 86399 ? 0 : Math.floor(timeHour/24);
timerObj.sec=timeSec%60;
timerObj.min=timeMin%60;
timerObj.hour=timeHour%24;
timerObj.day=timeDay;
}
const zero = "0";
const timeStr = (timerObj.day>=1 ? (timerObj.day+" ").padStart(3,zero) : "") +
(timerObj.hour+":").padStart(3,zero) +
(timerObj.min+":").padStart(3,zero) +
(timerObj.sec+"").padStart(2,zero);
return timeStr;
}