Refactoring of isInWorkingHours method (#1574)

# What this PR does
Instead of using string comparing now isBetween method from dayjs is
used

## Which issue(s) this PR fixes
https://github.com/grafana/oncall/issues/1418

---------

Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
This commit is contained in:
Yulia Shanyrova 2023-03-28 16:45:47 +02:00 committed by GitHub
parent 30103762db
commit 63af99eb75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 134 additions and 9 deletions

View file

@ -0,0 +1,110 @@
import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
dayjs.extend(timezone);
dayjs.extend(utc);
dayjs.extend(isBetween);
import { isInWorkingHours } from './WorkingHours.helpers';
describe('Is in working hours', () => {
const currentMoment = dayjs('2023-03-27 14:57');
test('Returns true when it is in working hours', () => {
const workingHours = {
monday: [{ end: '17:00:00', start: '09:00:00' }],
tuesday: [{ end: '17:00:00', start: '09:00:00' }],
wednesday: [{ end: '17:00:00', start: '09:00:00' }],
thursday: [{ end: '17:00:00', start: '09:00:00' }],
friday: [{ end: '17:00:00', start: '09:00:00' }],
saturday: [{ end: '17:00:00', start: '09:00:00' }],
sunday: [{ end: '17:00:00', start: '09:00:00' }],
};
expect(isInWorkingHours(currentMoment, workingHours, dayjs.tz.guess())).toBeTruthy();
});
test('Returns false when it is NOT in working hours', () => {
const workingHours = {
monday: [{ end: '14:00:00', start: '09:00:00' }],
tuesday: [{ end: '14:00:00', start: '09:00:00' }],
wednesday: [{ end: '14:00:00', start: '09:00:00' }],
thursday: [{ end: '14:00:00', start: '09:00:00' }],
friday: [{ end: '14:00:00', start: '09:00:00' }],
saturday: [{ end: '14:00:00', start: '09:00:00' }],
sunday: [{ end: '14:00:00', start: '09:00:00' }],
};
expect(isInWorkingHours(currentMoment, workingHours, dayjs.tz.guess())).toBeFalsy();
});
test('Returns false when it is complex Working hours schedule', () => {
const workingHours = {
monday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
tuesday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
wednesday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
thursday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
friday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
saturday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
sunday: [
{ start: '09:00:00', end: '11:00:00' },
{ start: '15:00:00', end: '18:00:00' },
],
};
expect(isInWorkingHours(currentMoment, workingHours, dayjs.tz.guess())).toBeFalsy();
});
test('Returns true when it is complex Working hours schedule', () => {
const workingHours = {
monday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
tuesday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
wednesday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
thursday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
friday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
saturday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
sunday: [
{ start: '09:00:00', end: '13:00:00' },
{ start: '14:00:00', end: '18:00:00' },
],
};
expect(isInWorkingHours(currentMoment, workingHours, dayjs.tz.guess())).toBeTruthy();
});
});

View file

@ -98,19 +98,34 @@ export const getNonWorkingMoments = (startMoment, endMoment, workingMoments) =>
return nonWorkingMoments;
};
const getDayJsDateFromTime = (momentToStart: dayjs.Dayjs, currentMoment: dayjs.Dayjs, workingHours) => {
const [hours, minutes, seconds] = workingHours.split(':');
return dayjs(momentToStart)
.set('date', currentMoment.date())
.set('hour', Number(hours))
.set('minute', Number(minutes))
.set('second', Number(seconds));
};
export const isInWorkingHours = (currentMoment: dayjs.Dayjs, workingHours, timezone) => {
const timeFormat = 'HH:mm:ss';
const momentToStart = dayjs().tz(timezone).utcOffset() === 0 ? currentMoment : currentMoment.tz(timezone);
const currentDayOfTheWeek = currentMoment.format('dddd').toLowerCase();
const workingHourStart = workingHours[currentDayOfTheWeek][0]?.start;
const workingHourEnd = workingHours[currentDayOfTheWeek][0]?.end;
if (workingHourStart && workingHourEnd) {
const startTime = dayjs(workingHourStart, timeFormat).tz(timezone).format(timeFormat);
const endTime = dayjs(workingHourEnd, timeFormat).tz(timezone).format(timeFormat);
const currentTime = dayjs(currentMoment, timeFormat).format(timeFormat);
if (workingHours[currentDayOfTheWeek]?.length > 0) {
const currentTime = dayjs(momentToStart);
return currentTime < endTime && currentTime >= startTime;
for (const range of workingHours[currentDayOfTheWeek]) {
const rangeStartData = range?.start;
const rangeEndData = range?.end;
let startTime = getDayJsDateFromTime(momentToStart, currentMoment, rangeStartData);
let endTime = getDayJsDateFromTime(momentToStart, currentMoment, rangeEndData);
if (currentTime.isBetween(startTime, endTime, null, '[)')) {
return true;
}
}
}
return false;
};