
在许多应用场景中,我们需要实现一个能够根据特定规则进行计数的计时器。例如,一个项目进度跟踪器可能只需要在工作日的工作时间内累积时间。这要求计数器不仅能按设定的频率(如每分钟)递增,还需要智能地识别当前时间是否符合计数条件,并在不符合条件时暂停计数但仍显示当前值,同时在每月初自动重置。
实现这样一个计数器面临的主要挑战包括:
为了实现上述功能,我们首先需要定义一些核心参数并获取当前的时间状态:
function startCounter() {
// 获取当前日期和时间
var currentDate = new Date();
var currentDay = currentDate.getDay(); // 0: 星期日, 1: 星期一, ..., 6: 星期六
var currentHour = currentDate.getHours();
var currentMinutes = currentDate.getMinutes();
var currentDayOfMonth = currentDate.getDate(); // 当前月份的日期 (1-31)
// 定义工作日和工作时间参数
var weekEndDays = [0, 6]; // 星期日和星期六为周末
var startHour = 6; // 工作开始时间 (上午6点)
var endHour = 20; // 工作结束时间 (晚上8点,不包含20点)
// 判断当前是否为周末或非工作时间
var isWeekend = weekEndDays.indexOf(currentDay) > -1;
var isOutsideWorkingHours = currentHour < startHour || currentHour >= endHour;在这里:
立即学习“Java免费学习笔记(深入)”;
计数器的核心在于其初始值的准确性。当页面加载或功能启动时,我们需要计算出当前月份中,直到当前时刻为止,所有符合工作日和工作时间条件的累积分钟数。这分为两个主要部分:计算已过去的工作天数,以及计算当前工作日已过的分钟数。
我们需要遍历当前月份中从1号到当前日期前一天的所有日期,判断它们是否为工作日。
// 计算从本月1号到当前日期前一天,已过去的工作天数
var daysSinceStart = 0;
for (let i = 1; i < currentDayOfMonth; i++) {
let checkDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), i);
if (weekEndDays.indexOf(checkDate.getDay()) === -1) { // 如果不是周末
daysSinceStart++;
}
}这段代码确保了我们准确地统计了当前月份中,截至当前日期的前一天,所有符合工作日条件的完整天数。
当前日期的情况相对复杂:
var minutesSinceStartOfDay = 0;
// 如果今天是工作日,且当前时间已超过工作结束时间,则将今天计为一个完整的工作日
if (!isWeekend && isOutsideWorkingHours && currentHour >= endHour) {
daysSinceStart++;
}
// 如果当前是工作日且处于工作时间内,计算当天已过的分钟数
else if (!isWeekend && !isOutsideWorkingHours) {
minutesSinceStartOfDay = (currentHour - startHour) * 60 + currentMinutes;
console.log('Counter starting...');
} else {
console.log('Counter paused.');
}一旦 daysSinceStart 和 minutesSinceStartOfDay 计算完毕,我们就可以确定计数器的初始值:
// 计算每个工作日总分钟数
var minutesPerWorkingDay = (endHour - startHour) * 60;
// 计算计数器初始值
var counter = daysSinceStart * minutesPerWorkingDay + minutesSinceStartOfDay;这里的 minutesPerWorkingDay 是一个关键常量,代表一个完整工作日(6 AM 到 8 PM 之间,即14小时)的分钟数,即 (20 - 6) * 60 = 840 分钟。
计数器的实时递增是通过 setInterval 实现的。关键在于在每次递增前,都需要重新判断当前时间是否符合计数条件。
// 启动计数器,每分钟递增
var intervalId = setInterval(function() {
// 在每次递增前重新获取当前时间状态
currentDate = new Date();
currentDay = currentDate.getDay();
currentHour = currentDate.getHours();
currentMinutes = currentDate.getMinutes();
isWeekend = weekEndDays.indexOf(currentDay) > -1;
isOutsideWorkingHours = currentHour < startHour || currentHour >= endHour;
if (isWeekend || isOutsideWorkingHours) {
// 如果是周末或非工作时间,不递增,但仍显示当前值
console.log('Counter:', counter, '(Paused)');
return; // 暂停递增
}
counter++; // 符合条件时递增
console.log('Counter:', counter);
}, 60000); // 60000毫秒 = 1分钟
// 页面加载时显示初始值
console.log('Counter:', counter);
}
// 启动计数器
startCounter();这里的核心改进是:
本方案通过将计数器的初始值计算基于当前月份的1号,天然地实现了每月重置功能。当进入一个新的月份时,currentDate.getMonth() 会发生变化,从而 daysSinceStart 的计算会从新月份的1号重新开始,达到自动重置的效果。
将以上所有部分整合,形成一个完整的、健壮的JavaScript计数器实现:
function startCounter() {
// 获取当前日期和时间
var currentDate = new Date();
var currentDay = currentDate.getDay(); // 0: 星期日, 1: 星期一, ..., 6: 星期六
var currentHour = currentDate.getHours();
var currentMinutes = currentDate.getMinutes();
var currentDayOfMonth = currentDate.getDate(); // 当前月份的日期 (1-31)
// 定义工作日和工作时间参数
var weekEndDays = [0, 6]; // 星期日和星期六为周末
var startHour = 6; // 工作开始时间 (上午6点)
var endHour = 20; // 工作结束时间 (晚上8点,不包含20点)
// 判断当前是否为周末或非工作时间
var isWeekend = weekEndDays.indexOf(currentDay) > -1;
var isOutsideWorkingHours = currentHour < startHour || currentHour >= endHour;
// 计算从本月1号到当前日期前一天,已过去的工作天数
var daysSinceStart = 0;
for (let i = 1; i < currentDayOfMonth; i++) {
let checkDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), i);
if (weekEndDays.indexOf(checkDate.getDay()) === -1) { // 如果不是周末
daysSinceStart++;
}
}
var minutesSinceStartOfDay = 0;
// 如果今天是工作日,且当前时间已超过工作结束时间,则将今天计为一个完整的工作日
if (!isWeekend && isOutsideWorkingHours && currentHour >= endHour) {
daysSinceStart++;
}
// 如果当前是工作日且处于工作时间内,计算当天已过的分钟数
else if (!isWeekend && !isOutsideWorkingHours) {
minutesSinceStartOfDay = (currentHour - startHour) * 60 + currentMinutes;
console.log('Counter starting...');
} else {
console.log('Counter paused.');
}
// 计算每个工作日总分钟数
var minutesPerWorkingDay = (endHour - startHour) * 60; // 14小时 * 60分钟 = 840分钟
// 计算计数器初始值
var counter = daysSinceStart * minutesPerWorkingDay + minutesSinceStartOfDay;
// 启动计数器,每分钟递增
var intervalId = setInterval(function() {
// 在每次递增前重新获取当前时间状态
currentDate = new Date();
currentDay = currentDate.getDay();
currentHour = currentDate.getHours();
currentMinutes = currentDate.getMinutes(); // 重新获取分钟数,确保跨分钟时判断准确
isWeekend = weekEndDays.indexOf(currentDay) > -1;
isOutsideWorkingHours = currentHour < startHour || currentHour >= endHour;
if (isWeekend || isOutsideWorkingHours) {
// 如果是周末或非工作时间,不递增,但仍显示当前值
console.log('Counter:', counter, '(Paused)');
return; // 暂停递增
}
counter++; // 符合条件时递增
console.log('Counter:', counter);
}, 60000); // 60000毫秒 = 1分钟
// 页面加载时显示初始值
console.log('Counter:', counter);
}
// 启动计数器
startCounter();通过以上详细的步骤和代码实现,您可以构建一个功能完善、逻辑清晰的JavaScript计数器,满足在特定工作日和工作时间内进行计数的复杂需求。
以上就是JavaScript实现基于工作日和工作时间的精确计数器的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号