7

I have two sets of codes that work. Needed help combining them into one.

This code gets me the difference between two dates. works perfectly:

function test(){
var date1 = new Date(txtbox_1.value);    
var date2 = new Date(txtbox_2.value);

var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff));

var days = Math.floor(diff/(24*60*60));
var leftSec = diff - days * 24*60*60;

var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;

var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;

txtbox_3.value = days + "." + hrs; }

source for the above code

The code below by @cyberfly appears to have the answer of excluding sat and sun which is what i needed. source. However, its in jquery and the above code is in JS. Therefore, needed help combining as i lacked that knowledge :(

<script type="text/javascript">

$("#startdate, #enddate").change(function() {       

var d1 = $("#startdate").val();
var d2 = $("#enddate").val();

        var minutes = 1000*60;
        var hours = minutes*60;
        var day = hours*24;

        var startdate1 = getDateFromFormat(d1, "d-m-y");
        var enddate1 = getDateFromFormat(d2, "d-m-y");

        var days = calcBusinessDays(new Date(startdate1),new Date(enddate1));             

if(days>0)
{ $("#noofdays").val(days);}
else
{ $("#noofdays").val(0);}


});

</script>

EDIT Made an attempt at combining the codes. here is my sample. getting object expected error.

function test(){
var date1 = new Date(startdate.value);    
var date2 = new Date(enddate.value);
var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff)); 
var days = Math.floor(diff/(24*60*60));
var leftSec = diff - days * 24*60*60;
var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;
var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;

var startdate1 = getDateFromFormat(startdate, "dd/mm/yyyy hh:mm");
var enddate1 = getDateFromFormat(enddate, "dd/mm/yyyy hh:mm");
days = calcBusinessDays(new Date(startdate1),new Date(enddate1));           
noofdays.value = days + "." + hrs; }

start: <input type="text" id="startdate" name="startdate" value="02/03/2015 00:00">
end: <input type="text" id="enddate" name="enddate" value="02/03/2015 00:01">
<input type="text" id="noofdays" name="noofdays" value="">

Community
  • 1
  • 1
marv
  • 962
  • 3
  • 9
  • 17
  • 1
    You're missing the `calcBusinessDays()` function in your post which is the relevant portion of the code. – jfriend00 Feb 02 '15 at 20:44
  • FYI, jQuery is JavaScript. It's just a library of already written functions that makes it easier for you to do common things in JavaScript. To use jQuery, just [include it as an import](https://developers.google.com/speed/libraries/devguide#jquery). – Matthew Herbst Feb 02 '15 at 20:48
  • 1
    In the second function, you are missing the important bits: *getDateFromFormat* and *calcBusinessDays*, which are the bits actually doing the calculations. jQuery is just being used to get and set some values in the page and can be replaced with about the same amount of plain JS. The "*…works perfectly…*" part is questionable since you are parsing strings without validating the input and using the built–in *Date.parse* (which is used when passing strings to the Date constructor). I suspect decent testing will reveal errors. – RobG Feb 02 '15 at 20:57
  • Please do not use the [tag:jquery-validate] tag when the question has nothing to do with the jQuery Validate plugin. – Sparky Feb 02 '15 at 21:09
  • @jfriend00 Hi everyone. thank you for taking time and looking at my post. I tried to combine the two codes but get an object expected error. I think its something trivial but i was unable to debug it. Posted my code sample above. Kindly help. – marv Feb 03 '15 at 10:03
  • How do you count business days? Is Sunday to Monday one day or zero? Is Monday to Friday is 5 business days or 4? If 5, then Tue to Fri is 4, Wed to Fri is 3, Thu to Fri is 2 and Fri to Fri is 1. If 4, then Sun to Fri must be 5 and Sun to Mon is 1. – RobG Feb 03 '15 at 13:06
  • @RobG ok i think i give up. dont think i'm able to translate that into code. thanks for the comment anyway – marv Feb 03 '15 at 15:11

6 Answers6

17

When determining the number of days between two dates, there are lots of decisions to be made about what is a day. For example, the period 1 Feb to 2 Feb is generally one day, so 1 Feb to 1 Feb is zero days.

When adding the complexity of counting only business days, things get a lot tougher. E.g. Monday 2 Feb 2015 to Friday 6 February is 4 elapsed days (Monday to Tuesday is 1, Monday to Wednesday is 2, etc.), however the expression "Monday to Friday" is generally viewed as 5 business days and the duration Mon 2 Feb to Sat 7 Feb should also be 4 business days, but Sunday to Saturday should be 5.

So here's my algorithm:

  1. Get the total number of whole days between the two dates
  2. Divide by 7 to get the number of whole weeks
  3. Multiply the number of weeks by two to get the number of weekend days
  4. Subtract the number of weekend days from the whole to get business days
  5. If the number of total days is not an even number of weeks, add the numbe of weeks * 7 to the start date to get a temp date
  6. While the temp date is less than the end date:
  • if the temp date is not a Saturday or Sunday, add one the business days
  • add one to the temp date
  1. That's it.

The stepping part at the end can probably be replaced by some other algorithm, but it will never loop for more than 6 days so it's a simple and reasonably efficient solution to the issue of uneven weeks.

Some consequences of the above:

  1. Monday to Friday is 4 business days
  2. Any day to the same day in a different week is an even number of weeks and therefore an even mutiple of 5, e.g. Monday 2 Feb to Monday 9 Feb and Sunday 1 Feb to Sunday 8 Feb are 5 business days
  3. Friday 6 Feb to Sunday 7 Feb is zero business days
  4. Friday 6 Feb to Monday 9 Feb is one business day
  5. Sunday 8 Feb to: Sunday 15 Feb, Sat 14 Feb and Fri 13 Feb are all 5 business days

Here's the code:

// Expects start date to be before end date
// start and end are Date objects
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 dalight 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 Sunday or Saturday, add to business days
      if (s.getDay() != 0 && s.getDay() != 6) {
        ++days;
      }
    }
  }
  return days;
}

I don't know how it compares to jfriend00's answer or the code you referenced, if you want the period to be inclusive, just add one if the start or end date are a business day.

peterh
  • 11,875
  • 18
  • 85
  • 108
RobG
  • 142,382
  • 31
  • 172
  • 209
  • 1
    Thank you SO MUCH for the detailed explanation Rob. I cant tell you how much i appreciate your time and effort. your solution works well!! :) – marv Feb 04 '15 at 12:12
  • @RobG this returns the number of days, what if we want to display all the resulted dates too? Could you please amend a bit. Thank you –  Nov 22 '17 at 11:51
  • @Mogambo—what are "resulted dates"? If you mean the weekend dates that are excluded, that is a different question so no, I won't amend the answer. – RobG Nov 23 '17 at 04:09
  • @RobG see this please :) https://stackoverflow.com/questions/47449790/passing-the-list-of-dates-to-view-and-comparing-with-the-already-specified-dates –  Nov 23 '17 at 07:35
5

Here's a simple function to calculate the number of business days between two date objects. As designed, it does not count the start day, but does count the end day so if you give it a date on a Tuesday of one week and a Tuesday of the next week, it will return 5 business days. This does not account for holidays, but does work properly across daylight savings changes.

function calcBusinessDays(start, end) {
    // This makes no effort to account for holidays
    // Counts end day, does not count start day

    // make copies we can normalize without changing passed in objects    
    var start = new Date(start);
    var end = new Date(end);

    // initial total
    var totalBusinessDays = 0;

    // normalize both start and end to beginning of the day
    start.setHours(0,0,0,0);
    end.setHours(0,0,0,0);

    var current = new Date(start);
    current.setDate(current.getDate() + 1);
    var day;
    // loop through each day, checking
    while (current <= end) {
        day = current.getDay();
        if (day >= 1 && day <= 5) {
            ++totalBusinessDays;
        }
        current.setDate(current.getDate() + 1);
    }
    return totalBusinessDays;
}

And, the jQuery + jQueryUI code for a demo:

// make both input fields into date pickers
$("#startDate, #endDate").datepicker();

// process click to calculate the difference between the two days
$("#calc").click(function(e) {
    var diff = calcBusinessDays(
        $("#startDate").datepicker("getDate"), 
        $("#endDate").datepicker("getDate")
    );
    $("#diff").html(diff);
});

And, here's a simple demo built with the date picker in jQueryUI: http://jsfiddle.net/jfriend00/z1txs10d/

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Re: "*…but does work properly across daylight savings changes*". There's a bug in Safari where it applies daylight saving 4 hours early on the changeover date, so midnight on the last day becomes 23:00 (and *vice versa* at the start). May not affect your algorithm though. I set the time to noon and round so as to avoid it for whole days at least. – RobG Feb 04 '15 at 03:59
  • @jfriend00 Thank you so much mate, i tried your solution as well and it works awesome!! Again, appreciate your time and help on this one. – marv Feb 04 '15 at 12:13
  • @jfriend00 Can you look at this please? https://stackoverflow.com/questions/47435105/displaying-the-filtered-dates-from-a-given-range-of-dates-excluding-the-weekends – DirtyBit Nov 22 '17 at 13:05
  • this ain't working for month january 2021. showing 20 days – Flash Noob Aug 03 '21 at 11:45
2

const firstDate = new Date("December 30, 2020");
const secondDate = new Date("January 4, 2021");
const daysWithOutWeekEnd = [];
for (var currentDate = new Date(firstDate); currentDate <= secondDate; currentDate.setDate(currentDate.getDate() + 1)) {
  // console.log(currentDate);
  if (currentDate.getDay() != 0 && currentDate.getDay() != 6) {
    daysWithOutWeekEnd.push(new Date(currentDate));
  }
}
console.log(daysWithOutWeekEnd, daysWithOutWeekEnd.length);
RobG
  • 142,382
  • 31
  • 172
  • 209
  • 2
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – janw Dec 29 '20 at 16:25
1

@RobG has given an excellent algorithm to separate business days from weekends. I think the only problem is if the starting days is a weekend, Saturday or Sunday, then the no of working days/weekends will one less.

Corrected code is below.

function dateDifference(start, end) {

  // Copy date objects so don't modify originals

  var s = new Date(start);
  var e = new Date(end);

    var addOneMoreDay = 0;
    if( s.getDay() == 0 || s.getDay() == 6 ) {
    addOneMoreDay = 1;
  }

  // Set time to midday to avoid dalight 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 Sunday or Saturday, add to business days
      if (s.getDay() != 0 && s.getDay() != 6) {
        ++days;
      }
      //s.setDate(s.getDate() + 1);
    }
  }
  var weekEndDays = totalDays - days + addOneMoreDay;
  return weekEndDays;
}

JSFiddle link is https://jsfiddle.net/ykxj4k09/2/

Pranav
  • 21
  • 2
0

First Get the Number of Days in a month

     totalDays(month, year) {
        return new Date(year, month, 0).getDate();
     }

Then Get No Of Working Days In A Month By removing Saturday and Sunday

  totalWorkdays() {
     var d = new Date(); // to know present date
     var m = d.getMonth() + 1; // to know present month
     var y = d.getFullYear(); // to knoow present year
     var td = this.totalDays(m, y);// to get no of days in a month
     for (var i = 1; i <= td; i++) {  
        var s = new Date(y, m - 1, i);
        if (s.getDay() != 0 && s.getDay() != 6) {
           this.workDays.push(s.getDate());// working days
        }else {
           this.totalWeekDays.push(s.getDate());//week days
         }
      }
      this.totalWorkingDays = this.workDays.length;
 }
0

I thought the above code snippets others shared are lengthy. I am sharing a concise snippet that gives date after considering the total number of days specified. we can also customize dates other than Saturdays and Sundays.

function getBusinessDays(dateObj, days) {
    for (var i = 0; i < days; i++) {
        if (days > 0) {
            switch (dateObj.getDay()) {
                // 6 being Saturday and 0 being Sunday.
                case 6, 0:
                    dateObj.setDate(dateObj.getDate() + 2)
                    break;
                //5 = Friday.
                case 5:
                    dateObj.setDate(dateObj.getDate() + 3)
                    break;
                //handle Monday, Tuesday, Wednesday and Thursday!
                default:
                    dateObj.setDate(dateObj.getDate() + 1)
                    //console.log(dateObj)
                    break;
            }
        }
    }

    return dateObj;
}

console.log(getBusinessDays(new Date(), 11))
//Mon Dec 20 2021 18:56:01 GMT+0530 (India Standard Time)
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 03 '21 at 15:06