convert a week number and year to a date object in Javascript - 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())
);

Related

generate a specific number of dates from an array of days

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

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>

How to get the calendar week difference between two moments?

I want to get the calendar week difference between two dates in javascript.
Example:
a='09-May-2018'
b='14-May-2018'
Calendar week difference between these two is 2.
I started by converting date to moment and getting the difference in terms of weeks by Moment.js diff method. But that is considering 7 days as a weeks and giving me 1 for above example.
I thought of getting the week number of moment and then subtract it. But in that, if the date is of two different year. I will get wrong result. Like '01-Jan-2017' and '01-Jan-2018' will give week number as 1.
Is there any better way to do this efficiently?
You can also calculate week difference in plain javascript. Since you haven't fully explained the rules for how to determine the number of weeks I've made some guesses. The following:
Defaults the first day of the week as Monday
Copies the dates and moves them to the start of the week
Makes sure d0 is before d1
Calculates the number of weeks as 1 + (endDate - startDate) / 7
The day for the start of the week can be set using an optional 3rd parameter: 0 = Sunday, 1 = Monday, etc.
The result is always positive. If the dates are in the same week, the difference is 1.
This only works correctly if the end date is after the start date.
/* Calculate weeks between dates
** Difference is calculated by getting date for start of week,
** getting difference, dividing and rounding, then adding 1.
** #param {Date} d0 - date for start
** #param {Date} d1 - date for end
** #param {number} [startDay] - default is 1 (Monday)
** #returns {number} weeks between dates, always positive
*/
function weeksBetweenDates(d0, d1, startDay) {
// Default start day to 1 (Monday)
if (typeof startDay != 'number') startDay = 1;
// Copy dates so don't affect originals
d0 = new Date(d0);
d1 = new Date(d1);
// Set dates to the start of the week based on startDay
[d0, d1].forEach(d => d.setDate(d.getDate() + ((startDay - d.getDay() - 7) % 7)));
// If d1 is before d0, swap them
if (d1 < d0) {
var t = d1;
d1 = d0;
d0 = t;
}
return Math.round((d1 - d0)/6.048e8) + 1;
}
console.log(weeksBetweenDates(new Date(2018, 4, 9), new Date(2018, 4, 14)));
I had a requirement that, if difference is greater that 12 weeks I have to perform some action.
So I did it by getting week by week() method of Moment. Like this:
Math.abs(endDate.diff(startDate, 'days'))<91 &&
Math.abs(startDate.week() - endDate.week()) < 12)
Using moment.js, according to https://momentjs.com/docs/#/durations/diffing/
/**
* #param fromDate - moment date
* #param toDate - moment date
* #return {int} diffInWeeks Diff between dates with weeks as unit
**/
const getDiffInWeeks = (fromDate, toDate) => {
const requestedOffset = 1
const diff = toDate.diff(fromDate);
const diffInWeeks = moment.duration(diff).as('weeks')
return Math.ceil(diffInWeeks) + requestedOffset
}

Momentjs - Week Numbers When April Is Week One

Using this function in momentjs I can find the week number of the year:
var dt = new Date();
var weekNumber = moment(dt).week();
Can anyone tell me how to set the first week in April as week one, and therefore for week 52 to be the last week in March.
In the documentation I can only see how to adjust the first day of the year (ie Sunday or Monday). I need to do both. Saturday will actually be day one.
Help much appreciated.
You will have to add a custom function,
Sample
function getCustomWeekNumber(weekNo) {
var baseWeek = moment("01/04/", "DD/MM/").week() - 1; // 13
var lastWeek = moment("31/12/", "DD/MM/").week() //53;
return weekNo > baseWeek ? weekNo - baseWeek : (lastWeek - baseWeek) + weekNo;
}
var d = moment().week();
console.log(getCustomWeekNumber(d))
d = moment("01/04/2016", "DD/MM/YYYY").week();
console.log(getCustomWeekNumber(d))
d = moment("24/03/2016", "DD/MM/YYYY").week();
console.log(getCustomWeekNumber(d))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.0/moment.min.js"></script>

How to select first day and last day of the week when we select any date in dojox.calendar.?

I am using a custom dojox.calendar. currently if I select any date I am able to get the date. Now,How to select first day and last day of the week when we select any date in dojox.calendar.?
Here is a small function that, given a Date object and week day number, returns the previous day of the same week day number (Sunday = 0, Monday = 1, …, Saturday = 6).
function getPreviousDay(date, day) {
var d = new Date(+date);
d.setDate(d.getDate() - ((7 + d.getDay() - day) % 7));
return d;
}
console.log(getPreviousDay(new Date(2013,11,24), 2)); // Tue 17-Dec-2013
If the Date is a Tuesday and the week day number is 2, it will return a copy of the supplied Date. This can be used to build functions that, given a Date, return the previous Sunday and next Saturday:
// If date is Sunday, return a copy of date (default for getPreviousDay)
// Otherwise, get previous Sunday
function getPreviousSunday(date) {
var d = getPreviousDay(date, 0);
return d;
}
// If date is Saturday, return a copy of date
// Otherwise, get previous Saturday and add 7 days
function getNextSaturday(date) {
if (date.getDay() == 6) {
return new Date(+date);
}
var d = getPreviousDay(date, 6);
d.setDate(d.getDate() + 7);
return d;
}
var d = new Date(2013,11,21);
console.log(
d + '\n' +
getPreviousSunday(d) + '\n' +
getNextSaturday(d)
);
/*
Sat 21-Dec-2013
Sun 15-Dec-2013
Sat 21-Dec-2013
*/
Those values can then be used to select a date range in the calendar.
I use new Date(+date) to copy dates because otherwise in the years 0 to 99, IE will assume 1900 to 1999 and mess up the copy. While it's unlikely you'll want to use dates in this range (pretty pointless really) it makes me feel better knowing that it will "work" if you do.
IE does this because if a Date object is passed to the Date constructor, it is first converted to a string, then the string parsed to create a Date object. IE incorrectly parses its own string for years 0 to 99. Using + converts the date to a time value, which is treated correctly by the Date constructor everywhere (as far as I know).

Categories

Resources