Determine the number of days without including weekends and holidays using JavaScript

I am working on a code that calculates the total number of days excluding weekends and specified holidays. After researching on various platforms like stackoverflow and adobe forum, I have come up with the following code. If a public holiday falls on a working day (Saturday-Wednesday), it is excluded from the calculation. However, my issue arises when a public holiday falls on a weekend (Thursday-Friday), as it deducts both the holiday and the weekend days. For example, for a leave duration from 18/09/2018 to 22/09/2018, the total count shows 2 days instead of 3. Similarly, for dates 17/10/2018-21/10/2018, the total count is 1 day instead of 3 days. I would greatly appreciate any assistance or ideas to resolve this problem!
Regards

//Thursday and Friday will be excluded as weekend.
var start = this.getField("From").value;
// get the start date value
var end = this.getField("To").value;
var end = util.scand("dd/mm/yyyy H:MM:SS", end + " 0:00:00");
var start =util.scand("dd/mm/yyyy H:MM:SS", start + " 0:00:00");
event.value = dateDifference(start, end);
function dateDifference(start, end) {
  // Copy date objects so don't modify originals
  var s = new Date(+start);
  var e = new Date(+end);
  // Set time to midday to avoid daylight saving and browser quirks
  s.setHours(12,0,0,0);
  e.setHours(12,0,0,0);
  // Get the difference in whole days
  var totalDays = Math.round((e - s) / 8.64e7);
  // Get the difference in whole weeks
  var wholeWeeks = totalDays / 7 | 0;
  // Estimate business days as number of whole weeks * 5
  var days = wholeWeeks * 5;
  // If not even number of weeks, calc remaining weekend days
  if (totalDays % 7) {
    s.setDate(s.getDate() + wholeWeeks * 7);
    while (s < e) {
      s.setDate(s.getDate() + 1);
      // If day isn't a Thursday or Friday, add to business days
      if (s.getDay() != 4 && s.getDay() != 5) {
        ++days;
      }
    }
  }
var hdayar = ["2018/02/21","2018/03/17","2018/03/26","2018/04/14","2018/05/01","2018/08/15","2018/09/2 1","2018/10/18","2018/10/19","2018/12/16","2018/12/25"];
//test for public holidays
var phdays = 0;
for (var i = 0; i <hdayar.length; i++){
if ((Date.parse(hdayar[i]) >= Date.parse(start)) && (Date.parse(hdayar[i]) <= Date.parse(end))) {phdays ++;}}
  return days-phdays + 1;
}

Answer №1

It is recommended to utilize an existing library instead of creating a solution from scratch.

However, if you prefer to create your own solution, you can use the .getDay method to determine if public holidays fall on a weekend.

var weekend = [4, 5],   // for Thursday, Friday
    holDate, holDay;
for (var i = 0; i < hdayar.length; i++){
    holDate = Date.parse(hdayar[i]);
    holDay = new Date(holDate).getDay()
    if (weekend.indexOf(holDay) == -1 && holDate >= Date.parse(start) && holDate <= Date.parse(end)) {
        phdays ++;
    }
}

The variable phdays will now store the count of public holidays that are not on weekends within the specified range.

Answer №2

Having encountered the same requirement, I devised a workaround which I hope will benefit others.

var holidayDates = ["4/18/2019", "4/19/2019", "4/20/2019", "4/25/2019", "4/26/2019"];
var startDate = new Date();
var endDate = new Date(startDate.setDate(startDate.getDate() + 1));

for (i = 0; i < holidayDates.length; i++) {
    var dayOfMonth = endDate.getDate();
    var month = endDate.getMonth() + 1; //Months are zero indexed
    var year = endDate.getFullYear();
    
    if ((month + '/' + dayOfMonth + '/' + year) === (holidayDates[i])) {
        endDate = new Date(endDate.setDate(endDate.getDate() + 1));
        
        if (endDate.getDay() == 6) {
            endDate = new Date(endDate.setDate(endDate.getDate() + 2));
        } else if (endDate.getDay() == 0) {
            endDate = new Date(endDate.setDate(endDate.getDate() + 1));
        }
    }
}

The end date provided gives you the next working day by disregarding the current day and starting comparison from the following day to check for holidays or weekends. You have the flexibility to customize the dateTime format as needed

(month + '/' + dayOfMonth + '/' + year)
. Exercise caution when comparing two dates as they may look similar but differ in reality. Make adjustments accordingly.

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

Changing array indices in JavaScript by splicing elements

I'm experiencing a curious issue that seems to involve overwriting array indices after splicing, or at least that's what I suspect. This problem arises in a small game project built using phaser 2 - essentially, it's a multiplayer jumping ga ...

Learn how to retrieve data by clicking on the previous and next buttons in FullCalendar using Vue.js

Seeking guidance on retrieving calendar data from the database for my Vue frontend, I have incorporated the fullcalendar API. Successfully able to retrieve data for the current week, however facing challenges when attempting to fetch data for the previous ...

Fetch data in JSON format from a specified URL

I have been attempting to fetch a JSON from a specific URL. Here is my current code snippet: <script> var co2; $(document).ready(function(){ alert("0"); $.getJSON(url,function(result){ var jsonObject = result; alert(result); ...

Sending numerous messages from a single event using Socket.io

After an exhaustive search, I have yet to find a solution to my problem. I am attempting to send a message from the server every time it detects a file change in a specific directory. However, instead of sending just one message, it sends the same message ...

What is the proper way to utilize "three.module.js"?

I am currently learning how to utilize modules and decided to start with a simple example. However, I encountered an issue where the script does not want to run. I must be missing something crucial, but I can't seem to figure out what it is. I have tr ...

Do you have any suggestions on how to fix this npm SQLite installation issue?

Could use some help with an SQLite installation error I'm encountering. Any ideas on what the issue might be and how to resolve it? C:\Users\jacka\Downloads\discord-emoji-stealer-master\discord-emoji-stealer-master>npm i & ...

Providing real-time results as numbers are added together

I need assistance in calculating a price inclusive of VAT based on a user-entered VAT rate. Is it possible to show the result in an input box dynamically as the user inputs the VAT rate and price, without requiring them to click a button or resubmit the fo ...

BufferGeometry's Vertices

Since version 125, the use of THREE.Geometry has been deprecated. As we update our code base, we are encountering errors that are proving difficult to resolve. Our current task involves creating a sphere and applying a raycaster on it to determine the int ...

Incorporating a new textfield in Codeigniter through a button/link activation

Currently, I am working on designing a request form for my website. I am facing an issue with creating a button that can dynamically add new input fields when clicked. Unfortunately, I am unsure of how to resolve this problem. Picture this: [ button ] A ...

The ngOnChanges method fails to exhibit the anticipated modifications in a variable

Trying to grasp the concept of the ngOnChanges() callback, I created an example below. Despite having values for the attributes title and content in the Post interface during compile time, I do not see any logs from ngOnChanges. Please advise on the corre ...

Ways to access a JavaScript function on a div with multiple identifiers

Currently working on developing a discussion panel using ASP.net, where each comment is assigned a unique id. I am looking to trigger the jQuery click function whenever a user clicks on a comment. However, since the comment ids are dynamically assigned an ...

The distinction between storing data and component data becomes apparent when using Vuex in conjunction with a persisted state

Below is my post.js file in the store directory: import axios from 'axios' import createPersistedState from "vuex-persistedstate" export default { namespaced: true, state: { sample_data: 'Welcome!!', l ...

Subdomain redirection issue with express-subdomain for localhost GET requests

In order to manage requests to specific subdomains, I am utilizing a package in express.js called express-subdomain. From my understanding, the subdomain constructor function requires an express router object that I pass from an exported router module. M ...

Express.js post request not functioning properly

I am currently in the process of developing a discussion-based Node.js/Express app and I am focusing on creating a discussion page. I have been attempting to test if my discussion controller file is properly linked, but for some reason every time I click t ...

Vue 3 gracefully handles errors by displaying an alternative component

I am currently developing a rendering library for my Vue 3 + Vite project. Essentially, I have a JSON array of products which I pass to a special <Render :products /> component. This Render component reads all the JSON products and converts them in ...

I am struggling to create a modal component for a settings button

I am currently working with Quasar VueJS and I have a requirement to add a button on my navbar that will trigger a pop-up dialog settings panel. This settings panel will be used for various functionalities such as dynamic theming, although that is somewhat ...

A method for displaying monthly data in a single row

Hey there! I'm currently dealing with a data list stored in an array. The |arraycontains various objects` each with their own properties such as name, created-at, and more. My goal is to display all users who were created within a specific month in on ...

Unable to remove jQuery variable using jQuery .remove() method

My goal is to remove the $movieDiv that appears when I click "#buttonLicensedMovie". It successfully appends to the html and the button hides as expected. However, I am encountering an issue when clicking the anchor tag with id "licensedMovie1", the $movie ...

Updating label values to default in JavaScript/jQuery

I need to utilize jQuery/js for the following tasks: Extract label values from form inputs Insert those labels as input values in the corresponding fields Conceal the labels It's a simple task. Instead of manually entering each label like this: $( ...

Tips for creating a substitute for a standard prototype in JavaScript

Having trouble with a JavaScript interpreter that has a buggy Array.prototype.sort. I want to replace it, at least for testing purposes. I have a function called mySort(array, comparator), but how can I make it work like array.sort(comparator)? I also ne ...