I have been able to get around this limitation by adding a few checks when shift end time move into the next day morning. Here is the modified code, that works well for all intervals along with break deductions:
function calculateHoursGroups(startShift, endShift) {
const parseTime = (timeStr) => {
const [hours, minutes] = timeStr.split(":").map(Number);
return hours * 60 + minutes;
};
const formatHours = (minutes) => (minutes / 60).toFixed(2);
var check = false;
var endTime;
const NORMAL_START = parseTime("06:00");
const NORMAL_END = parseTime("18:00");
const EVENING_START = parseTime("18:00");
const EVENING_END = parseTime("21:00");
const NIGHT_START = parseTime("21:00");
const NIGHT_END = parseTime("06:00");
const BREAK_TIMES = {
normal: { start: parseTime("12:00"), end: parseTime("12:30") },
evening: { start: parseTime("20:00"), end: parseTime("20:30") },
night: { start: parseTime("04:00"), end: parseTime("04:30") },
midnightBreak: { start: 1680, end: 1710 }, // Midnight break from 28:00 to 28:30
};
const startTime = parseTime(startShift);
if(parseTime(endShift) < startTime) {
endTime = parseTime(endShift) + 1440;
check = true;
}
else {
endTime = parseTime(endShift);
}
const shiftDuration = endTime - startTime;
let breakDuration = 0;
if (shiftDuration == 6 * 60) breakDuration = 20;
else if (shiftDuration > 6 * 60) breakDuration = 30;
const calculateOverlap = (start, end, rangeStart, rangeEnd) => {
// console.log(start)
// console.log(end)
const overlapStart = Math.max(start, rangeStart);
const overlapEnd = Math.min(end, rangeEnd);
return Math.max(0, overlapEnd - overlapStart);
};
const calculateShiftHoursInRange = (rangeStart, rangeEnd) => {
return calculateOverlap(startTime, endTime, rangeStart, rangeEnd);
};
let normalHours = calculateShiftHoursInRange(NORMAL_START, NORMAL_END);
let eveningHours = calculateShiftHoursInRange(EVENING_START, EVENING_END);
let nightHours = calculateShiftHoursInRange(NIGHT_START, NIGHT_END + 1440);
if (breakDuration > 0) {
if (calculateOverlap(startTime, endTime, BREAK_TIMES.normal.start, BREAK_TIMES.normal.end) > 0) {
normalHours -= breakDuration;
} if (calculateOverlap(startTime, endTime, BREAK_TIMES.evening.start, BREAK_TIMES.evening.end) > 0) {
eveningHours -= breakDuration;
} if (calculateOverlap(startTime, endTime, BREAK_TIMES.night.start, BREAK_TIMES.night.end) > 0) {
nightHours -= breakDuration;
}
}
// console.log(shiftDuration);
if(check){
console.log(startTime);
console.log(endTime)
console.log("Into the Next Day");
// console.log(BREAK_TIMES.midnightBreak.start)
// console.log(BREAK_TIMES.midnightBreak.end)
if(nightHours == 360 && startTime < BREAK_TIMES.midnightBreak.start && endTime > BREAK_TIMES.midnightBreak.end){
nightHours = nightHours - 20;
}
if(nightHours > 360 && startTime < BREAK_TIMES.midnightBreak.start && endTime > BREAK_TIMES.midnightBreak.end){
nightHours = nightHours - 30;
}
if(endTime > 1800){
normalHours = endTime - 1800;
}
}
if (startTime < NORMAL_START) { // Handle shifts starting before 06:00
console.log("Into before normal start time")
console.log(startTime);
console.log(endTime);
nightHours = Math.min(NORMAL_START, endTime) - startTime;
normalHours = Math.max(0, endTime - NORMAL_START);
var totalHours = nightHours + normalHours;
console.log("Sum: ", totalHours)
if(totalHours == 360 && startTime < 240 && endTime > 270){
nightHours = nightHours - 20;
}
if(totalHours > 360 && startTime < 240 && endTime > 270){
nightHours = nightHours - 30;
}
console.log(nightHours);
console.log(normalHours)
}
return {
normal: formatHours(normalHours),
evening: formatHours(eveningHours),
night: formatHours(nightHours)
};
}
function testShiftCalculation(){
const result = calculateHoursGroups("16:00", "00:00");
console.log(result);
}
These added checks, explicitly get start and end time, compare them with the break intervals and then compile the results, any suggestions to improve the overall efficiency of the script would be much appreciated.