How to get the calendar week difference between two moments? - javascript

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
}

Related

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())
);

Why does Javascript's Date.getDate() .setDate() behave so unpredictably?

Hobbyist coder here, and this problem is above my pay grade. I'm trying to build a dynamic html / css calendar, where the cells are filled in based on today's date. I get today's date, and then try to add days to fill in another 13 days (looping thru html elements.innerHTML).
If I try to setDate(30 + 2) and then getDate(). The code works fine. Javascript figures out that June ends at the 30th day, and the result is 2 as desired (July 2nd)
But this only works if there's only one call, if I have a loop, or call this code multiple times, then the result is different. Is there some async stuff gumming up the works? Here's code:
If you leave the "result2" call and comment the others, works great, but multiple calls, things break and numbers get repeated. Please help!
const theDate = new Date();
const todaysDate = 30;
theDate.setDate(todaysDate + 1);
let result1 = theDate.getDate();
theDate.setDate(todaysDate + 2);
let result2 = theDate.getDate();
theDate.setDate(todaysDate + 3);
let result3 = theDate.getDate();
theDate.setDate(todaysDate + 4);
let result4 = theDate.getDate();
console.log(result1);
console.log(result2);
console.log(result3);
console.log(result4);
June has 30 days but July has 31 days.
When you set the date to 32 for the first time, you are setting it to the 32nd of June and the dates after June 30 push it to July 2nd. (32-30=2)
When you set to 32 again, it is already July so the dates after July 31 push it to August 1st (32-31=1).
In answer to your question, the setDate() function is behaving so strangely for you because each time you are setting the date you are setting it relative to the previous setting, so incrementing each time by 31, 32, or 33 days instead of by 1, 2, or 3. See the brilliant answer by #Quentin for more information, this finding was entirely his and I just wanted to mention the root cause in my answer as well as my own fix to your problem.
An alternative solution if you just want to generate the dates:
const dayOfMonth = 30;
const date = new Date();
date.setDate(dayOfMonth);
console.log("Date:", date);
let timestamp = Date.parse(date);
for (let i = 1; i <= 14; i++) {
const newTimestamp = timestamp + i * (1000 * 60 * 60 * 24);
const newDate = new Date(newTimestamp);
console.log("New date:", newDate);
}
This method will manipulate the timestamp and generate new dates for each of the timestamps added to the number of milliseconds in a day.
You could use your date logic within the loop to populate the calendar as you mentioned.
If you use the Date() constructor on each iteration, you don't have to worry about the varying days of a particular month.
Details are commented in example
/**
* #desc - return a range of dates starting today (or a given
* date) and a given number of days (including start)
* #param {number} range - The number of days
* #param {string<date>} start - The date to start the range
* if not defined #default is today
* #return {array<date>} An array of dates
*/
function dayRange(range, start) {
// If undefined default is today
let now = start ? new Date(start) : new Date();
// Create an array of empty slots - .length === range
let rng = [...new Array(range)];
/*
.map() through array rng
If it's the first iteration add today's date...
... otherwise get tommorow's date...
and return it in local format
*/
return rng.map((_, i) => {
if (i === 0) {
return now.toLocaleDateString();
}
let day = now.getDate() + 1;
now.setDate(day);
return now.toLocaleDateString();
});
}
console.log("Pass the first parameter if the start day is today");
console.log(JSON.stringify(dayRange(14)));
console.log("Pass a properly formatted date string as the second parameter if you want to start on a date other than today");
console.log(JSON.stringify(dayRange(10, '05/12/2020')));

How to get the date of a specific day in javascript?

I have a diferent number of days
example (1=monday,2=tuesday.......)
and i need to return the date o this day in the current week
For example: if i send number 3 to my function, in this current week, today is sunday 23 , and i need that my function give me the date of the day 3 in this week, in this case the wednesday day was june-19 .
other example i pass the number 5 to my function the function return me the date of the day 5 this week (friday)= june-21 (2019/06/21)
something like that
let currentDate = new Date().toISOString().slice(0, 10)
The strategy is fairly straight forward:
new Date() gets you the current date
The getDay method returns the day number of the date's day of the week
The getDate method returns the day number of the date's day of the month
The setDate method sets the day number of the date's day of the month
So you get the current date, subtract the current day number, then add the day number you want to the date. This will also wrap to previous and following months, e.g.
/* Given a week day number, return the date for that
* day in the current week.
*
* #param {number} dayNumber - number of day in week.
* If 0, returns Sunday at start of week
* If 7, returns Sunday at end of week
* Otherwise 1 Mon, 2 Tue, etc.
* If not an integer in range 0 to 7 returns undefined
* #returns {number|undefined} date of supplied day number
*/
function getDateForDayInWeek(dayNumber) {
dayNumber = Number(dayNumber);
// Validate input
if (dayNumber < 0 ||
dayNumber > 7 ||
parseInt(dayNumber) != dayNumber) {
return; // undefined
}
let d = new Date();
d.setDate(d.getDate() - d.getDay() + dayNumber);
return d.getDate();
}
// Examples
console.log('Today is ' +
new Date().toLocaleString(undefined, {
month:'long', weekday:'long', day:'numeric'
})
);
// Sample values
[0, // Sunday at start of week
3, // Wednesday
7, // Sunday end of week
23, -2, 2.4 // All invalid, return undefined
].forEach(
n => console.log(n + ':' + getDateForDayInWeek(n))
);
You might want the function to return a Date, then you can do more with it, including just getting the date, but also the month and day name, etc.

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>

MooTools: Get the first and last days of a given week

I'm relatively inexperienced in JavaScript (we're using MooTools, here) and I'm stuck with a problem:
Is there a quick way to get the first and last dates of a given week?
e.g. week 17 / 2015 starts on Monday, April 20th and ends on Sunday, April 26th.
My goal is to find out if a given week starts and ends in the same month (week 18 wont, since it starts on April 27th and ends on May 3rd).
Many thanks on any help with examples or pointing me to the right documentation.
I've been looking for a while and haven't found anything like this, and I find MooTools documentation very poor...
Boa noite Filipe,
to do this you do not need MooTools. You can do with Vanilla JS.
Here is an idea:
function dayAnalizer(str) {
var date = new Date(str).getTime();
var weekAfter = date + 7 * 24 * 60 * 60 * 1000;
return new Date(date).getMonth() == new Date(weekAfter).getMonth();
}
console.log(dayAnalizer('10-05-2015')); // true
console.log(dayAnalizer('13-05-2015')); // false
console.log(dayAnalizer('16-05-2015')); // false
jsFiddle: http://jsfiddle.net/1g4bvgjg/
basically it gets a date in string format and converts it to timestamp (miliseconds), then create another date 1 week forward. In the end compare if both have same month.
If you need to know if a certain week in a year starts and ends in the same month you could use something like this:
function weekAnalyser(week, year) {
var days = (1 + (week - 1) * 7); // 1st of January + 7 days for each week
var date = new Date(year, 0, days);
var dayOfWeek = date.getDay(); // get week day
var firstDayOfWeek = date.getTime() - (dayOfWeek) * 60 * 60 * 24 * 1000); // rewind to 1st day of week
var endOfWeek = firstDayOfWeek + 6 * 24 * 60 * 60 * 1000;
return new Date(firstDayOfWeek).getMonth() == new Date(endOfWeek).getMonth();
}
jsFiddle: http://jsfiddle.net/zfassz29/
Ps. Welcome to Portuguese Stackoverflow: https://pt.stackoverflow.com/

Categories

Resources