Retrieve the total number of hours within a designated time frame that falls within a different time frame

Having a difficult time with this, let me present you with a scenario:

A waiter at a restaurant earns $15/hour, but between 9:00 PM and 2:30 AM, he gets paid an additional $3/hour. I have the 'start' and 'end' of the shift as Date objects, and I want to calculate how many hours of that extra paid period are within the shift, if any. The start and end times of the shift can vary, which makes it challenging.

I managed to make it work using a lot of if statements, but I know that's not the most efficient way. Here is the code snippet link, but it's quite messy (involving two different time periods with extra pay). Does anyone have a better idea of how to calculate this? Are there any classes or methods that could assist in this calculation?

static calculateShiftSalary(shift: Shift, employee: Employee): Shift {
    const extraPaidStart = 22
    const extraPaidEnd= 2.5 // meaning 02:30 o'clock -of the next day here

    let start:Date = shift.startDate
    let end:Date = shift.endDate

    let extraHours:number = 
          getNumberOfExtraPaidHours(start,end,extraPaidStart,extraPaidEnd)
}

So, for example, if the shift is between 8:00 PM and 11:30 PM, 'extraHours' would be 1.5. If the shift is between 11:00 PM and 2:00 AM, 'extraHours' would be 3 hours.

Feel free to change 'extraPaidStart' and 'extraPaidEnd' to Date objects if that would be more beneficial.

Answer №1

Let's start with the simplest scenario: When our worker only works for one day, a timetable where overtime extends into the night would be laid out as follows:

extra paid ---|-- regular paying ---------|---- extra paid ---
      |--------- working time -----------------------------|
      |--- 1 -------|--------------- 2 ----------------|---- 3 ---|

When the extra time spans just one day, it becomes even simpler:

|----------- regular paying -------|------ extra paid ----|----|
    |------ working time -----------------|
    |-----  1 -----------------------------|- 2 -|

We now have three ranges to calculate when determining the worker's pay, all in minutes:

 function paymentRange(payment: number, start: number, end: number) {
    return function calculatePayment(startWorking: number, endWorking: number) {
      if(start < end) { 
        const rangeStart = Math.max(start, startWorking);
        const rangeEnd = Math.min(end, endWorking);
        return Math.max(rangeEnd - rangeStart, 0) / 60 * payment;
    } else {
       const morning =  Math.max(end - startWorking, 0);
       const evening = Math.max(endWorking - start, 0)
       return (morning + evening) / 60 * payment;
  }
 }
}

To combine multiple payments, we use:

 function combinedPayment(...payments) {
   return (start, end) => payments.reduce((sum, payment) => sum + payment(start, end), 0);
 }

To calculate the payment for one day, we can simply do this:

 const calculatePayment = combinedPayment(
   paymentRange(3/*$*/, 22/*h*/ * 60, 2/*h*/ * 60 + 30/*min*/),
   paymentRange(15/*$*/, 0/*min*/, 24/*h*/ * 60)
);

 // If he worked from 1h to 22h:
calculatePayment(1/*h*/ * 60, 22/*h*/ * 60)

Next, we need to break down the date range into days and calculate payments accordingly:

 const dateToMins = date => date.getHours() * 60 + date.getMinutes();

const toWholeDay = date => new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
const min = (a, b) => new Date(Math.min(+a, +b));
const max = (a, b) => new Date(Math.max(+a, +b));

 function paymentForDateRange(payment, start: Date, end: Date) {
  let pay = 0;
  let today = toWholeDay(start);
  while(+today < +end) {
    const nextDay = new Date(today + 1000 * 60 * 60 * 24);
    const startWorking = max(start, today);
    const endWorking = min(end, nextDay);
    pay += payment(dateToMins(startWorking), dateToMins(endWorking));
   today = nextDay;
  }
  return pay;
}

Finally, we can execute:

paymentForDateRange(calculatePayment, new Date(), new Date())

PS: While every part has not been fully tested, there may be some inconsistencies

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for deselecting text from a text field?

After performing a search and displaying the results on my search form, I've noticed that the text query in the textfield is being marked as selected text even though I don't want it to be. How can I prevent this? Fiddle 1) What is the best app ...

The async function in Jasmine is causing issues with expectedAsync functionality

Currently conducting the following examination: it("should receive rejection", async done => { class someTest { async run(){ return this.rejectFunc(); } async rejectFunc(){ return new Promise( ...

TS - deduce the specific type of a key value without receiving a union type

Welcome to the coding playground: Click here to start coding Let's talk about a scenario where a function is expected to return some value based on an input argument. The challenge arises when there are keys with the same name but different types re ...

Can someone explain the significance of '{}' within the function shown below?

I've been able to grasp most of this code, but I'm unsure about "{}". Can anyone clarify its meaning? var Toggle = function(section, expand) { this.section = section || {}; this.expand = expand | ...

After clearing the option, the onChange function stops functioning

I'm facing an issue with the following code: success: function (data) { $('#' + idDivRefresh).endLoading(); if (data.message != '@Geral.Sucesso') { $('#' + idDropDown + ...

The function to set the state in React is malfunctioning

I'm currently in the process of developing a website where I utilize fetch to retrieve information and display it to the user. Initially, I opted to save this data in a state variable, but for some reason, it's not functioning as expected. Upon ...

Is there a way to access various history.pushState events when using window.popState in JavaScript?

In my code, there are two pushStates that I need to read separately and execute different functions for. However, when the form is not submitted, the related pushState does not trigger and results in this error: Uncaught TypeError: Cannot read property &ap ...

Tips for displaying a removal option and eliminating an uploaded document

I need assistance in implementing file uploading using dropzone.js. I am struggling to find a solution on how to delete uploaded files. Here is the code snippet: index.php <div class="container"> <div class="file_upload"> <form action= ...

What is the best way to simultaneously utilize two APIs where one is using HTTP and the other is using HTTPS?

What is the best way to simultaneously use two APIs, one being http and the other https, in Angular or JavaScript? ...

What is the best way to fully reload an Angular component when the route is changed?

I'm looking for a way to reload or refresh a sidebar component when the route changes. Below is the code I currently have: constructor( private auth: AuthService, private router: Router, private changeDetector: ChangeDetectorRef ) { ...

Could you assist me in navigating the process of creating a dynamic 10x10 multiplication table using HTML and JavaScript? I'm eager to learn where to begin with this methodology

As I explore various questions related to the "simple" multiplication tables, I find myself with a more fundamental query. I am seeking clarity on how Javascript operates when intertwined with HTML, as that is where my confusion lies. In my multiplication ...

Navigating the screen reader with the cursor位

Site Design Challenge I recently discovered that the master/detail design of my website is not very accessible. The main view features a column chart where each column represents a different month. Clicking on one of these columns reveals details in a nes ...

Encountering an unexpected token while trying to use createUserWithEmailAndPassword in firebase/auth with Next.js and TypeScript left Jest puzzled

I have been working on integrating Firebase authentication into my Next.js project (using TypeScript), but it appears that there are configuration issues with Firebase causing my Jest tests to fail. Here are the key configuration files: jest.config.js : ...

Retrieve the chosen item along with its quantity

I'm currently working on building a shopping cart application similar to this example using React.js. index.js: (Sending each product to the product component) {products.length > 0 ? products.map((product) => ( <Produ ...

ag-grid-angular failing to present information in a table layout

I have implemented ag-grid-angular to showcase data in a structured table format, but the information appears jumbled up in one column. The data for my ag-grid is sourced directly from the raw dataset. https://i.stack.imgur.com/sjtv5.png Below is my com ...

How can I reverse the names displayed in ng-repeat when I click?

When utilizing the orderby filter in angularjs, I want to be able to sort the data only when the button is clicked. If the button is not clicked, the sorting order should not be displayed. <tr ng-repeat="tools in toolsfilter | orderBy:orderByField:reve ...

Troubleshooting jQuery Dropdown Menu Animation Bugs

Take a look at this interesting fiddle: https://jsfiddle.net/willbeeler/tfm8ohmw/ HTML: <a href="#" class="roll-btn">Press me! Roll me down and up again!</a> <ul class="roll-btns"> <li><a href="#" class="control animated noshow ...

Error message indicating that a TypeError is occurring specifically while using the

For the past two days, I've been encountering an error when attempting to upload files using AJAX with angularJS. The error occurs after selecting the file to upload, and it's a TypeError: TypeError: Failed to execute 'append' on &apos ...

Losing focus issue with Material-UI TextField occurs constantly with every onChange event

I am in the process of developing a new component: https://i.stack.imgur.com/czM9i.png This component will consist of an array of objects, each representing a prescription. Each object will include the medicine name selected from a dropdown and a text fi ...

Angular does not automatically update the template

I've been grappling with this issue for quite some time now and I can't seem to figure out why the angular template is failing to refresh when the scope changes. Here's a link to my JSFiddle - http://jsfiddle.net/HB7LU/2591/ (please note tha ...