JavaScript weekday list get - javascript

I need to create a JavaScript function for the below requirements. I need to get every week day date list. If you know nodeJs package tell me that. Thank you for your attention.
Example -
2022-01-03
2022-01-04
2022-01-05
2022-01-06
2022-01-07
2022-01-10
2022-01-11
2022-01-12
2022-01-13
2022-01-14
..........
..........
until year-end
like this pattern (only Monday to Friday)

function getWeekDaysForYear(year) {
const isLeap = year % 4 === 0;
const numberOfDays = isLeap ? 366 : 365;
let currentDate = new Date(Date.UTC(year, 0, 0, 0, 0, 0, 0));
const weekDays = [];
for(let i = 1; i <= numberOfDays; i++) {
currentDate = new Date(currentDate.getTime() + 24 * 3600 * 1000);
if (currentDate.getDay() === 0 || currentDate.getDay() === 6) {
continue;
}
weekDays.push(currentDate.toISOString().split('T')[0]);
}
return weekDays;
}
console.log(getWeekDaysForYear(2022));
This is a simple function which returns all the weekdays for the specified year in an array.

JavaScript's Date object overflows, so you can use:
for (i=1;i<366;i++) {
if (i%7==1 || i%7==2) continue;
const d = new Date(2022, 0, i);
document.write(d.toDateString(),'<br>');
}
You will need to watch for leap years, and recalculate which days are the weekend every year.

Something like this
const endDate = new Date(2022,1,2);
const date = new Date(); //today
while (endDate > date) {
const weekDay = date.getDay();
if (weekDay != 6 && weekDay != 0) {
let year = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date);
let month = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(date);
let day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date);
console.log(`${year}-${month}-${day}`);
}
date.setDate(date.getDate() + 1);
}

Since we're play code golf…
function getWeekDays(year) {
// Start on 1 Jan of given year
let d = new Date(Date.UTC(year, 0));
let result = [];
do {
// Only push dates that aren't Sat (6) or Sun (0)
d.getDay() % 6 ? result.push(d.toLocaleDateString('en-CA')) : null;
// Increment date
d.setDate(d.getDate() + 1);
// Until get to 1 Jan again
} while (d.getMonth() + d.getDate() > 1)
return result;
}
console.log(getWeekDays(new Date().getFullYear()))

function getWeekDaysForDateRange(start, end) {
const [startYear, startMonth, startDate] = start.split("-");
const [endYear, endMonth, endDate] = end.split("-");
let beginDate = new Date(Date.UTC(startYear, startMonth - 1, startDate - 1, 0, 0, 0, 0));
let closeDate = new Date(Date.UTC(endYear, endMonth - 1, endDate, 0, 0, 0, 0));
const weekDays = [];
while(beginDate.getTime() !== closeDate.getTime()) {
beginDate = new Date(beginDate.getTime() + 24 * 3600 * 1000);
if (beginDate.getDay() === 0 || beginDate.getDay() === 6) {
continue;
}
weekDays.push(beginDate.toISOString().split('T')[0]);
}
return weekDays;
}
console.log(getWeekDaysForDateRange('2022-01-01', '2022-01-10'));
Something like this would work for date range as you want!

Related

how to set the Date to the 1st Friday of the Current Year in javascript

I am trying to set the date to the 1st Friday of the Current Year in JavaScript.
var currentDate = new Date();
const firstMonth = "01"
var currentYear = currentDate.getFullYear();
var firstDay = new Date(currentYear, 0, 1);
var weekday = firstDay.getDay();
while (weekday != 5) {
if (weekday < 5) {
weekday = weekday + 1;
} else {
weekday = weekday - 1;
}
}
var friday = new Date(currentDate.setDate(firstDay.getDate() + 6)).toUTCString();
console.log(friday)
So first Friday of the current year can be in last year according to your code example? That would only work if you mean first Friday in the first week of the year
Here is first Friday of this year using your loop:
const currentDate = new Date();
const newYear = new Date(currentDate.getFullYear(), 0, 1, 15, 0, 0, 0); // make a date that is not near midnight anywhere
let day = newYear.getDay()
while (day != 5) {
console.log(newYear.toString())
newYear.setDate(newYear.getDate() + 1);
day = newYear.getDay();
}
console.log("Friday", newYear.toString())
var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var firstDay = new Date(currentYear, 0, 1);
var weekday = firstDay.getDay();
while(weekday != 5)
{
firstDay.setDate(firstDay.getDate()+1);
weekday = firstDay.getDay();
}

How to get all Saturdays in year with format as "Saturday, dd.MM.YYYY"?

I want to add all Saturdays of 2020/2021 into an object like following:
saturdays = {
"Saturday, 22.02.2020" : "Saturday, 22.02.2020" ,
"Saturday, 29.02.2020" : "Saturday, 29.02.2020"
}
1) First find out number of days in year (daysInYear method)
2) Find out first saturday date (firstSatDate method)
3) Go over for loop from first saturday to end of the year day and build the date string requirement format.
const daysInYear = year =>
(new Date(year + 1, 0, 1) - new Date(year, 0, 1)) / (24 * 60 * 60 * 1000);
const firstSatDate = year => {
const week_day = new Date(year, 0, 1).getDay();
const satDate = new Date(year, 0, 7 - week_day);
return satDate.getDate();
};
const getSaturdays = year => {
const yearDays = daysInYear(year);
const first = firstSatDate(year);
const saturdays = {};
for (let day = first; day <= yearDays; day = day + 7) {
const date = new Date(year, 0, day);
const day_str = String(date.getDate()).padStart(2, '0');
const month_str = String(date.getMonth() + 1).padStart(2, '0');
const date_str = `Saturday, ${day_str}.${month_str}.${date.getFullYear()}`;
saturdays[date_str] = date_str;
}
return saturdays;
};
console.log(getSaturdays(2020));
console.log(getSaturdays(2021));
It is an unusual format (name is the same as the value) and objects are not ordered so don't expect to get them back in any particular order . . . but it is pretty trivial to do if you want . . .
saturdays = {};
function loadSaturdays(startYear, endYear) {
const SATURDAY = 6;
let start = new Date("01/01/" + startYear);
let end = new Date("12/31/" + endYear);
var dateOptions = {weekday: 'long', year: 'numeric', month: 'numeric', day: 'numeric'};
var current = new Date(start);
while (current <= end) {
if (SATURDAY === current.getDay()) {
let newSaturday = "\"" + current.toLocaleString('en-GB', dateOptions).replace(/\//gi, '.') + "\"";
// if you want to see the individual ones as you are building the object
// console.log(newSaturday);
saturdays[newSaturday] = newSaturday;
}
current = new Date(current.setDate(current.getDate() + 1));
}
}
loadSaturdays("2020", "2021");
// if you want to see the entire object
//console.log(saturdays);
// objects are not ordered but they are all there
for (saturday in saturdays) {
console.log(saturday);
}

Get week range for given month and year in JavaScript

I need to display a range of dates in corresponding week for selected month. Suppose the selected values are month=3 (April) and year=2018. The output should show a list of ranged dates for weeks in that particular month selected.
month = 3;
year = 2018;
Output:
Week 1: 01/04/2018 - 01/04/2018
Week 2: 02/04/2018 - 08/04/2018
Week 3: 09/04/2018 - 15/04/2018
Week 4: 16/04/2018 - 22/04/2018
Week 5: 23/04/2018 - 29/04/2018
Week 6: 30/04/2018 - 30/04/2018
I tried this function but it doesn't work correctly. Can you help me ? thanks a lot.
public getWeeksInMonth(): {
let year: number = 2018;
let month: number = 3 //April;
const weeks = [];
const firstDay: Date = new Date(year, month, 1);
const lastDay: Date = new Date(year, month + 1, 0);
const daysInMonth: number = lastDay.getDate();
let dayOfWeek: number = firstDay.getDay();
let start: number;
let end: number;
for (let i = 1; i < daysInMonth + 1; i++) {
if (dayOfWeek === 0 || i === 1) {
start = i;
}
if (dayOfWeek === 6 || i === daysInMonth) {
end = i;
if ((start !== end) || (start === 30 && end === 30) || (start === 31 && end === 31)) {
weeks.push({
'start': start,
'end': end
});
}
}
dayOfWeek = new Date(year, month, i).getDay();
}
return weeks;
}
The first problem is that sunday gets 0 by .getDay() instead of monday.
Solved this issue checking for dayOfWeek === 1 instead of dayOfWeek === 0 and dayOfWeek === 0 instead of dayOfWeek === 6.
The second problem is your checking befor pushing a new week. You're checking for if start !== end but start could be equal to end
Solved this issue by setting start to null after pushing a new week and checking for start instead.
(Example below is written in JS, because TS is not runable at StackOverflow)
function getWeeksInMonth() {
let year = 2018;
let month = 3; //April;
const weeks = [];
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const daysInMonth = lastDay.getDate();
let dayOfWeek = firstDay.getDay();
let start;
let oldstart;
let end;
for (let i = 1; i < daysInMonth + 1; i++) {
if (dayOfWeek === 1 || i === 1) {
start = i;
}
if (dayOfWeek === 0 || i === daysInMonth) {
end = i;
if(start){
weeks.push({
'start': start,
'end': end
});
start = null;
}
}
dayOfWeek = new Date(year, month, i + 1).getDay();
}
return weeks;
}
console.log(getWeeksInMonth());
I have slightly refactored your solution and it seems to deliver expected result.
My code follows exactly the same (brute force) approach as yours:
make up an array (with Array.from()) of length equal to the number of days in a given month and fill it with the dates of each day of that month;
cycle through that array (with Array.prototype.reduce()) and throw into resulting array objects ({week,start,end}) that correspond to weeks, generating new objects as you hit Monday and closing the end date as you hit Sunday:
const getWeeksInMonth = (month, year) =>
Array
.from({length: (new Date(year, month+1, 0) - new Date(year, month, 0))/864E5},
(_,i) => new Date(year, month, i+1))
.reduce((res,date,idx,self) => {
const itsMonday = date.getDay() == 1,
itsSunday = date.getDay() == 0,
monthStart = idx == 0,
monthEnd = idx == self.length-1,
options = {dateStyle: 'short'};
if(itsMonday || monthStart)
res.push({
week:(res[res.length-1]||{week:0}).week+1,
start: date.toLocaleDateString('fr',options),
end: (monthStart ? date.toLocaleDateString('fr',options) : '')
});
if(itsSunday || monthEnd)
res[res.length-1].end = date.toLocaleDateString('fr',options);
return res;
}, []);
console.log(getWeeksInMonth(3,2018));
.as-console-wrapper {min-height:100%}
I found the solution.
Here the complete funtion working correctly:
public getWeeksInMonth(): Observable<Week[]> {
let year: number = 2018;
let month: number = 3;
const weeks: Week[] = [];
const firstDay: Date = new Date(Date.UTC(year, month, 1));
const lastDay: Date = new Date(Date.UTC(year, month + 1, 0));
const daysInMonth: number = lastDay.getDate();
let dayOfWeek: number = firstDay.getDay();
let start: number;
let end: number;
for (let i = 1; i < daysInMonth + 1; i++) {
if (dayOfWeek === 0 || i === 1) {
start = i;
}
if (dayOfWeek === 0 && start === 1 && i !== daysInMonth) {
end = 1;
weeks.push({
'start': start,
'end': end
});
}
if (dayOfWeek === 6 || i === daysInMonth) {
end = i;
if ((start !== end) || (start === 30 && end === 30) || (start === 31 && end === 31)) {
weeks.push({
'start': start,
'end': end
});
}
}
dayOfWeek = new Date(year, month, i).getDay();
}
return of(weeks);
}

How to return the next available date

I'm building a project with express and I have a scheduling calendar. I want to give to my users next available day. Format YYYY-MM-DD.
Rules:
The next available day is usually tomorrow unless:
- After 4pm the next available day is two days from now (i.e. Monday afternoon they can book Wednesday);
- Friday after 4pm the next available day is Monday;
- For Saturday it's Monday;
- For Sunday it's Tuesday;
I also have an array of public holidays, which are also unavailable. If the next day is a public holiday, the app should return the day after.
When there is a public holiday my app goes into a loop and it runs the whole loop. I don't know how to fix this. I thought it would skip the loop when it runs the second time.
const publicHolidays = ['2018-09-28', '2018-12-25']
const availableDay = (nextDay) => {
const d = new Date();
const utc = d.getTime() + (d.getTimezoneOffset() * 60000);
const nd = new Date(utc + (3600000 * 8));
if (nextDay === undefined) {
nextDay = 1;
}
if (nd.getDay() === 5 && nd.getHours() > 15) {
nextDay = 3;
} else if ([0, 6].includes(nd.getDay()) || nd.getHours() > 15) {
nextDay = 2;
}
const day = new Date();
const tomorrow = new Date(day);
tomorrow.setDate(tomorrow.getDate() + nextDay);
const yy = tomorrow.getFullYear();
let mm = tomorrow.getMonth() + 1;
if (mm < 10) {
mm = `0${mm}`;
}
let dd = tomorrow.getDate();
if (dd < 10) {
dd = `0${dd}`;
}
const available = `${yy}-${mm}-${dd}`;
if (publicHolidays.includes(available)) {
const nextDay = 7;
for (let i = 2; i < nextDay; i += 1) {
availableDay(i);
}
} else {
console.log('returning available', available);
return(available);
}
}
availableDay()
I think this logic will work - I've created a function to do the "date string - yyyy-mm-dd" thing because it's used in two places now
I also check for weekends by tomorrow.getDay() % 6 === 0 - you can of course use [0, 6].includes(tomorrow.getDay()) if you prefer
const publicHolidays = ['2018-09-28', '2018-12-25']
const availableDay = () => {
let nextDay = 1; // since we are not recursive any more
const d = new Date();
const utc = d.getTime() + (d.getTimezoneOffset() * 60000);
const nd = new Date(utc + (3600000 * 8));
if (nd.getDay() === 5 && nd.getHours() > 15) {
nextDay = 3;
} else if ([0, 6].includes(nd.getDay()) || nd.getHours() > 15) {
nextDay = 2;
}
const day = new Date();
const tomorrow = new Date(day);
tomorrow.setDate(tomorrow.getDate() + nextDay);
// changes start here
const dateString = d => `${.getFullYear()}-${('0' + (d.getMonth() + 1)).toString(-2)}-${('0' + d.getDate()).toString(-2)}`;
let available = dateString(tomorrow);
while (publicHolidays.includes(available) || (tomorrow.getDay() === 0)) {
tomorrow.setDate(tomorrow.getDate() + 1);
available = dateString(tomorrow);
}
console.log('returning available', available);
return(available);
}
availableDay()
There's probably more you can do to streamline the code - but this should fix the problem at least
I think you should always + 1 to nextDay. so if today is public holiday, try get the next day. the cycle repeat until it is not public holiday.
if (publicHolidays.includes(available)) {
availableDay(nextDay +1 );
} else {
console.log('returning available', available);
return(available);
}
Here is a more generic solution that might be applicable for people searching for something similar:
/**
* #summary Finds the next available date between a range, excluding a list of unavailable dates
* #param {Date} startDate The beginning of the date range.
* #param {Date} endDate The beginning of the date range.
* #param {Array of Date} excludeDates Dates that are not available.
*/
export const findNextAvailableDate = (startDate, endDate, excludeDates) => {
const excludeDatesStrArr = excludeDates.map(date => {
// Make sure dates are in a consistent string format so we can check for equality
excludeDate.setUTCHours(0, 0, 0, 0)
return excludeDate.toISOString()
})
let possibleDate = startDate
possibleDate.setUTCHours(0, 0, 0, 0)
let possibleDateStr = possibleDate.toISOString()
while (possibleDateStr !== endDate) {
if (!excludeDatesStrArr.includes(possibleDateStr)) {
// Date is not in exclude array, return available date
return possibleDate
} else {
// Date is included in exclude array, iterate to the next day
const newDate = possibleDate.setDate(possibleDate.getDate() + 1)
possibleDate = new Date(newDate)
possibleDate.setUTCHours(0, 0, 0, 0)
possibleDateStr = possibleDate.toISOString()
}
}
// Did not find next available date
return false
}

How can I use moment.js to add days, excluding weekends?

I'm setting a default follow-up date two days from current date, which currently works:
const Notify = moment().add(2, 'days').toDate();
However, I would like to exclude weekends. So I installed moment WeekDay, but I can't seem to get it to work with adding days to the current date. The documentation calls for:
moment().weekday(0)
But I can't get that to work with adding in two days forward. Any ideas?
This solution is simple, easy to follow, and works well for me:
function addBusinessDays(originalDate, numDaysToAdd) {
const Sunday = 0;
const Saturday = 6;
let daysRemaining = numDaysToAdd;
const newDate = originalDate.clone();
while (daysRemaining > 0) {
newDate.add(1, 'days');
if (newDate.day() !== Sunday && newDate.day() !== Saturday) {
daysRemaining--;
}
}
return newDate;
}
Try: moment-business-days
It should help you.
Example:
var momentBusinessDays = require("moment-business-days")
momentBusinessDays('20-09-2018', 'DD-MM-YYYY').businessAdd(3)._d
Result:
Tue Sep 25 2018 00:00:00 GMT+0530 (IST)
You could also not use external lib and do a simple function like one of these two:
const WEEKEND = [moment().day("Saturday").weekday(), moment().day("Sunday").weekday()]
const addBusinessDays1 = (date, daysToAdd) => {
var daysAdded = 0,
momentDate = moment(new Date(date));
while (daysAdded < daysToAdd) {
momentDate = momentDate.add(1, 'days');
if (!WEEKEND.includes(momentDate.weekday())) {
daysAdded++
}
}
return momentDate;
}
console.log(addBusinessDays1(new Date(), 7).format('MM/DD/YYYY'))
console.log(addBusinessDays1('09-20-2018', 3).format('MM/DD/YYYY'))
// This is the somewhat faster version
const addBusinessDays2 = (date, days) => {
var d = moment(new Date(date)).add(Math.floor(days / 5) * 7, 'd');
var remaining = days % 5;
while (remaining) {
d.add(1, 'd');
if (d.day() !== 0 && d.day() !== 6)
remaining--;
}
return d;
};
console.log(addBusinessDays2(new Date(), 7).format('MM/DD/YYYY'))
console.log(addBusinessDays2('09-20-2018', 3).format('MM/DD/YYYY'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
They are slightly modified from this post and I think are a good alternative to external library you have to carry/deal with (assuming this is the only part you need and not other features of that lib).
This will do it based on any starting date, and without a costly loop. You calculate the number of weekend days you need to skip over, then just offset by the number of weekdays and weekends, together.
function addWeekdays(year, month, day, numberOfWeekdays) {
var originalDate = year + '-' + month + '-' + day;
var futureDate = moment(originalDate);
var currentDayOfWeek = futureDate.day(); // 0 = Sunday, 1 = Monday, ..., 6 = Saturday
var numberOfWeekends = Math.floor((currentDayOfWeek + numberOfWeekdays - 1) / 5); // calculate the number of weekends to skip over
futureDate.add(numberOfWeekdays + numberOfWeekends * 2, 'days'); // account for the 2 days per weekend
return futureDate;
}
const addWorkingDays = (date: Moment, days: number) => {
let newDate = date.clone();
for (let i = 0; i < days; i++) {
if (newDate.isoWeekday() !== 6 && newDate.isoWeekday() !== 7) {
newDate = newDate.add(1, "days");
} else {
newDate = newDate.add(1, "days");
i--;
}
}
return newDate.format("YYYY/MM/DD");
};
var moment = require("moment")
function addWorkingDay(date, days){
let daysToAdd = days
const today = moment(date);
const nextWeekStart = today.clone().add(1, 'week').weekday(1);
const weekEnd = today.clone().weekday(5);
const daysTillWeekEnd = Math.max(0, weekEnd.diff(today, 'days'));
if(daysTillWeekEnd >= daysToAdd) return today.clone().add(daysToAdd, 'days');
daysToAdd = daysToAdd - daysTillWeekEnd - 1;
return nextWeekStart.add(Math.floor(daysToAdd/5), 'week').add(daysToAdd % 5, 'days')
}
I think this code will be faster:
var businessDays = 10;
var days = businessDays + Math.floor((Math.min(moment().day(),5)+businessDays)/6)*2;
moment.add(days, 'days');
// using pure JS
function addBusinessDays(originalDate, numDaysToAdd) {
const Sunday = 0;
const Saturday = 6;
let daysRemaining = numDaysToAdd;
const newDate = originalDate;
while (daysRemaining > 0) {
newDate.setDate(newDate.getDate() + 1);
if (newDate.getDay() !== 0 && newDate.getDay() !== 6) {
// skip sunday & saturday
daysRemaining--;
}
}
return newDate;
}
var dt = new Date(); // get date
var business_days = 8;
newDate = addBusinessDays(dt, business_days);
console.log(newDate.toString());

Categories

Resources