login
TypeScript跨天夜间时间段判断
2025/06/04·StepFun can make mistakes, check important info.
Reason
思考过程

我们有一个时间段字符串,格式为 "HH:mm-HH:mm",例如 "21:30-07:15",表示从当天21:30到次日07:15(跨天)。
目标:判断当前时间是否在这个时间段内(注意跨天的情况)。

思路:

  1. 将输入字符串拆分为开始时间和结束时间。
  2. 由于结束时间可能小于开始时间(跨天),所以我们可以将时间段分为两部分:
    • 从开始时间到当天结束(23:59:59.999)
    • 从当天的00:00:00到结束时间(第二天)
  3. 但更简单的方法是将时间转换为分钟数,并考虑跨天的情况。

具体步骤:
步骤1:解析时间段字符串
步骤2:将当前时间转换为分钟数(从00:00开始的分钟数)
步骤3:将开始时间和结束时间也转换为分钟数
注意:如果结束时间小于开始时间,则结束时间实际上是第二天的这个时间,所以我们可以将结束时间加上24小时(1440分钟)来表示。
步骤4:判断当前时间(分钟数)是否在区间内,但要注意跨天的情况有两种表示方式:
方式1:将当前时间与两个时间点比较,如果当前时间在开始时间之后(且小于24*60)或者在结束时间之前(且大于0),但这样需要分两段。
方式2:我们可以这样处理:
如果结束时间小于开始时间,那么结束时间加上1440(代表第二天的同一时间)。
同时,如果当前时间小于开始时间,那么我们可以将当前时间也加上1440(相当于也放到第二天去比较)。
然后判断当前时间(可能是当天的分钟数,也可能是加上1440后的分钟数)是否在 [startMinutes, endMinutes+1440] 区间内,但注意我们只加了一次。

更清晰的逻辑:

  • 将开始时间(start)和结束时间(end)转换为分钟数(假设startMinutes, endMinutes)。
  • 如果endMinutes小于startMinutes,则说明跨天,那么将endMinutes加上1440(24*60)。
  • 获取当前时间(current)的分钟数(currentMinutes)。
  • 同时,如果当前时间在跨天的后半天(即当前时间小于开始时间),那么我们可以将当前时间也加上1440(这样当前时间就相当于第二天的时间),然后再判断是否在[startMinutes, endMinutes](注意此时endMinutes已经加了1440)之间。
  • 但这样相当于:
    如果当前时间小于开始时间,那么我们可以将当前时间加上1440,然后判断是否小于结束时间(加上1440后的)吗?不,我们需要统一比较。

另一种方法(推荐):

  • 将当前时间转换为从当天00:00开始的分钟数(currentMinutes)。
  • 同样,开始时间(startMinutes)和结束时间(endMinutes)也这样转换。
  • 如果时间段没有跨天(即endMinutes >= startMinutes),那么判断currentMinutes是否在[startMinutes, endMinutes]之间。
  • 如果跨天了(endMinutes < startMinutes),那么判断currentMinutes是否在[startMinutes, 24*60) 或者 [0, endMinutes]之间。但这样需要两个条件。

我们可以写一个函数来实现:

步骤:

  1. 解析输入字符串,例如"21:30-07:15",拆分为两个字符串数组。
  2. 将开始时间和结束时间转换为分钟数。
  3. 获取当前时间,并转换为分钟数。
  4. 如果结束时间大于等于开始时间,那么时间段在同一天内,直接判断当前分钟数是否在区间内。
  5. 如果结束时间小于开始时间,那么时间段跨天,判断当前分钟数是否大于等于开始时间 或者 小于等于结束时间(注意:这里结束时间是当天的结束时间,所以实际上只要大于等于开始时间(即晚上)或者小于等于结束时间(即第二天凌晨)就算在区间内)。

注意:这里的时间段是包含边界的,即如果当前时间正好等于开始时间或结束时间,也算在区间内。

例如:时间段 "21:30-07:15"
开始分钟数:2160+30 = 1290
结束分钟数:7
60+15 = 435
因为435 < 1290,所以跨天。
那么判断:
如果当前分钟数 >= 1290 (即21:30之后到24:00) 或者 当前分钟数 <= 435 (即00:00到07:15) 则返回true。

因此,代码实现如下:

步骤:

  1. 使用正则或split拆分时间段字符串。
  2. 将拆分后的两个字符串分别解析为分钟数。
  3. 获取当前时间(注意:当前时间是一个Date对象,我们可以获取小时和分钟)。
  4. 计算当前时间的分钟数。
  5. 比较并返回结果。

注意:输入字符串的格式是固定的,我们可以假设格式正确。

写一个函数:
function isInNightPeriod(timeRange: string, currentDate: Date = new Date()): boolean {
// 拆分字符串
const [start, end] = timeRange.split('-');
// 解析开始和结束时间
const startMinutes = convertToMinutes(start);
const endMinutes = convertToMinutes(end);
const currentMinutes = currentDate.getHours() * 60 + currentDate.getMinutes();

text

}

辅助函数:将"HH:mm"字符串转换为分钟数
function convertToMinutes(timeStr: string): number {
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}

注意:这里我们假设时间段是当天的21:30到次日的07:15,所以跨天的情况就是结束时间小于开始时间。

测试用例:

  1. 当前时间在21:30-23:59之间,返回true。
  2. 当前时间在00:00-07:15之间,返回true。
  3. 当前时间在07:16-21:29之间,返回false。

但是,如果时间段是同一天的,比如 "08:00-18:00",那么跨天标志就是false,直接判断是否在区间内。

因此,这个函数可以满足需求。

我们还需要考虑当前时间可能是第二天的凌晨,但我们的逻辑已经覆盖了:跨天时,只要当前时间小于等于结束时间(即07:15)就算,因为结束时间是435分钟,而凌晨的时间分钟数在0到435之间。

编写代码:

以下是使用 TypeScript 实现的方法,用于判断当前时间是否在跨天的夜间时间段内(如 21:30-07:15):

typescript

方法说明:

  1. 时间解析:将输入的时间段拆分为开始时间和结束时间,并转换为分钟数。
  2. 跨天处理
    • 如果结束时间早于开始时间(如 07:15 < 21:30),则为跨天时间段
    • 将结束时间加上 1440 分钟(24 小时)表示它在第二天
  3. 当前时间调整
    • 如果当前时间在开始时间之前(如 20:00),将其视为第二天的同一时间(加上 1440 分钟
  4. 区间判断:检查调整后的当前时间是否在开始时间和结束时间之间

示例测试:

typescript

注意事项:

  1. 时间格式必须严格为 HH:mm-HH:mm(24 小时制)
  2. 自动处理跨天逻辑,无需手动指定日期
  3. 包含时间段的边界值(如 21:3007:15 会被包含在内)

此方法可应用于夜间模式切换、定时任务等需要判断跨天时间段的场景。