I'm beginner in web programming, and now I'm trying to get the number of days between two dates excluding the weekends and the public holidays of each year of our country.
I want to get a list of holidays of my own specific year. Like I pass the year 2021, then it will return all the holidays of 2021, similarly, if I pass 2022, then it will return 2022.
By using the JavaScript, I calculated the difference between two dates excluding the weekends.
The following code describes the difference between two dates excluding the weekends.
function getBusinessDateCount (startDate, endDate) {
var elapsed, daysBeforeFirstSaturday, daysAfterLastSunday;
var ifThen = function (a, b, c) {
return a == b ? c : a;
};
elapsed = endDate - startDate; elapsed /= 86400000;
daysBeforeFirstSunday = (7 - startDate.getDay()) % 7; daysAfterLastSunday = endDate.getDay();
elapsed -= (daysBeforeFirstSunday + daysAfterLastSunday);
elapsed = (elapsed / 7) * 5;
elapsed += ifThen(daysBeforeFirstSunday - 1, -1, 0) + ifThen(daysAfterLastSunday, 6, 5);
return Math.ceil(elapsed); }
$(document).ready(function(){
$(document).on('change','#date2',function (evt) {
let start = document.querySelector('#date1').value,
end = document.querySelector('#date2').value,
result = getBusinessDateCount(new Date(start),
new Date(end));
document.getElementById("days").value = result+ " Jours";
}); });
Now, I'm stuck in how I can add also the public holidays of each year of our country and get the number between two dates excluding weekends and public holidays.
If you have any ideas, please help
You have date1 and date2. date1 was in year1 and date2 was in year2.
year2 >= year1
Even though it's possible that some holidays are not celebrated every year or, they were introduced between your two dates, for the sake of simplicity I will assume that any holiday is celebrated each year.
So, assuming there are n holidays celebrated yearly, you also know that for
year1 < y < year2
years, there are n holidays. So:
let holidays = 0;
if (year2 > year1 + 2) {
holidays = (year2 - year1 - 1) * n;
}
Now, you will need to loop your holidays and compare their months and date against the months and date of date1 and date2, so, if they are later than date1 then add them and if they are earlier than date2 then add them (if both criterias are fulfilled, add them twice):
let month1 = date1.getMonth();
let day1 = date1.getDate();
let month2 = date2.getMonth();
let day2 = date2.getDate();
for (let holiday of holidayArray) {
let m = holiday.getMonth();
let d = holiday.getDate();
if ((month1 < m) || ((month1 === m) && (day1 <= d))) {
holidays++;
}
if ((month2 > m) || ((month2 === m) && (day2 >= d))) {
holidays++;
}
}
Now, let's focus on the weekends, luckily this part was already solved at SO at How to determine number Saturdays and Sundays comes between two dates in java script
function countWeekendDays( d0, d1 )
{
var ndays = 1 + Math.round((d1.getTime()-d0.getTime())/(24*3600*1000));
var nsaturdays = Math.floor( (d0.getDay()+ndays) / 7 );
return 2*nsaturdays + (d0.getDay()==0) - (d1.getDay()==6);
}
At the result of countWeekendDays to holidays and that should solve the problem.
Related
This question already has answers here:
How to calculate number of days between two dates?
(42 answers)
Closed last month.
I am new to javascript.
I have specific month columns (9/30/2022, 10/31/2022,11/30/2022). I have a contract with a start date and end date (spanning multiple months).
I need to determine the number of days the contract was active for a specific month column.
Example:
Contact Start Date: 09/15/2022
Contract End Date: 10/24/2022
Number of days the contract was active in Sept 2022 is 16.
I found the code below that gives me the contract period broken down for each month (i.e.) **9 - 17; 10 - 23; **
Thank you in advance for any assistance.
I found this code
function getDays() {
var dropdt = new Date(document.getElementById("arr").value);
var pickdt = new Date(document.getElementById("dep").value);
var result = "";
for (var year = dropdt.getFullYear(); year <= pickdt.getFullYear(); year++) {
var firstMonth = (year == dropdt.getFullYear()) ? dropdt.getMonth() : 0;
var lastMonth = (year == pickdt.getFullYear()) ? pickdt.getMonth() : 11;
for (var month = firstMonth; month <= lastMonth; month++) {
var firstDay = (year === dropdt.getFullYear() && month === firstMonth) ? dropdt.getDate() : 1;
var lastDay = (year === pickdt.getFullYear() && month === lastMonth) ? pickdt.getDate() : 0;
var lastDateMonth = (lastDay === 0) ? (month + 1) : month
var firstDate = new Date(year, month, firstDay);
var lastDate = new Date(year, lastDateMonth, lastDay);
result += (month + 1) + " - " + parseInt((lastDate - firstDate) / (24 * 3600 * 1000) + 1) + "; ";
}
}
return result;
}
function cal() {
if (document.getElementById("dep")) {
document.getElementById("number-of-dates").value = getDays();
}
Calculate
`
The following snippet will generate an object res with the keys being zero-based month-indexes ("8" is for September, "9" for October, etc.) and the values are the number of days for each of these months:
const start=new Date("2022-09-15");
const end=new Date("2022-11-24");
let nextFirst=new Date(start.getTime()), month, days={};
do {
month=nextFirst.getMonth();
nextFirst.setMonth(month+1);nextFirst.setDate(1);
days[month]=Math.round(((nextFirst<end?nextFirst:end)-start)/86400000);
start.setTime(nextFirst.getTime());
} while(nextFirst<end)
console.log(days);
This can be extended into a more reliable function returning a year-month combination:
function daysPerMonth(start,end){
let nextFirst=new Date(start.getTime()), year, month, days={};
do {
year=nextFirst.getFullYear();
month=nextFirst.getMonth();
nextFirst.setMonth(month+1);nextFirst.setDate(1);
days[`${year}-${String(1+month).padStart(2,"0")}`]=Math.round(((nextFirst<end?nextFirst:end)-start)/86400000);
start.setTime(nextFirst.getTime());
} while(nextFirst<end)
return days;
}
[["2022-09-15","2022-11-24"],["2022-11-29","2023-02-04"]].forEach(([a,b])=>
console.log(daysPerMonth(new Date(a),new Date(b))));
Managing and calculating dates, times, and date-times are notoriously finicky in javascript and across browsers. Rather than trying to define your own logic for this use the famous Moment.js library.
In particular to calculate the length between two dates you can utilize the diff function between two moments
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 25]);
var diff = a.diff(b, 'days') // 1
console.log(diff);
<script src="https://momentjs.com/downloads/moment.js"></script>
The supported measurements are years, months, weeks, days, hours, minutes, and seconds.
I am trying to write a code where total days will be counted excluding weekends and custom defined holiday. I searched through stackoverflow and adobe forum to find a solution and came with below code.
If public holiday falls in a working day (Saturday-Wednesday) it is excluding from calculation.
My problem is that if public holiday falls in weekend (Thursday-Friday), it is deducting for both (holiday & weekend). Suppose leave duration is 18/09/2018-22/09/2018, total count 2 days is showing in place of 3. Again for 17/10/2018-21/10/2018, total count 1 day is showing in place of 3 days.
Any help or any idea to solve the problem would be great!
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;
}
You should use a library for this rather than reinventing the wheel.
But if you want to do it yourself you could use .getDay to check if the public holidays are 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 ++;
}
}
phdays will now contain the number of non-weekend public holidays within the range.
Just have the same requirement and this is the my work around.Hope it helps other
var holiday = ["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 < holiday.length; i++) {
var date = endDate.getDate();
var month = endDate.getMonth() + 1; //Months are zero based
var year = endDate.getFullYear();
if ((month + '/' + date + '/' + year) === (holiday[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));
}
}
}
Here, end date gives you next working day.Here,I'm ignoring current day and start comparing from Next day whether it's holiday or weekend.You can customize dateTime as per your requirement (month + '/' + date + '/' + year).Careful whenever you compares two dates with each other. Because it looks same but actually it's not.So customize accordingly.
How would you increase a a number on a webpage twice a week on specific days and times?
For example the webpage would read:
"2 Apples"
However every Tuesday & Thursday at 9:00pm the number should increase by two.
So by Friday the number should have increased to 6 "Apples"
What's a simple way to increment this in Javascript, php or Jquery?
As it was mentionned in the comments, I advise you to use a cron to handle this.
First, you have to store your value somewhere (file, databse, ...). Then, you should create a cron job, that runs a code that increase and update your value at the given days of the week.
Some help about crons : https://en.wikipedia.org/wiki/Cron#Examples
I would add this post about cron and php : Executing a PHP script with a CRON Job
Hope it helps
Here a Javascript version, you can pass it the date it should start counting, the date you want to know the ammount of apples of, the days of the week apples will be added, the hours of the day the updat will take place and the ammount of apples that will be added on each of these dates.
Date.prototype.addDays = function (days) {
var result = new Date(this);
result.setDate(result.getDate() + days);
return result;
}
Date.prototype.addHours = function (hours) {
var result = new Date(this);
result.setHours(result.getHours() + hours);
return result;
}
function getApples(startdate, date, updateDays, updateTime, applesPerUpdate) {
var startDay = startdate.getDay();
var firstUpdateDate;
for(day of updateDays) {
if (day >= startDay) {//assumes startdate has no time added
firstUpdateDate = startdate.addDays(day - startDay).addHours(updateTime);
break;
}
}
if (!firstUpdateDate)
firstUpdateDate = startdate.addDays(7 - (startDay - updateDays[0])).addHours(updateTime);
var updateDaysReverse = updateDays.slice(0).reverse();//clones the array
var dateDay = date.getDay();
var lastUpdateDate;
for(day of updateDaysReverse) {
if (day < dateDay || day == dateDay && date.getHours() > updateTime) {
lastUpdateDate = date.addDays(day - dateDay);
break;
}
}
if (!lastUpdateDate)
lastUpdateDate = date.addDays(updateDaysReverse[0] - (7 + dateDay));
lastUpdateDate = new Date(Date.UTC(1900 + lastUpdateDate.getYear(), lastUpdateDate.getMonth(), lastUpdateDate.getDate(), updateTime, 0, 0, 0));
var secs = Math.trunc((lastUpdateDate - firstUpdateDate));
if (secs < 0) return 0;
var dayDiffs = [];
for(day of updateDays)
dayDiffs.push(day - updateDays[0]);
var weeks = Math.trunc(secs / 604800000);
var days = Math.trunc((secs % 604800000) / 86400000);
var apples = weeks * updateDays.length;
for(diff of dayDiffs)
{
if (diff <= days)
apples++;
else
break;
}
return apples * applesPerUpdate;
}
// important, day and month is zero-based
var startDate = new Date(Date.UTC(2016, 01, 07, 0, 0, 0, 0));
var updateDays = [2, 4];// 0 = sunday , have to be in order and must be 0 <= x < 7
var updateTime = 9;
console.log(getApples(startDate, new Date(), updateDays, updateTime, 2));
Was more coplicated than I thaught, and i havn't testet it much, so there may be bugs.
Here is a plunker to play with the values.
How would I write this expression in JavaScript?
It is to represent a date that is 2 weeks, counted by each passing Thursday, but excludes the thursday of the week the date was made.
NeededDay = Today + (18 - DayOfWeek(today))
or since it is Wednesday, it could be written?
var date = new Date();
var NeededDate = date.getDay() + (18-3);
or
I wrote this but I do not know if it is right?
var value = 3;
var GivenDate = value;
var GivenDay = value.getDay();
var daysToSecondThursday = Givenday2.setDate(GivenDay + Givenday2.setDate(18 - GivenDay));
alert("two weeks after next thursday is = " + daysToSecondThursday.val());
what is the correct way? ?
You could use:
function GetThursdayIn2Weeks(date)
{
var day = date.getDay();
// Add 2 weeks.
var newDate = new Date(date.setTime(date.getTime() + (14 * 86400000)));
// Adjust for Thursday.
var adjust = 4 - day;
if (adjust <= 0) // Might need to be changed - See comments!
adjust +=7;
// Apply Thursday adjustment.
newDate = new Date(newDate.setTime(newDate.getTime() + (adjust * 86400000)));
return newDate;
}
If the date passed in is Thursday, then it will return two weeks from the following Thursday. If this is not what you want, then adjust the if (adjust <= 0) code above to be:
if (adjust < 0)
Here is a jsFiddle: http://jsfiddle.net/kgjertsen/ec7vnezn/
Hey javascript masters,
Attempting to create an age verification page to a client's site. Code below is not functioning as it doesn't matter what year you select, it will still allow you to enter the site. Not sure what I should be looking at to correct.
Any help is appreciated.
<script type="text/javascript"><!--
function checkAge(f){
var dob=new Date();
var date=dob.getDate();
var month=dob.getMonth() + 1;
var year=dob.getFullYear();
var cmbmonth=parseInt(document.getElementById("cmbmonth").options[document.getElementById("cmbmonth").selectedIndex].value);
var cmbday=parseInt(document.getElementById("cmbday").options[document.getElementById("cmbday").selectedIndex].value);
var cmbyear=parseInt(document.getElementById("cmbyear").options[document.getElementById("cmbyear").selectedIndex].value);
age=year-cmbyear;
if(cmbmonth>month){age--;}
else{if(cmbmonth==month && cmbday>=date){age--;}}
if(cmbmonth==0){alert("You must enter the month you were born in.");return false;}
else if(cmbday==0){alert("You must enter the day you were born on.");return false;}
else if(cmbyear==2005){alert("You must enter the year you were born in.");return false;}
else if(age<13){alert("You are unable to view this site!");location.replace("http://www.dharmatalks.org");return false;}
else{return true;}
}
// --></script>
Calculating age in years, months and days is a bit trickier than it should be due to the differences in month and year lengths. Here's a function that will return the difference between two dates in years, months, days, hours, minutes and seconds.
function dateDifference(start, end) {
// Copy date objects so don't modify originals
var s = new Date(+start);
var e = new Date(+end);
var timeDiff, years, months, days, hours, minutes, seconds;
// Get estimate of year difference
years = e.getFullYear() - s.getFullYear();
// Add difference to start, if greater than end, remove one year
// Note start from restored start date as adding and subtracting years
// may not be symetric
s.setFullYear(s.getFullYear() + years);
if (s > e) {
--years;
s = new Date(+start);
s.setFullYear(s.getFullYear() + years);
}
// Get estimate of months
months = e.getMonth() - s.getMonth();
months += months < 0? 12 : 0;
// Add difference to start, adjust if greater
s.setMonth(s.getMonth() + months);
if (s > e) {
--months;
s = new Date(+start);
s.setFullYear(s.getFullYear() + years);
s.setMonth(s.getMonth() + months);
}
// Get remaining time difference, round to next full second
timeDiff = (e - s + 999) / 1e3 | 0;
days = timeDiff / 8.64e4 | 0;
hours = (timeDiff % 8.64e4) / 3.6e3 | 0;
minutes = (timeDiff % 3.6e3) / 6e1 | 0;
seconds = timeDiff % 6e1;
return [years, months, days, hours, minutes, seconds];
}
You can abbreviate the above just after the year part and return just that if you want.
Note that in your code:
var cmbmonth=parseInt(document.getElementById("cmbmonth").options[document.getElementById("cmbmonth").selectedIndex].value);
can be:
var cmbmonth = document.getElementById("cmbmonth").value;
There is no need for parseInt, the Date constructor will happily work with string values. If you have used calendar month numbers for the values (i.e. Jan = 1) then subtract 1 before giving it to the Date constructor, but simpler to use javascript month indexes for the values (i.e. Jan = 0).
You can then do:
var diff = dateDifference(new Date(cmbyear, cmbmonth, cmbdate), new Date());
if (diff[0] < 18) {
// sorry, under 18
}