有這樣的一個場景:給定一個時間區間,需要判定這個時間區間在哪些時間段範圍內.
比如時間段範圍如下:
[["00:00","01:00"],["01:00","02:00"],["02:00","03:00"],["03:00","04:00"],["04:00","05:00"],["05:00","06:00"],["06:00","07:00"],["07:00","08:00"],["08:00","09:00"],["09:00","10:00"],["10:00","11:00"],["11:00","12:00"],["12:00","13:00"],["13:00","14:00"],["14:00","15:00"],["15:00","16:00"],["16:00","17:00"],["17:00","18:00"],["18:00","19:00"],["19:00","20:00"],["20:00","21:00"],["21:00","22:00"],["22:00","23:00"],["23:00","24:00"]]
現在給定一個時間區間 10:15-16:38 ,那麼就需要返回 ["10:00","11:00"],["11:00","12:00"],["12:00","13:00"],["13:00","14:00"],["14:00","15:00"],["15:00","16:00"],["16:00","17:00"] 這些時間段範圍。
1、常規時間區間判定
假設給定的時間區間為 [st, et],時間段範圍為 [t1, t2],那麼 [st, et] 在 [t1, t2] 範圍內的判定依據有以下幾種情況:
- t1 >= st && t2 <= et;
- st >= t1 && st <= t2;
- et >= t1 && et <= t2;
再來看看給定時間區間不在時間段範圍內,即 [st, et] 不在 [t1, t2] 範圍內的判定依據:
- st < t1 && et < t1;
- st > t2 && et > t2;
從上面的判定依據來看,給定時間區間不在時間段範圍內的判定依據更簡單,對其取反,即可得到正確的時間段範圍,下面給出具體的判定程式碼:
function judge(startTime, endTime) {
// 生成24小時時間區間,跨度為1小時
let timeArrays = new Array(24).fill(['', '']).map((item, index) => [(index < 10 ? '0' + index : index) + ':00', ((index + 1) < 10 ? '0' + (index + 1) : (index + 1)) + ':00']);
return timeArrays.filter(item => !((compare(item[0], startTime) && compare(item[0], endTime)) || (compare(startTime, item[1]) && compare(endTime, item[1]))));
}
function compare(startTime, endTime) {
// 將時間轉換為分鐘,再進行比較
let startTimes = startTime.split(':');
let endTimes = endTime.split(':');
let startTimeVal = startTimes[0] * 60 + Number(startTimes[1]);
let endTimeVal = endTimes[0] * 60 + Number(endTimes[1]);
return startTimeVal >= endTimeVal;
}
下面來驗證一下 10:15-16:38 這個時間區間
console.log(JSON.stringify(judge('10:15', '16:38')))
輸出的結果如下:
[["10:00","11:00"],["11:00","12:00"],["12:00","13:00"],["13:00","14:00"],["14:00","15:00"],["15:00","16:00"],["16:00","17:00"]]
2、包含臨界點時間區間的判定
如果給定的時間區間包含了臨界時間點,比如 10:00-17:00,那麼結果又是如何呢?
console.log(JSON.stringify(judge('10:00', '17:00')))
此時輸出的結果如下:
[["10:00","11:00"],["11:00","12:00"],["12:00","13:00"],["13:00","14:00"],["14:00","15:00"],["15:00","16:00"],["16:00","17:00"]]
在實際的應用中,對於臨界點時間可能有不同的規則,具體有以下三種場景:
(1)同時算兩個時間區間內,比如 16:00 ,既算做位於 ["15:00","16:00"],也算做位於 ["16:00","17:00"] 區間;
(2)臨界時間作為結束時間,比如 16:00 ,那麼就只算做位於 ["15:00","16:00"] 區間;
(3)臨界時間作為起始時間,比如 16:00 ,那麼就只算做位於 ["16:00","17:00"] 區間;
如果想同時滿足上面的三個場景,那麼就需要對判定方法進行改造,通過傳入相應的引數進行控制,改造後的程式碼如下:
function judge(startTime, endTime, leftEquals, rightEquals) {
// 生成24小時時間區間,跨度為1小時
let timeArrays = new Array(24).fill(['', '']).map((item, index) => [(index < 10 ? '0' + index : index) + ':00', ((index + 1) < 10 ? '0' + (index + 1) : (index + 1)) + ':00']);
return timeArrays.filter(item => !((compare(item[0], startTime, leftEquals) && compare(item[0], endTime, rightEquals)) || (compare(startTime, item[1], leftEquals) && compare(endTime, item[1], rightEquals))));
}
function compare(startTime, endTime, equals) {
// 將時間轉換為分鐘,再進行比較
let startTimes = startTime.split(':');
let endTimes = endTime.split(':');
let startTimeVal = startTimes[0] * 60 + Number(startTimes[1]);
let endTimeVal = endTimes[0] * 60 + Number(endTimes[1]);
return equals ? startTimeVal >= endTimeVal : startTimeVal > endTimeVal;
}
下面分別測試一下上述的三個場景:
場景一:兩邊都包含,由於是取反的判定方式,所以兩個引數都需要傳 false
console.log(JSON.stringify(judge('10:00', '12:00', false, false)))
輸出結果如下:
[["09:00","10:00"],["10:00","11:00"],["11:00","12:00"],["12:00","13:00"]]
場景二:臨界點作為結束時間
console.log(JSON.stringify(judge('10:00', '12:00', false, true)))
輸出結果如下:
[["09:00","10:00"],["10:00","11:00"],["11:00","12:00"]]
場景三:臨界點作為起始時間
console.log(JSON.stringify(judge('10:00', '12:00', true, false)))
輸出結果如下:
[["10:00","11:00"],["11:00","12:00"],["12:00","13:00"]]
3、時間區間跨越0點的判定
在上面討論的兩種情況中,都沒有考慮到給定的時間區間跨越0點的問題,即結束時間小於起始時間的情況,比如 10:15-01:23,那麼對於這種情況,又需要怎麼處理呢?
如果時間區間跨越了0點,那麼就相當於存在兩個時間區間,即 10:15-24:00 和 00:00-01:23 ,此時就是對兩個時間區間進行判定,改造後的程式碼如下:
function judge(startTime, endTime, leftEquals, rightEquals) {
// 分割時間區間,判定結束時間是否小於起始時間
let targetTimes = compare(startTime, endTime, false) ? [[startTime, '24:00'], ['00:00', endTime]] : [[startTime, endTime]];
// 生成24小時時間區間,跨度為1小時
let timeArrays = new Array(24).fill(['', '']).map((item, index) => [(index < 10 ? '0' + index : index) + ':00', ((index + 1) < 10 ? '0' + (index + 1) : (index + 1)) + ':00']);
return timeArrays.filter(item => targetTimes.some(target => !((compare(item[0], target[0], leftEquals) && compare(item[0], target[1], rightEquals))
|| (compare(target[0], item[1], leftEquals) && compare(target[1], item[1], rightEquals)))));
}
function compare(startTime, endTime, equals) {
// 將時間轉換為分鐘,再進行比較
let startTimes = startTime.split(':');
let endTimes = endTime.split(':');
let startTimeVal = startTimes[0] * 60 + Number(startTimes[1]);
let endTimeVal = endTimes[0] * 60 + Number(endTimes[1]);
return equals ? startTimeVal >= endTimeVal : startTimeVal > endTimeVal;
}
下面驗證一下 10:15-01:23 這個時間區間
console.log(JSON.stringify(judge('10:15', '01:23', false, true)))
輸出結果如下
[["00:00","01:00"],["01:00","02:00"],["10:00","11:00"],["11:00","12:00"],["12:00","13:00"],["13:00","14:00"],["14:00","15:00"],["15:00","16:00"],["16:00","17:00"],["17:00","18:00"],["18:00","19:00"],["19:00","20:00"],["20:00","21:00"],["21:00","22:00"],["22:00","23:00"],["23:00","24:00"]]