generate a specific number of dates from an array of days - javascript

if I have an array of : ['Thursday', 'Friday']
and I want to generate 5 dates on the next dates of these days
for example, i want the result is the next Thursday is 14/7/2022, next Friday 15/7/2022
the output should be :
Thursday , Friday , Thursday , Friday , Thursday
=> output ['14/7/2022', '15/7/2022' , '21/7/2022' , '22/7/2022' , '28/7/2022']

If you can use libraries for that, then moment.js will help you a lot.
From that question we can create a solution for your case.
You can use moment.js to get a date from your string, and then using solution from question above get the date of that day of week on next week

This would be doable with two simple function in javascript
The first one would be to know the current date you are in ( & the day )
const d = new Date();
const day = d.getDay();
The getDay() method returns the day of the week (0 to 6) of a date.
Sunday = 0, Monday = 1, ... (See below):
More info here : https://www.w3schools.com/jsref/jsref_getday.asp.
Once you know the date, you would just need to convert your array from
['Thursday', 'Friday']
to [4,5]
Then you need to calculate the offset between the days
let offset = (targetDay - currentDayInNumber) % 7
if (offset < 0) { offset += 7 } // Want to make sure you offset is always positive
An example with tuesday = 2, thursday = 4, or monday = 1
let offset = (4 - 2) % 7 // ( 2 )
let offset = (1 - 2) % 7 // (-1)
offset = -1 + 7 // (6) we will be adding 6 days
Then you can simply loop and add days as you go
var date = new Date();
date.setDate(date.getDate() + days); // For tomorrow + 1 for example
Let me know if that helps, otherwise can provide you with the complete solution, but wanted to guide rather than give solution
-- Edit --
To complete this and to have the occurences, you could have a counter
const counterDays = {
0:0,
1:0,
..,
6:0
}
When going through the loop, everytime you setup a day, you increase the counter for it
This would be become something like this :
date.setDate(date.getDate() + offset + 7 * counterDays[targetDay]);
counterDays[targetDay]++;
I've provided you with the sample code here:
https://onecompiler.com/javascript/3y9sb8dqe
Hope this helps

Related

Weekly counter with text display

error message screenshotA screenshot of website interfaceMy day will be made more beautiful if I get some assistance. Using JavaScript or any other language is there a way I can develop a weekly counter that will display certain text per week, for instance, Week1 - Algeria, Week 2 - South Africa down to week 52 on a website I am developing
Still making research regarding this, no-coding trial yet
You can start by getting the number of a week and use that to index an array of "week names", or also use a time library to achieve the same goal. The following code uses the former:
/* For a given date, get the ISO week number */
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
// Get first day of year
const yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
// Calculate full weeks to nearest Thursday
const weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
// Return array of year and week number
return [d.getUTCFullYear(), weekNo];
}
const weekNames = ["Morocco", "South Africa", ...]
const currentWeek = getWeekNumber(new Date())
const formattedText = `Week${currentWeek}: ${weekNames[currentWeek]}`

convert a week number and year to a date object in Javascript

I am very new to web development and I am currently working on a dashboard my data comes from a MySql database. I would like to convert a week number and year to an actual date object in the frontend using javascript. This is my first try, which i stumbled while researching I believe that this function assumes the first day of the week of the current year is Monday(1):
function getDateOfWeek(w, y) {
var d = 1 + (w - 1) * 7;
return new Date(y, 0, d);
}
But the idea that the first day of the week is always Monday is desirable what if otherwise? So upon more research, I modified the code to look like this:
let currentDate = new Date()
let currentYear = currentDate.getFullYear()
let firstOfJan = new Date(currentYear, 0, 1).getDay();
function getDateOfWeek(w, y) {
var d = firstOfJan + (w - firstOfJan) * 7;
return new Date(y, 0, d);
}
Please I am not sure if this solves the problem 100 percent. Is there a downside to the function above? or does it cover it? or I am missing something? Thank you for your time
There are various schemes for calculating week number. ISO 8601 uses Monday before the first Thursday of the year as the start of the first week. So the last few days of a year may be in the first week of the following year, and the first few days may be in the last week of the previous year. There might be 52 or 53 weeks in a year. There are other schemes. Which one do you want to use?
The following converts an ISO week into a Date. It doesn't validate the input, so you'll need to add that.
// Convert week in format yyyyWww (e.g. 2022W05) to Date
function isoWeekToDate(isoWeek) {
let [y, w] = isoWeek.split(/w/i);
// Get date for 4th of January for year
let d = new Date(y, 0, 4);
// Get previous Monday, add 7 days for each week after first
d.setDate(d.getDate() - (d.getDay() || 7) + 1 + (w - 1) * 7);
return d;
}
// Tests
['2010W01',
'2011W01',
'2012W01',
'2013W01',
'2014W01',
'2015W01',
'2016W01',
'2017W01',
'2018W01',
'2019W01',
'2020W01'].forEach(s =>
console.log(isoWeekToDate(s).toDateString())
);

Get the current week using JavaScript without additional libraries ? [SO examples are broken]

I built a calendar control and was adding the week numbers as a final touch, and encountered a problem with every script example I could find on SO and outside of SO (most of which one has copied from the other).
The issue is that when dates fall in partial months, the week calculation seems to mess up and either continue counting when it is the same week in a new month, or it thinks the last full week in a previous month is the same week number as the first full new week in the following month.
Following is a visual demonstration of one of the libraries (they all have their inaccuracies as they generally base their week calculation off a fixed number and build from there) :
You can view the codepen here as the project is rather complex, I have the Date.prototype.getWeek function at the start to play with this easier. Feel free to swap in any code from the samples found here on SO as they all end up funking out on some months.
Some of the calculations used :
Show week number with Javascript?
Date get week number for custom week start day
w3resource.com ISO86901
epoch calendar - getting ISO week
Get week of year in JavaScript like in PHP
When running the most current example (2017) from "Get week of year in JavaScript like in PHP", the week returned right now is 42. When you look on my calendar, the week in October right now is showing as 42 which is correct according to here https://www.epochconverter.com/weeks/2018.
Given the example, there are full weeks sharing the same week number - so I don't see how 42 can even be accurate.
Date.prototype.getWeek = function (dowOffset) {
/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.epoch-calendar.com */
dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero
var newYear = new Date(this.getFullYear(),0,1);
var day = newYear.getDay() - dowOffset; //the day of week the year begins on
day = (day >= 0 ? day : day + 7);
var daynum = Math.floor((this.getTime() - newYear.getTime() -
(this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
var weeknum;
//if the year starts before the middle of a week
if(day < 4) {
weeknum = Math.floor((daynum+day-1)/7) + 1;
if(weeknum > 52) {
nYear = new Date(this.getFullYear() + 1,0,1);
nday = nYear.getDay() - dowOffset;
nday = nday >= 0 ? nday : nday + 7;
/*if the next year starts before the middle of
the week, it is week #1 of that year*/
weeknum = nday < 4 ? 1 : 53;
}
}
else {
weeknum = Math.floor((daynum+day-1)/7);
}
return weeknum;
};
Here is some code (also tried this) that is Sunday specific (see near the bottom). I am also pasting the relevant snip here :
/* For a given date, get the ISO week number
*
* Based on information at:
*
* http://www.merlyn.demon.co.uk/weekcalc.htm#WNR
*
* Algorithm is to find nearest thursday, it's year
* is the year of the week number. Then get weeks
* between that date and the first day of that year.
*
* Note that dates in one year can be weeks of previous
* or next year, overlap is up to 3 days.
*
* e.g. 2014/12/29 is Monday in week 1 of 2015
* 2012/1/1 is Sunday in week 52 of 2011
*/
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
// Get first day of year
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
// Return array of year and week number
return [d.getUTCFullYear(), weekNo];
}
The algorithm is to use the week number of the following Saturday. So get the following Saturday, then use it's year for the 1st of Jan. If it's not a Sunday, go to the previous Sunday. Then get the number of weeks from there. It might sound a bit convoluted, but it's only a few lines of code. Most of the following is helpers for playing.
Hopefully the comments are sufficient, getWeekNumber returns an array of [year, weekNumber]. Tested against the Mac OS X Calendar, which seems to use the same week numbering. Please test thoroughly, particularly around daylight saving change over.
/* Get week number in year based on:
* - week starts on Sunday
* - week number and year is that of the next Saturday,
* or current date if it's Saturday
* 1st week of 2011 starts on Sunday 26 December, 2010
* 1st week of 2017 starts on Sunday 1 January, 2017
*
* Calculations use UTC to avoid daylight saving issues.
*
* #param {Date} date - date to get week number of
* #returns {number[]} year and week number
*/
function getWeekNumber(date) {
// Copy date as UTC to avoid DST
var d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
// Shift to the following Saturday to get the year
d.setUTCDate(d.getUTCDate() + 6 - d.getUTCDay());
// Get the first day of the year
var yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
yearStart.setUTCDate(yearStart.getUTCDate() - yearStart.getUTCDay());
// Get difference between yearStart and d in milliseconds
// Reduce to whole weeks
return [d.getUTCFullYear(), (Math.ceil((d - yearStart) / 6.048e8))];
}
// Helper to format dates
function fDate(d) {
var opts = {weekday:'short',month:'short',day:'numeric',year:'numeric'};
return d.toLocaleString(undefined, opts);
}
// Parse yyyy-mm-dd as local
function pDate(s){
var b = (s+'').split(/\D/);
var d = new Date(b[0],b[1]-1,b[2]);
return d.getMonth() == b[1]-1? d : new Date(NaN);
}
// Handle button click
function doButtonClick(){
var d = pDate(document.getElementById('inp0').value);
var span = document.getElementById('weekNumber');
if (isNaN(d)) {
span.textContent = 'Invalid date';
} else {
let [y,w] = getWeekNumber(d);
span.textContent = `${fDate(d)} is in week ${w} of ${y}`;
}
}
Date:<input id="inp0" placeholder="yyyy-mm-dd">
<button type="button" onclick="doButtonClick()">Get week number</button><br>
<span id="weekNumber"></span>

Going through weeks is automatically changing on wednesday rather than sunday/monday

I'm looking for some help with my coursework as I've spent the last 8 hours trying to find a way to do what i'm trying to accomplish.
Now I have to use JavaScript, cannot use plugins but i can use the jQuery Library.
I'm basically trying to assign weeks to the semesters of the university year, so we say 29th September 2014 (Monday) to 26th January which is around 15 weeks.
Now I'm using something like this:
Date.prototype.getWeek = function() {
var firstJan = new Date(2014,0,1);
var today = new Date(2014, 9, 14);
var firstMonSem1 = new Date(2014, 8, 29);
var firstMonSem2 = new Date(this.getFullYear(), 1, 1);
var dayOfYear = ((today - firstJan + 86400000)/86400000);
var startWeekSem1 = ((firstMonSem1 - firstJan + 86400000)/86400000);
var startWeekSem2 = ((firstMonSem2 - firstJan + 86400000)/86400000);
var currentWeekNumber = Math.ceil(dayOfYear/7);
var startWeekNumberSem1 = Math.ceil(startWeekSem1/7);
var startWeekNumberSem2 = Math.ceil(startWeekSem2/7);
var output = {current: currentWeekNumber, sem1: startWeekNumberSem1, sem2: startWeekNumberSem2};
return output;
};
So i'm returning the current week of the year, semester start date for semester 1 and 2.
But for this example let's only focus on the first is 29th September (Monday) until 26th January which is around 15 weeks.
Now i've worked out based on the values i get when the semester starts and finishes including a 4 week holiday over the christmas period. And then I have an array for the index of which week of the semester we are in, in comparison to the week of the year (this way it could be week 41 in the year and based on the index array I would know that this is week 2).
Here's the code (note: it works!)
var today = new Date();
var info = today.getWeek();
if (info['current'] >= info['sem1'] && info['current'] <= (info['sem1'] + 18)) {
// Semester 1
var index = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var yearWeeks = [];
var count = 1;
for (var i = info['sem1']; i < (info['sem1'] + 18); i++) {
if (count !== 12 && count !== 13 && count !== 14) {
yearWeeks.push(i);
}
count++;
}
var rightIndex = $.inArray(info['current'], yearWeeks);
var x = 1;
while (x <= 15) {
if (x >= rightIndex) {
var weekOption = $("<option/>", {
"value" : x,
html : "Week "+x
}).appendTo(week);
}
x++;
}
}
So what I do here is append to a select all the weeks that are greater than the current week, so if we are in week 5 then there won't be a week 1,2,3,4 for the sake of this example (it's because in the project we are selecting a week to make a booking on but that's irrelevant).
Now, the problem.
This all works fantastically but there is a major catch, the week changes on Wednesday for example:
Week 1 is commencing 29th of September (Monday)
Week 2 starts 8th October (Wednesday)
Week 3 starts 15th October (Wednesday)
So every time the week changes on the Wednesday, now as the idea is that this system is being implemented so you can book room for that given week aka Monday - Friday, I need the weeks to update every Monday rather than Wednesday.
I really need help with this, and I know it might be a lot to grasp. However, I appreciate all the help I can get.
Thank you.
I think you need to replace this line:
var currentWeekNumber = Math.ceil(dayOfYear/7);
To be:
var currentWeekNumber = Math.ceil((dayOfYear + 5)/7);
To make a week start from Wednesday. In such case, the week of Day 2 (Tuesday) is Math.ceil((2+5)/7)=1, while Day 3 (Wednesday) is Math.ceil((3+5)/7)=2.
I worked it out some and hope it helps. This is not just for 2014 that you use, but for the current year. With some adaptation you can adjust.
You get the first of the year and get the offset of the day-number. Then you calculate the current day and subtract. The result will help you get the weeknr.
The week starts on Monday (where in other regions it may be on Sunday).
I created a fiddle, so you can play with it:
http://jsfiddle.net/djwave28/r0m4sokv/
This is an abstract from that fiddle:
// set an offset
var offset = 0;
var now = new Date();
var testday = new Date(now.getTime() + offset * 24 * 60 * 60 * 1000);
var firstofyear = new Date(testday.getFullYear(), 0, 1);
var firstdayoffset = firstofyear.getDay();
var daynr = Math.ceil((testday - firstofyear) / 86400000);
var weeknr = (daynr - firstdayoffset) / 7;

Moment.js how to get week of month? (google calendar style)

I am using Moment.js and it is great. The problem I have now is that I can't figure out how to get the week of the month a certain date is. I can only find "week of year" in the Moment js docs. For example, if I choose today's date (2/12/2014), I would like to know that this date is in the second week of this month of february and consequently, it is the second wednesday of the month. Any ideas?
EDIT:
I guess some clarification is necessary. What I need most is the nth number of a certain day in a month. For example, (from the comments) Feb 1, 2014 would be the first Saturday of the month. Feb 3, 2014 would be the first Monday of the month even though it is "technically" the second week of the month. Basically, exactly how google calendar's repeat function classifies days.
It seems that moment.js does not have the method that implements the functionality that you are looking for.
However, you can find the nth number of a certain day of the week in a month is using the Math.ceil of the date / 7
For example:
var firstFeb2014 = moment("2014-02-01"); //saturday
var day = firstFeb2014.day(); //6 = saturday
var nthOfMoth = Math.ceil(firstFeb2014.date() / 7); //1
var eightFeb2014 = moment("2014-02-08"); //saturday, the next one
console.log( Math.ceil(eightFeb2014.date() / 7) ); //prints 2, as expected
It looks like this is the number you are looking for, as demonstrated by the following test
function test(mJsDate){
var str = mJsDate.toLocaleString().substring(0, 3) +
" number " + Math.ceil(mJsDate.date() / 7) +
" of the month";
return str;
}
for(var i = 1; i <= 31; i++) {
var dayStr = "2014-01-"+ i;
console.log(dayStr + " " + test(moment(dayStr)) );
}
//examples from the console:
//2014-01-8 Wed number 2 of the month
//2014-01-13 Mon number 2 of the month
//2014-01-20 Mon number 3 of the month
//2014-01-27 Mon number 4 of the month
//2014-01-29 Wed number 5 of the month
When calculating the week of the month based on a given date, you have to take the offset into account. Not all months start on the first day of the week.
If you want to take this offset into account, you can use something something like the following if you are using moment.
function weekOfMonth (input = moment()) {
const firstDayOfMonth = input.clone().startOf('month');
const firstDayOfWeek = firstDayOfMonth.clone().startOf('week');
const offset = firstDayOfMonth.diff(firstDayOfWeek, 'days');
return Math.ceil((input.date() + offset) / 7);
}
Simple using moment.js
function week_of_month(date) {
prefixes = [1,2,3,4,5];
return prefixes[0 | moment(date).date() / 7]
}
This library adds the function moment.weekMonth()
https://github.com/c-trimm/moment-recur
I made some modifications based on feedback.
let weeks = moment().weeks() - moment().startOf('month').weeks() + 1;
weeks = (weeks + 52) % 52;
On days passing through the next year, the week value will be negative so I had to add 52.
What about something like:
weekOfCurrentMonth = (moment().week() - (moment().month()*4));
This takes the current week of the year, and subtracts it by the 4 times the number of previous months. Which should give you the week of the current month
I think the answer to this question will be helpful, even though it doesn't use moment.js as requested:
Get week of the month
function countWeekdayOccurrencesInMonth(date) {
var m = moment(date),
weekDay = m.day(),
yearDay = m.dayOfYear(),
count = 0;
m.startOf('month');
while (m.dayOfYear() <= yearDay) {
if (m.day() == weekDay) {
count++;
}
m.add('days', 1);
}
return count;
}
There is a problem with #Daniel Earwicker answer.
I was using his function in my application and the while loop was infinite because of the following situation:
I was trying to figure out which week of december (2016) was the day 31.
the first day of december was day 336 of the year. The last day of december was day 366 of the year.
Problem here: When it was day 366 (31 of december, last day of the year) the code added another day to this date. But with another day added it would be day 1 of january of 2017. Therefore the loop never ended.
while (m.dayOfYear() <= yearDay) {
if (m.day() == weekDay) {
count++;
}
m.add('days', 1);
}
I added the following lines to the code so the problem would be fixed:
function countWeekdayOccurrencesInMonth(date) {
var m = moment(date),
weekDay = m.day(),
yearDay = m.dayOfYear(),
year = m.year(),
count = 0;
m.startOf('month');
while (m.dayOfYear() <= yearDay && m.year() == year) {
if (m.day() == weekDay) {
count++;
}
m.add('days', 1);
}
return count;
}
It verifies if it is still in the same year of the date being veryfied
Here's Robin Malfait's solution implemented with the lightweight library date-fns
import {
differenceInDays,
startOfMonth,
startOfWeek,
getDate
} from 'date-fns'
const weekOfMonth = function (date) {
const firstDayOfMonth = startOfMonth(date)
const firstDayOfWeek = startOfWeek(firstDayOfMonth)
const offset = differenceInDays(firstDayOfMonth, firstDayOfWeek)
return Math.ceil((getDate(date) + offset) / 7)
}
export default weekOfMonth
I'd do the following:
let todaysDate = moment(moment.now());
let endOfLastMonth = moment(get(this, 'todaysDate')).startOf('month').subtract(1, 'week');
let weekOfMonth = todaysDate.diff(endOfLastMonth, 'weeks');
That gets todaysDate and the endOfLastMonth and then uses Moment's built-in diff() method to compute the current month's week number.
It's not built-in, but basically you can subtract the week number of the start of the month from the week number of the date in question.
function weekOfMonth(m) {
return m.week() - moment(m).startOf('month').week() + 1;
}
Credit goes to code by original author, give him a star if it helped you.
How about this?
const moment = require("moment");
// Generate Week Number of The Month From Moment Date
function getWeekOfMonth(input = moment()) {
let dayOfInput = input.clone().day(); // Saunday is 0 and Saturday is 6
let diffToNextWeek = 7 - dayOfInput;
let nextWeekStartDate = input.date() + diffToNextWeek;
return Math.ceil((nextWeekStartDate) / 7);
}
Simple code, but has been working for me.
const weekOfTheMonth = (myMomentDate) => {
const startDay = moment(myMomentDate).startOf('week');
const day = parseInt(startDay.format('DD'),10);
if(day > 28){
return 5;
}
if((day > 21) && (day <= 28) ){
return 4;
}
if((day > 14) && (day <= 21) ){
return 3;
}
if((day > 7) && (day <= 14) ){
return 2;
}
return 1;
}

Categories

Resources