I'm trying to create a method to calculate the total days off.
I have an array that contains the working days:
"workingDays": [1,2,3,4,5],
So I have two dates; a startDate and an endDate, and I should count in this range how many days aren't working days (i.e. total days off).
For example, I have a range from 03/15 (today) to 03/21, a total of 7 days.
Today (03/15) is day 2, and it is a working day so I don't have to increment a counter for days off, while for example 03/19 is not a working day (it is number 6) so I have to increment the day off variable.
I have tried to implement the code, but it doesn't work correctly:
const checkDate = (start, end) => {
const workingDays = [1,2,3,4,5]
let dayOff = 0
var currentDate = new Date(start)
while (currentDate <= end) {
workingDays.map((day) => {
console.log('current ', currentDate.getDay(), ' day ', day)
if (currentDate.getDay() !== day) {
dayOff += 1
}
currentDate = currentDate.addDays(1)
})
}
console.log('dayOff ', dayOff)
return dayOff
}
it prints me:
LOG current 2 day 1
LOG current 3 day 2
LOG current 4 day 3
LOG current 5 day 4
LOG current 6 day 5
LOG current 0 day 1
LOG current 1 day 2
LOG current 2 day 3
LOG current 3 day 4
LOG current 4 day 5
LOG dayOff 10
but it is wrong because the result should be 2.
How can I do? Thank you
EDIT.
The function that I use to add a day:
Date.prototype.addDays = function (days) {
var date = new Date(this.valueOf())
date.setDate(date.getDate() + days)
return date
}
currentDate = currentDate.addDays(1)
.addDays is not a correct function of Javascript. It's used in C#.
Below is the right code which will return correct answer:
const workingDays = [1,2,3,4,5]
const endDate = new Date(startDate)
let dayOff = []
var currentDate = new Date(endDate)
while (currentDate <= endDate) {
console.log('currentDate', currentDate)
let index = workingDays.indexOf(currentDate.getDay());
console.log('dayOff - index', index)
if(index == -1)
{
console.log('dayOffDate - addded', currentDate)
dayOff.push(currentDate)
}
currentDate = new Date(currentDate.setDate(currentDate.getDate() + 1))
}
The following small function will calculate the total days off between two (2) dates, given the first date and the end date.
It is simple and assumes the end date is the same or higher than the start date (does not check for reversing the dates).
function getTotalOffDays(start,end) {
const workingDays = [1,2,3,4,5];
let daysOff = 0, // days off counter
date = new Date(start), // starting date
endDate = new Date(end); // end date
while (date <= endDate) {
if (!workingDays.includes(date.getUTCDay())) daysOff += 1; // increment days off
date = new Date(date.setUTCDate(date.getUTCDate() + 1)); // go the next day
}
return daysOff;
}
console.log("Total days off: " + getTotalOffDays("2022-03-15", "2022-03-21"));
Related
I want to retrieve a date by providing day number of a specific week
E.g
When I say
day: 1
It should provide me:
2023-01-15
What I have tried so far is:
function calculatedDate (day){
let date = new Date();
let dayAtDate = date.getDay();
let dayDiff = day - dayAtDate;
if(dayDiff < 0){
dayDiff = 7 + dayDiff;
}
let desiredDate = date.setDate(date.getDate() + dayDiff);
return new Date(desiredDate);
}
console.log(calculatedDate(1));
Now the problem with above code is that it considers day: 1 as monday, but I want day: 1 to be sunday here.
Can anyone help me with the best possible way here?
How about just -1 the provided day? that should solve it:
function calculatedDate (day){
let date = new Date();
let dayAtDate = date.getDay();
day = day - 1;
let dayDiff = day - dayAtDate;
if(dayDiff < 0){
dayDiff = 7 + dayDiff;
}
let desiredDate = date.setDate(date.getDate() + dayDiff);
return new Date(desiredDate);
}
console.log(calculatedDate(1));
You'd probably want to add some validation on the input parameter day, make sure it's a number and 1 or greater.
The current day will be 0, account for this by making the following change.
if(dayDiff < 0){
dayDiff = 6 + dayDiff;
}
Sunday is 0, Monday is 1 here :
function calculatedDate (day) {
let date = new Date();
let dayAtDate = date.getDay();
let dayDiff = day - (dayAtDate + 1); // change here
if (dayDiff < 0) {
dayDiff = 7 + dayDiff;
}
let desiredDate = date.setDate(date.getDate() + dayDiff);
return new Date(desiredDate);
}
console.log(calculatedDate(1));
I have a model in my database that contains an array called "AvailableDays" [0...6]. 0 = Sunday & 6 = Saturday. I am looking to convert this day number of the week to the date of day in the current week.
For example, this is the logic broken down
Retrieve the list of available days (const availableDays = [0,2,4,6])
Get the current DATE (const today = new Date('2021-08-20');)
Covert day numbers to dates (output =['15-08-2021', '17-08-2021', '19-08-2021', '21-08-2021'])
What you can do is get the day-of-the-week from the given Date instance and work out the offset from your available day.
Then subtract that offset in days from the given date to produce your result.
const transformDate = (date, day) => {
const offset = date.getDay() - day
const d = new Date(date)
d.setDate(d.getDate() - offset)
return d
}
const availableDays = [0,2,4,6]
const today = new Date("2021-08-20")
console.log(availableDays.map(day => transformDate(today, day)))
Was able to solve this myself. I am now able to wrap this into a availableDates.map() and return an array of dates using the below logic.
var availableDay = 0
var d = new Date(),
day = d.getDay(), // 0 ... 6
calcAvailableDay = day-availableDay,
diff = d.getDate() - calcAvailableDay,
output = new Date(d.setDate(diff));
console.log(output)
You can generate all the days in weeks and then get the dates using availableDays.
const getWeekDays = (current) => {
current.setDate((current.getDate() - current.getDay() - 1));
return Array.from({ length: 7 }, (_, i) => {
current.setDate(current.getDate() + 1)
return new Date(current).toLocaleDateString('en-CA');
});
},
today = new Date('2021-08-20'),
weekDays = getWeekDays(today),
availableDays = [0, 2, 4, 6],
availableDates = availableDays.map(day => weekDays[day]);
console.log(availableDates);
JavaScript getDay method returns the day of the week for the specified date according to local time, where 0 represents Sunday.
So what you have to do is connect this index with your availableDays values.
Logic
Get current date, month, year and the index of todays date.
Loop through the availableDays array, and create new dates with the difference between the current day calculated with getDay value and the day value specified in your array.
Make use of some logic to reperesent those date object in specified format. I took support from this post to format your date string.
const availableDays = [0,2,4,6];
const today = new Date();
const currentDay = today.getDay();
const currentDate = today.getDate();
const currentMonth = today.getMonth();
const currentYear = today.getFullYear();
formatDateToString = (date) => String(date.getDate()).padStart(2, '0') + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + date.getFullYear();
const output = availableDays.map((day) => formatDateToString(new Date(currentYear, currentMonth, currentDate - (currentDay - day))));
console.log(output);
This question already has answers here:
Find day difference between two dates (excluding weekend days)
(13 answers)
Closed 3 years ago.
In my application i have two date picker as start date and end date. when user choose start and end date the system will show the days between two dates but excluding the saturday and sunday. How to calculate it by using angularjs?
Does something like this work:
var startDate = new Date("01-10-2020");
var endDate = new Date("01-20-2020");
var nextDay = new Date(startDate);
var cnt = 0;
do {
/*if (nextDay.getDay() >= 1 && nextDay.getDay() <= 5) {
cnt = cnt + 1;
}*/
cnt += (nextDay.getDay() >= 1 && nextDay.getDay() <= 5) ? 1 : 0;
nextDay.setDate(nextDay.getDate() + 1);
} while (nextDay <= endDate);
console.log("Number of week days between " + startDate + " and " + endDate + " = " + cnt);
Here is the fiddler.
You don't want to do an expensive loop over every day to see whether it is Saturday or Sunday. The logic should be as follows:
Work in UTC so we don't need to worry about time zone
Calculate total number of calendar weeks. In a single calendar week, there are guaranteed to be 5 weekdays (not weekends == SAT || SUN)
Calculate the remainder of days. This will be added to the calculation later.
Determine the "finalAdjustment" by seeing if the remainder falls on weekend days.
The number of weekdays is (5 * numWeeks) + remainderDays + finalAdjust
(function() {
"use strict";
var SUN = 0;
var MON = 1;
var TUE = 2;
var WED = 3;
var THU = 4;
var FRI = 5;
var SAT = 6;
function isWeekendDay(day) {
return day === SAT || day === SUN;
}
function numberWeekDays(start, end) {
var numCalendarDays = (end - start) / 1000 / 60 / 60 / 24;
var numWeeks = Math.floor(numCalendarDays / 7);
// Potential days to add on to the number of full calendar
// weeks. This will be adjusted by "finalAdjust"
var remainderDays = numCalendarDays % 7;
// Adjustments for start and end dates being on a weekend
// ----------------------------
// Start at one because the same day should count as 1
// but number of days between same day is 0 based on
// arithmetic above.
// Change this to 0 if you don't want end date inclusive...
var finalAdjust = 1;
var startDay = start.getUTCDay();
var endDay = end.getUTCDay();
// On a weekend, so adjust by subtracting 1
if (isWeekendDay(startDay)) {
finalAdjust--;
}
// On a weekend, so adjust by subtracting 1
if (isWeekendDay(endDay)) {
finalAdjust--;
}
// This accounts for subtracting an extra weekend when starting
// at the beginning of a weekend (e.g. Saturday into Monday)
// The end day cannot also be on a weekend based on week modular division (mod 7)
if (startDay === SAT && remainderDays > 2) {
finalAdjust--;
}
// ---------------------------
// For every full calendar week there are 5 week days
// Use that number with the remainderDays and finalAdjust above
// to arrive at the answer.
var numWeekDays = (5 * numWeeks) + remainderDays + finalAdjust;
return numWeekDays;
}
// Test cases
// Assume that the start and end dates are inclusive
// 2020-01-01 to 2020-01-01 is one day
// 2020-01-01 to 2020-01-02 is two days
// ----------------------
// A Wednesdday
var start = new Date("2020-01-08");
// A Saturday
var end = new Date("2020-02-01");
// Expected answer: 18
console.log(numberWeekDays(start, end));
// A Saturday
start = new Date("2020-01-05");
// A Monday
end = new Date("2020-01-31");
// Expected answer: 20
console.log(numberWeekDays(start, end));
// Weekday to weekday Tuesday to
start = new Date("2020-01-07");
end = new Date("2020-01-16");
// Expected: 8
console.log(numberWeekDays(start, end));
// Same week: Mon-Wed
start = new Date("2020-01-06");
end = new Date("2020-01-08");
// Expected answer: 3
console.log(numberWeekDays(start, end));
// Same day
start = new Date("2020-01-08");
end = new Date("2020-01-08");
// Expect: 1
console.log(numberWeekDays(start, end));
// Weekend only
start = new Date("2020-01-04");
end = new Date("2020-01-05");
// Expect: 0;
console.log(numberWeekDays(start, end));
// ------------------
}());
As others have stated, a date library like moment is useful here because it gives you a lot of utility functions for working with dates and durations.
Im building a mini calendar that just displays the current month, I have figured out how to map out the calendar, here is the code:
Code:
var month = moment(),
index = 0,
maxDay = month.daysInMonth(),
start = month.startOf("month"),
offset = (start.isoWeekday() - 1 + 7) % 7; // start from monday
var week = []; // holds the weeks
var days = []; // holds the days
do {
var dayIndex = index - offset;
if(dayIndex >= 0 && dayIndex < maxDay){
days.push({
number: dayIndex + 1,
isPast: null, // stuck here boolean
isToday: null // stuck here boolean
})
}
if(index % 7 === 6){
week.push(days);
console.log(week);
days = [];
if (dayIndex + 1 >= maxDay) {
break;
}
}
index += 1;
} while(true);
This works fine, the only issue Im having is to figure out if the day is today or its in the past?
the code is here also: https://jsfiddle.net/chghb3Lq/3/
Moment has isBefore, isAfter and isSame functions to compare moments and as the docs says:
If you want to limit the granularity to a unit other than milliseconds, pass the units as the second parameter.
There are a couple of things in your code that you can achieve in a simple way using momentjs instead of reimplementing by yourself:
To loop from the first day of the month until the last day you can use:
startOf('month') and endOf('month') as limit of the loop
add(1, 'day') to increment loop index
isBefore as loop condition
Use date() to get date of the month (1-31)
Use day() to get day of the week (0 => Sunday, ... 6 => Saturday); or weekday() to get day of the week locale aware.
Using these suggestions your code could be like the following:
var day = moment().startOf('month');
var endOfMonth = moment().endOf('month');
var week = [];
var month = [];
while( day.isBefore(endOfMonth) ){
week.push({
number: day.date(),
isPast: moment().isAfter(day, 'day'),
isToday: moment().isSame(day, 'day')
});
if( day.day() === 0 ){
month.push(week);
week = [];
}
day.add(1, 'day');
}
console.log(month);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
Use moment methods like isSame() , isBefore(), isSameOrBefore() etc.
They each allow setting comparison units like year month week day hour minute second
See Query Section of moment docs
given a date object,how to get previous week's first day
This Datejs library looks like it can do that sort of thing relatively easily.
Code:
function getPreviousSunday()
{
var today=new Date();
return new Date().setDate(today.getDate()-today.getDay()-7);
}
function getPreviousMonday()
{
var today=new Date();
if(today.getDay() != 0)
return new Date().setDate(today.getDate()-7-6);
else
return new Date().setDate(today.getDate()-today.getDay()-6);
}
Reasoning:
Depends what you mean by previous week's first day. I'll assume you mean previous sunday for the sake of this discussion.
To find the number of days to subtract:
Get the current day of the week.
If the current day of the week is Sunday you subtract 7 days
If the current day is Monday you subtract 8 days
...
If the current day is Saturday 13 days
The actual code once you determine the number of days to subtract is easy:
var previous_first_day_of_week=new Date().setDate(today.getDate()-X);
Where X is the above discussed value. This value is today.getDay() + 7
If by first day of the week you meant something else, you should be able to deduce the answer from the above steps.
Note: It is valid to pass negative values to the setDate function and it will work correctly.
For the code about Monday. You have that special case because getDay() orders Sunday before Monday. So we are basically replacing getDay() in that case with a value of getDay()'s saturday value + 1 to re-order sunday to the end of the week.
We use the value of 6 for subtraction with Monday because getDay() is returning 1 higher for each day than we want.
function previousWeekSunday(d) {
return new Date(d.getFullYear(), d.getMonth(), d.getDate() - d.getDay() - 7);
}
function previousWeekMonday(d) {
if(!d.getDay())
return new Date(d.getFullYear(), d.getMonth(), d.getDate() - 13);
return new Date(d.getFullYear(), d.getMonth(), d.getDate() - d.getDay() - 6);
}
I didn't quite understand other people's posts. Here is the javascript I use to display a Sun-Sat week relative to a given day. So, for instance, to get "last week," you're checking what the Sun/Sat goalposts were relative to seven days ago: new Date()-7
// variables
var comparedate = new Date()-7; // a week ago
var dayofweek = comparedate.getDay();
// just for declaration
var lastdate;
var firstadate;
// functions
function formatDate (dateinput) // makes date "mm/dd/yyyy" string
{
var month = dateinput.getMonth()+1;
if( month < 10 ) { month = '0' + month }
var date = dateinput.getDate();
if( date < 10 ) { var date = '0' + date }
var dateoutput = month + '/' + date + '/' + dateinput.getFullYear();
return dateoutput;
}
// Sunday to Saturday ... Sunday is the firstdate, Saturday is the lastdate
// (modify this block if you want something different eg: Monday to Sunday)
if ( dayofweek == 6 ) { lastdate = comparedate; firstdate = comparedate-6; } // Saturday
else if ( dayofweek == 0 ) { lastdate = comparedate+6; firstdate = comparedate; } // Sunday
else if ( dayofweek == 1 ) { lastdate = comparedate+5; firstdate = comparedate-1; } // Monday
else if ( dayofweek == 2 ) { lastdate = comparedate+4; firstdate = comparedate-2; } // Tuesday
else if ( dayofweek == 3 ) { lastdate = comparedate+3; firstdate = comparedate-3; } // Wednesday
else if ( dayofweek == 4 ) { lastdate = comparedate+2; firstdate = comparedate-4; } // Thursday
else if ( dayofweek == 5 ) { lastdate = comparedate+1; firstdate = comparedate-5; } // Friday
// Finish
var outputtowebpage = formatDate(firstdate) + ' - ' + formatDate(lastdate);
document.write(outputtowebpage);
I have to look this up every time I need to do it. So, I hope this is helpful to others.
First day of week can be either Sunday or Monday depending on what country you are in:
function getPrevSunday(a) {
return new Date(a.getTime() - ( (7+a.getDay())*24*60*60*1000 ));
};
function getPrevMonday(a) {
return new Date(a.getTime() - ( (6+(a.getDay()||7))*24*60*60*1000 ));
};
If you want to set a dateobject to the previous sunday you can use:
a.setDate(a.getDate()-7-a.getDay());
and for the previous monday:
a.setDate(a.getDate()-6-(a.getDay()||7));
In the other examples you will have a problem when sunday falls in other month. This should solve the problem:
var today, todayNumber, previousWeek, week, mondayNumber, monday;
today = new Date();
todayNumber = today.getDay();
previousWeek = -1; //For every week you want to go back the past fill in a lower number.
week = previousWeek * 7;
mondayNumber = 1 - todayNumber + week;
monday = new Date(today.getFullYear(), today.getMonth(), today.getDate()+mondayNumber);