判断是否在某一个时间段内的处理

本文介绍了一种用于判断当前时间是否处于工作日中指定的不进行版本检测时间段的方法。通过具体示例代码展示了如何利用Java的Calendar类来实现这一逻辑。

前段时间项目中有这样的一个需求:在工作日内的早上 09:30-11:30和下午13:00-15:00这2各时间段内就不需要检测版本更新。反之则反。

其中这有2个问题需要处理:我们怎么知道当前时间是否在这2个时间段内并且是在工作日内(周一到周五)。显而易见。我们必须先获取日期在根据日期判断是否是周一到周五,然后在获取当前时间在判断是否在这个时间段内。代码如下:

/**
	 * <pre>
	 * 根据指定的日期字符串获取星期几
	 * </pre>
	 * 
	 * @param strDate
	 *            指定的日期字符串(yyyy-MM-dd 或 yyyy/MM/dd)
	 * @return week
	 *         星期几(MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY)
	 */
	public static String getWeekByDateStr(String strDate) {
		int year = Integer.parseInt(strDate.substring(0, 4));
		int month = Integer.parseInt(strDate.substring(5, 7));
		int day = Integer.parseInt(strDate.substring(8, 10));

		Calendar c = Calendar.getInstance();

		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month - 1);
		c.set(Calendar.DAY_OF_MONTH, day);

		String week = "";
		int weekIndex = c.get(Calendar.DAY_OF_WEEK);

		switch (weekIndex) {
		case 1:
			week = "星期日";
			break;
		case 2:
			week = "星期一";
			break;
		case 3:
			week = "星期二";
			break;
		case 4:
			week = "星期三";
			break;
		case 5:
			week = "星期四";
			break;
		case 6:
			week = "星期五";
			break;
		case 7:
			week = "星期六";
			break;
		}
		return week;
	}

	/**
	 * 检测版本时间  09:30-11:30
	 * 是否是检测版本时间以内 
	 * @return true 则是检测版本时间内, false 为检测版本时间外
	 */
	public static boolean isATime(){
		Calendar calendar = Calendar.getInstance();
		int week = calendar.get(Calendar.DAY_OF_WEEK);
		if(week==1 || week == 7)
			return false;

		long spe1 = getSpeDate(9, 30, 0, 0); // 09:30 分时时间
		long spe2 = getSpeDate(11, 30, 0, 0); // 11:30 分时时间


		return System.currentTimeMillis() > spe1
				&& System.currentTimeMillis() < spe2;

	}

	/**
	 * 检测版本时间  13:00-15:00
	 * 是否是检测版本时间以内 
	 * @return true 则是检测版本时间内, false 为检测版本时间外
	 */
	public static boolean isBTime(){
		Calendar calendar = Calendar.getInstance();
		int week = calendar.get(Calendar.DAY_OF_WEEK);
		if(week==1 || week == 7)
			return false;

		long spe1 = getSpeDate(13, 00, 0, 0); // 13:00 分时时间
		long spe2 = getSpeDate(15, 00, 0, 0); // 15:00 分时时间


		return System.currentTimeMillis() > spe1
				&& System.currentTimeMillis() < spe2;

	}




	/***
	 * 获取指定一天中指定的时间的时间戳
	 * 
	 * @param hour
	 * @param minute
	 * @param second
	 * @param milliSecond
	 * @return
	 */
	public static long getSpeDate(int hour, int minute, int second,
			int milliSecond) {

		Calendar cal = Calendar.getInstance();

		cal.set(Calendar.HOUR_OF_DAY, hour);

		cal.set(Calendar.SECOND, second);

		cal.set(Calendar.MINUTE, minute);

		cal.set(Calendar.MILLISECOND, milliSecond);

		return cal.getTimeInMillis();

	}

调用如下:

 Date now = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String dtStr = sdf.format(now);
    if (TimeUtil.getWeekByDateStr(dtStr).equals("星期六") || TimeUtil.getWeekByDateStr(dtStr).equals("星期日")) {
    	LogUtil.e("Protocols.AMMIDHQ_BBH return-------------发送请求");
    }else {
        if (TimeUtil.isATime() == true && TimeUtil.isBTime() == false) {
            LogUtil.e("Protocols.AMMIDHQ_BBH return-------------在当前时间段内什么都不做");

        }else if(TimeUtil.isATime() == false && TimeUtil.isBTime() == true){
            LogUtil.e("Protocols.AMMIDHQ_BBH return-------------在当前时间段内什么都不做");
        }else {
        	LogUtil.e("Protocols.AMMIDHQ_BBH return-------------发送请求");
        }

    }

当然大家可以把代码封装下,作为公共方法方便使用
<think>我们需要判断一个时间是否在指定的时间段内。时间段由开始时间和结束时间定义。 思路: 1. 将时间字符串转换为可比较的时间对象(如Date对象)或时间戳(数字)。 2. 将要判断时间也转换为同样的格式。 3. 比较这个时间是否在开始时间和结束时间之间。 注意:时间段可能跨越午夜,例如23:00到次日01:00。我们需要考虑这种情况。 有两种情况: 情况1:不跨天(开始时间 <= 结束时间) -> 判断条件:开始时间 <= 当前时间 <= 结束时间 情况2:跨天(开始时间 > 结束时间) -> 判断条件:当前时间 >= 开始时间 或 当前时间 <= 结束时间(即当前时间在开始时间之后到午夜,或者从午夜到结束时间之前) 但是,我们也可以统一处理:将时间转换为当天的分钟数或秒数,然后考虑跨天的情况。 然而,如果时间段是跨天的(比如23:00到第二天01:00),那么我们可以这样判断: - 如果当前时间在23:00之后(直到24:00)或者在00:00到01:00之间,则算在时间段内。 另一种思路:将时间转换为一天中的分钟数(0-1440分钟),然后处理跨天的情况。 但是,如果时间段是固定的,比如每天都是同一个时间段,那么我们可以用分钟数来比较。 步骤: 1. 将时间字符串(如"09:00")转换为分钟数。例如,"09:00" -> 9*60=540分钟;"13:30" -> 13*60+30=810分钟。 2. 同样,将当前时间也转换为分钟数。 3. 比较分钟数: 如果开始分钟数 <= 结束分钟数,那么当前分钟数在 [开始分钟数, 结束分钟数] 内即可。 如果开始分钟数 > 结束分钟数,那么当前分钟数在 [开始分钟数, 1440) 或 [0, 结束分钟数] 内。 但是,注意:时间段跨天,实际上结束时间是在第二天,但我们的分钟数都是当天的时间,所以当开始分钟数大于结束分钟数时,表示跨天。 因此,判断函数可以这样写: 函数输入:当前时间(可以是Date对象或字符串),开始时间字符串(格式"HH:mm"),结束时间字符串(格式"HH:mm") 输出:布尔值 示例: 时间段:23:00 到 01:00(跨天) 当前时间:23:30 -> 在时间段内 当前时间:00:30 -> 在时间段内 当前时间:10:00 -> 不在 实现步骤: 1. 将开始时间和结束时间转换为分钟数(startMin, endMin) 2. 将当前时间转换为分钟数(currentMin) 3. 如果startMin <= endMin,那么直接判断 currentMin 是否在 [startMin, endMin] 之间(包括边界) 4. 如果startMin > endMin,那么判断 currentMin 是否在 [startMin, 1440] 或 [0, endMin] 之间 注意:边界情况是否包含?根据需求,一般包含边界。 但是,我们也可以用一个条件判断:在跨天的情况下,相当于两个区间:[startMin, 1440] 和 [0, endMin]。那么,当前分钟数只要满足 currentMin >= startMin 或 currentMin <= endMin 即可。 因此,代码可以这样: function isInTimeRange(currentTime, startTimeStr, endTimeStr) { // 将时间字符串转换为分钟数 function timeStrToMinutes(timeStr) { const [hours, minutes] = timeStr.split(':').map(Number); return hours * 60 + minutes; } const startMin = timeStrToMinutes(startTimeStr); const endMin = timeStrToMinutes(endTimeStr); const currentMin = currentTime.getHours() * 60 + currentTime.getMinutes(); if (startMin <= endMin) { return currentMin >= startMin && currentMin <= endMin; } else { return currentMin >= startMin || currentMin <= endMin; } } 测试: 情况1:不跨天,9:00~18:00 当前时间:10:00 -> true 当前时间:8:59 -> false 当前时间:18:01 -> false 情况2:跨天,23:00~1:00 当前时间:23:30 -> true 当前时间:0:30 -> true 当前时间:22:00 -> false 当前时间:1:01 -> false 注意:这里的时间段是每天重复的,所以这样处理是合理的。 但是,如果用户给的时间段是具体的日期时间(比如包含年月日),那么我们需要用Date对象来比较时间戳。不过,根据问题描述,这里的时间段是每天的时间段(如9:00~12:00),所以用分钟数比较即可。 另外,如果用户给的时间字符串包含秒,我们可以忽略,或者也可以处理到秒。但问题中只要求到分钟(如9:00~12:00),所以分钟级别足够。 但是,如果用户需要精确到秒,我们可以将时间转换为秒数(一天86400秒),方法类似。 下面我们写一个精确到秒的版本(如果时间字符串包含秒): 输入时间字符串格式可能是"HH:mm"或"HH:mm:ss",我们可以分割成两部分或三部分。 修改timeStrToMinutes为timeStrToSeconds(然后除以60得到分钟?或者直接用秒比较更精确),但问题中时间段是分钟级,所以我们可以忽略秒,或者将秒也考虑进去。 根据问题,用户可能给的时间字符串是"9:00"和"12:00",所以我们可以默认没有秒,或者有秒。为了通用性,我们处理到秒。 但是,注意:问题描述中时间段是“9:00~12:00”,所以我们可以假设只有小时和分钟。但为了扩展,我们处理到秒。 修改函数: function timeStrToSeconds(timeStr) { const parts = timeStr.split(':'); let hours = 0, minutes = 0, seconds = 0; if (parts.length >= 1) hours = parseInt(parts[0]); if (parts.length >= 2) minutes = parseInt(parts[1]); if (parts.length >= 3) seconds = parseInt(parts[2]); return hours * 3600 + minutes * 60 + seconds; } 然后,将当前时间也转换为秒数:currentSeconds = currentTime.getHours()*3600 + currentTime.getMinutes()*60 + currentTime.getSeconds() 一天的总秒数:86400 然后,比较逻辑相同,只是将分钟换成秒。 但是,问题中用户只要求时间段(如9:00~12:00),所以我们可以只处理到分钟,忽略秒。但为了精确,我们处理到秒。 因此,我们可以写一个更通用的函数,支持到秒。 但是,根据引用[1][2][3],它们都是处理到毫秒或秒的,但我们的需求是每天的时间段,所以用秒数比较即可。 下面,我们写一个支持秒的函数,但也可以处理只给到分钟的情况。 代码实现: function isInTimeRange(currentTime, startTimeStr, endTimeStr) { // 将时间字符串转换为秒数 function timeStrToSeconds(timeStr) { const parts = timeStr.split(':').map(part => parseInt(part) || 0); // 如果只有小时和分钟,没有秒,则秒为0 const [hours, minutes, seconds] = parts.length === 1 ? [parts[0], 0, 0] : parts.length === 2 ? [parts[0], parts[1], 0] : [parts[0], parts[1], parts[2]]; return hours * 3600 + minutes * 60 + seconds; } const startSeconds = timeStrToSeconds(startTimeStr); const endSeconds = timeStrToSeconds(endTimeStr); const currentSeconds = currentTime.getHours() * 3600 + currentTime.getMinutes() * 60 + currentTime.getSeconds(); const totalSecondsInDay = 86400; if (startSeconds <= endSeconds) { return currentSeconds >= startSeconds && currentSeconds <= endSeconds; } else { return currentSeconds >= startSeconds || currentSeconds <= endSeconds; } } 但是,注意:如果时间段跨天,结束时间实际上是第二天的结束时间,但我们只比较一天内的秒数,所以这样处理是合理的。 测试跨天:23:00:00 到 01:00:00 startSeconds = 23*3600 = 82800 endSeconds = 1*3600 = 3600 当前时间:23:30:00 -> 23*3600+30*60=82800+1800=84600 -> 满足 currentSeconds>=startSeconds -> true 当前时间:00:30:00 -> 30*60=1800 -> 满足 currentSeconds<=endSeconds (1800<=3600) -> true 当前时间:01:30:00 -> 1*3600+30*60=5400 -> 不满足 >=82800 且不满足 <=3600 -> false 所以,这个函数可以处理跨天的情况。 但是,注意:这个函数只适用于比较同一天内的时间段或跨天的时间段(每天重复),不适用于具体的日期(年月日)。 如果用户给的是带年月日的时间,那么我们需要用Date对象解析,然后比较时间戳(如引用[2]和引用[3]的方法)。但根据问题,用户要求的是时间段(如9:00~12:00),所以应该是每天的时间段,因此用上述方法即可。 现在,我们根据需求写一个函数,并给出使用示例。 另外,如果用户给的时间字符串是24小时制,那么没有问题;如果是12小时制,需要带上AM/PM,但问题没有提及,所以默认24小时制。 示例代码: function isInTimeRange(currentTime, startTimeStr, endTimeStr) { // 将时间字符串分割并转换为数字 const partsToSeconds = (timeStr) => { const parts = timeStr.split(':').map(Number); let seconds = 0; if (parts.length > 0) seconds += parts[0] * 3600; if (parts.length > 1) seconds += parts[1] * 60; if (parts.length > 2) seconds += parts[2]; return seconds; }; const start = partsToSeconds(startTimeStr); const end = partsToSeconds(endTimeStr); const now = currentTime.getHours() * 3600 + currentTime.getMinutes() * 60 + currentTime.getSeconds(); if (start <= end) { return now >= start && now <= end; } else { return now >= start || now <= end; } } 使用示例: const now = new Date(); // 当前时间 const inRange = isInTimeRange(now, '9:00', '18:00'); console.log(inRange); // 如果在9:00到18:00之间,输出true,否则false 或者跨天: const inRange = isInTimeRange(now, '23:00', '1:00'); // 注意这里结束时间是1:00 注意:结束时间字符串如果是单数字的小时,比如1点,写成'1:00'是可以的,因为我们用split(':')分割。 但是,如果用户输入的时间字符串不规范,比如小时或分钟只有一位数,我们的函数也能处理(因为Number可以处理)。 另外,如果用户输入的时间字符串包含空格,我们可以先trim,但这里没有处理。为了健壮性,我们可以先trim。 改进一下: function isInTimeRange(currentTime, startTimeStr, endTimeStr) { const partsToSeconds = (timeStr) => { // 去除空格 timeStr = timeStr.trim(); const parts = timeStr.split(':').map(Number); // 如果转换后不是数字,则设为0 let seconds = 0; if (parts.length > 0 && !isNaN(parts[0])) seconds += parts[0] * 3600; if (parts.length > 1 && !isNaN(parts[1])) seconds += parts[1] * 60; if (parts.length > 2 && !isNaN(parts[2])) seconds += parts[2]; return seconds; }; const start = partsToSeconds(startTimeStr); const end = partsToSeconds(endTimeStr); const now = currentTime.getHours() * 3600 + currentTime.getMinutes() * 60 + currentTime.getSeconds(); if (start <= end) { return now >= start && now <= end; } else { return now >= start || now <= end; } } 这样更健壮。 但是,如果用户输入的时间字符串有误(比如负数或超过23小时),我们可能需要验证。不过,我们假设用户输入的是合法的时间。 另外,如果时间段是24小时(即start和end相等且都为0,或者start=0, end=86400-1?),但我们的函数中,如果start等于end,那么不跨天的条件会要求now等于start(也就是等于end),所以只有那一瞬间。但实际上,24小时时间段应该是全天,所以我们可以特殊处理:如果start等于end,并且start等于0,那么就是全天?但用户输入24小时时间段,通常不会输入0:00到0:00(这样只有0点这一瞬间),而是应该输入0:00到23:59:59或者到24:00,但24:00通常表示为0:00(第二天)。所以,用户如果要表示全天,可以输入0:00到23:59:59,或者跨天的23:59:59到0:00(但这样不行,因为跨天的条件是开始>结束,那么0:00到23:59:59是不跨天的,所以可以覆盖全天)。或者,我们可以认为如果start等于end,则返回true(表示全天)?但这样不准确,因为可能用户就是想判断0:00:00这一秒。 所以,我们按照常规逻辑,不特殊处理。如果用户需要全天,那么输入0:00到23:59:59即可(不跨天,所以判断条件为now>=0 && now<=86399,注意23:59:59是86399秒)。或者,用户也可以输入0:00到0:00(跨天表示法,因为0:00在0:00之后?不,0:00等于0:00,所以不跨天,那么只有0:00:00这一秒)。因此,我们不需要特殊处理。 最后,我们给出完整的函数。 另外,如果用户使用的是框架(如vue、uniapp、微信小程序),这个函数同样适用,因为不依赖环境,只依赖Date对象。 下面,我们写一个示例代码,并测试。</think>### JavaScript 判断时间是否时间段范围内 以下是判断时间是否在指定时间段内的完整解决方案,支持跨天时间段(如 23:00 到次日 01:00)和精确到秒的比较: ```javascript /** * 判断当前时间是否在指定时间段内 * @param {string} startTime 开始时间(格式: "HH:mm" 或 "HH:mm:ss") * @param {string} endTime 结束时间(格式: "HH:mm" 或 "HH:mm:ss") * @param {Date} [targetDate=new Date()] 要判断时间点(默认当前时间) * @returns {boolean} 是否时间段内 */ function isInTimeRange(startTime, endTime, targetDate = new Date()) { // 解析时间字符串为秒数 const parseTimeToSeconds = (timeStr) => { const [hours, minutes, seconds = 0] = timeStr.split(':').map(Number); return hours * 3600 + minutes * 60 + seconds; }; // 获取目标时间的秒数 const getTimeInSeconds = (date) => { return date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds(); }; const startSeconds = parseTimeToSeconds(startTime); const endSeconds = parseTimeToSeconds(endTime); const targetSeconds = getTimeInSeconds(targetDate); // 处理跨天时间段(如 23:00 到 01:00) if (startSeconds > endSeconds) { return targetSeconds >= startSeconds || targetSeconds <= endSeconds; } // 处理常规时间段 return targetSeconds >= startSeconds && targetSeconds <= endSeconds; } // 使用示例 const now = new Date(); // 示例1:检查是否在 9:00~18:00 工作时间段 console.log(isInTimeRange('09:00', '18:00', now)); // 示例2:检查是否在跨天的 23:00~01:00 时间段 console.log(isInTimeRange('23:00', '01:00', now)); // 示例3:精确到秒的检查(14:30:00~16:45:30) console.log(isInTimeRange('14:30:00', '16:45:30', now)); ``` #### 实现原理: 1. **时间转换**:将时间字符串(如 `"09:30"`)转换为全天秒数(0-86399) - 例如:`09:30` → `34200` 秒 2. **跨天处理**: - 当开始时间 > 结束时间(如 23:00 > 01:00)时,判断逻辑为: $$ \text{targetSeconds} \geq \text{startSeconds} \quad \lor \quad \text{targetSeconds} \leq \text{endSeconds} $$ - 常规时间段判断逻辑: $$ \text{startSeconds} \leq \text{targetSeconds} \leq \text{endSeconds} $$ 3. **边界包含**:包含开始和结束时间的精确时刻 #### 使用场景: - 营业时间检查(店铺是否营业中) - 活动时间段验证(限时折扣活动) - 系统维护窗口控制 - 定时任务触发条件 #### 注意事项: 1. 时间格式必须为 **24小时制**(不支持 AM/PM 格式) 2. 秒数为可选部分(`"HH:mm"` 和 `"HH:mm:ss"` 均支持) 3. 可传入任意 `Date` 对象检查特定时间点 > 此方案已考虑跨天场景,在 Vue/Uniapp/微信小程序等前端框架中均可直接使用[^1][^2]。 --- ### 相关问题 1. **如何处理带日期的时间范围判断(如 2023-01-01 到 2023-01-10)?** *解答:需使用完整时间戳比较,可结合 `Date.parse()` 实现* 2. **如何在时间判断中考虑时区因素?** *解答:使用 `getTimezoneOffset()` 转换本地时间到 UTC* 3. **如何用 Moment.js 简化时间段判断?** *解答:利用 `moment().isBetween()` 方法,支持更灵活的时间操作[^3]* 4. **如何实现周期性时间段判断(如每周一 10:00-12:00)?** *解答:结合星期判断和本文的时间段函数* 5. **判断时间范围时如何优化性能(高频调用场景)?** *解答:缓存时间转换结果,使用 Web Worker 后台计算* [^1]: JavaScript - 判断当前时间是否在指定区间内,例如:9:00~12:00(检查当前时间是否处于规定的两个时间段范围内) [^2]: JavaScript判断一个时间点在不在某段时间段范围之内 [^3]: 【Moment.js】判断某个时间是否位于某个时间区间范围内
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值