JS判定一個給定的時間區間在哪些時間段範圍內

十方發表於2022-06-16
有這樣的一個場景:給定一個時間區間,需要判定這個時間區間在哪些時間段範圍內.

比如時間段範圍如下:

[["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"]]

相關文章