用于从 JavaScript 中的两个时间戳中提取"work hours"的预定义函数?



我有两个时间戳,我必须找到"工作时间";在这两个时间戳之间的"工作时间"定义为9:00至17:00 (9AM至5PM)。

给定时间戳2022-04-25 15:00:002022-04-27 10:00:00:

2022-04-25 15:00:00->2小时

2022-04-26->8小时(全天)

2022-04-27 10:00:00->1小时

所以总共是11个工作小时。

我知道如何用EXTRACT函数在SQL中做到这一点,但我不擅长JavaScript,我的搜索没有返回任何有用的东西。或者,我可以把属于"工作时间"的时间加起来;给定两个时间戳,但我想检查是否有一些预定义的函数。

SQL等价:SQL extract hour from timestamp

本地API?

在JavaScript中没有简单的API。你必须自己编写这样的功能。

可能的解决方案这里有一个方法:

/**
* Calculate working hours in a given time range. Does not take weekends into account.
* @param {Date} start start Date of range
* @param {Date} end end Date of range
* @param {number} whStart start of working hours
* @param {number} whEnd end of working hours
* @returns object containing total working hours in range and working hours per day in milliseconds (ms) and hours (h)
*/
function workingHoursInRange(start, end, whStart, whEnd) {
let totalTime = 0;
// get day difference between start and end date
const dayDiff = end.getDate() - start.getDate() + 1;
let diff = 0;
const workingHoursPerDay = [...Array(dayDiff)].map((_, i) => {
// first day (start time till end of working hours)
if (i === 0) diff = firstDay(start, whStart, whEnd);
// last day (start of working hours till end date)
else if (i === dayDiff - 1) diff = lastDay(end, whStart, whEnd);
// days inbetween are full days
else diff = (whEnd - whStart) * 1000 * 3600;
totalTime += diff;
return diff;
});
return {
workingHoursPerDay: {
ms: workingHoursPerDay,
h: workingHoursPerDay.map((it) => it / (1000 * 3600)),
},
totalHours: {
ms: totalTime,
h: totalTime / (1000 * 3600),
},
};
}
/**
* Calculate working hours on first day of a date range
* @param {Date} date date
* @param {number} whStart start of working hours
* @param {number} whEnd end of working hours
* @returns working hours in milliseconds
*/
function firstDay(date, whStart, whEnd) {
const minEnd = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
whEnd
);
const maxStart = new Date(
Math.max(
new Date(date.getFullYear(), date.getMonth(), date.getDate(), whStart),
date
)
);
return minEnd - maxStart;
}
/**
* Calculate working hours on last day of a date range
* @param {Date} date date
* @param {number} whStart start of working hours
* @param {number} whEnd end of working hours
* @returns working hours in milliseconds
*/
function lastDay(date, whStart, whEnd) {
const maxStart = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
whStart
);
const minEnd = new Date(
Math.min(
new Date(date.getFullYear(), date.getMonth(), date.getDate(), whEnd),
date
)
);
return minEnd - maxStart;
}
// Test
const workingHoursStart = 9;
const workingHoursEnd = 17;
const input = [
{
start: new Date("2022-04-25 01:00:00"),
end: new Date("2022-04-27 10:00:00"),
},
{
start: new Date("2022-04-25 12:00:00"),
end: new Date("2022-04-27 10:00:00"),
},
{
start: new Date("2022-04-26 12:33:00"),
end: new Date("2022-04-26 16:05:00"),
},
];
// calculate working hours for all ranges
const result = input.map(({ start, end }) =>
workingHoursInRange(start, end, workingHoursStart, workingHoursEnd)
);
// log result
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

请注意:目前这个实现没有考虑到周末,但经过一些小的调整,这也可以考虑。

从本质上讲,这个想法是把一个日期范围分成三个部分: 第一天
  • 天中间画

第一天的工作时间将以working hours start和实际start date的最大值确定。最后一天的working hours endend date的最小值将决定当天的总工作时数。因为两者之间的所有日子都是完整的工作日,我们可以使用working hours endworking hours start的差值来计算总工作时间。

这种方法避免了日期算法(如夏令时)可能出现的警告。

所以我不知道是否有任何预定义的函数或任何东西。你说过你已经找过了,但没有找到解决办法。所以我假设没有。

<标题>一个小提琴h1> 就是我开始摆弄的原因!我喜欢挑战。-)下面的代码基本上做了你想要的例子,我猜。这更像是一个概念的证明。

但这也是为什么在实际用例中仍然有一些事情需要从这里开始:

  • 我没有考虑到分钟,例如
  • 我没有考虑周末
  • 我没有考虑两个不同月份之间的时间戳
    (例如从4月25日到5月2日)
  • 优惠吗?

但这只是一些微调!!

function calcWorkedHours(start, end) {
let workedHours = 0;
let startDateTime = new Date(start);
let endDateTime = new Date(end);
let workDate = startDateTime.getDate();
while (workDate <= endDateTime.getDate()) {
if (workDate === startDateTime.getDate()) {
// if they started before 17 oclock.
if (startDateTime.getHours() < 17) {
let workedHoursStartDate = 17 - startDateTime.getHours();
console.log(workedHoursStartDate);
workedHours += workedHoursStartDate;
}
} 
else if (workDate === endDateTime.getDate()) {
// if they finished after 9 oclock.
if (startDateTime.getHours() > 9) {
let workedHoursEndDate = endDateTime.getHours() - 9;
console.log(workedHoursEndDate);
workedHours += workedHoursEndDate;
}
} 
else {
let workedHoursFullDay = 8;
console.log(workedHoursFullDay);
workedHours += workedHoursFullDay;
}
workDate++;
}
console.log("Worked hours: " + workedHours);
return workedHours;
}

calcWorkedHours("2022-04-25 15:00:00", "2022-04-27 10:00:00");

最新更新