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

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/

Related

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
}

Rounding date by multiple weeks

It is easy to round dates to the start of the current week like so:
function roundWeek() {
var current = new Date();
var startOfWeek = current.getDate() - current.getDay();
console.log(new Date(current.setDate(startOfWeek)));
}
roundWeek();
This works fine when rounding by one week, but it gets a bit more complex when rounding by multiple weeks.
For instance, say I would like to round in three-week periods. I know this would require an epoch (such as new Date(0)) to be able to properly calculate the starting date of the three-week period, but this too causes an issue:
January 1, 1970 (which is new Date(0)) occured on a Thursday, so assuming I used it in the following manner, it would always calculate the start of the week to be on a Thursday:
function roundWeek(weeks) {
var current = new Date();
const WEEK_IN_MS = 60*60*24*7*1000; //sec * min * hr * day * ms
var index = Math.floor( (current.getTime() / (WEEK_IN_MS*weeks)) );
var startOfPeriod = new Date( index * WEEK_IN_MS*weeks );
console.log( startOfPeriod );
}
roundWeek(3);
How can this be modified so that it properly starts on a Sunday instead of a Thursday? Is there a better way of doing this? And most importantly: Would a leap year cause issues with this?
You need to decide whether you want the three-week period to start the Sunday before Jan 1, 1970 (12/28/69) or after. For example, which Sunday would Jan 14, 1970 round to? Then you can calculate the difference between Thursday and either the previous Sunday or next Sunday and add or subtract (depending on the decision you made) that to your rounded solution.
Here's a variation of you function that also takes a date as input for testing.
function roundWeek(weeks, d) {
var current = new Date(d);
var first_sunday = 60 * 60 * 24 * 4 * 1000 // seconds between Sunday and Thursday
const WEEK_IN_MS = 60 * 60 * 24 * 7 * 1000; // week in ms
var index = Math.floor((current.getTime() / (WEEK_IN_MS * weeks)));
console.log(`${weeks}-week periods from ${d.getMonth()+1}/${d.getDate()}/${d.getFullYear()} ${index}`)
var startOfPeriod = new Date(index * WEEK_IN_MS * weeks - first_sunday);
console.log("1st day of period:", startOfPeriod);
}
// round to three weeks starting Sunday before Jan 1 1970
roundWeek(3, new Date('January 2, 1970')); // Dec 28, 1968
roundWeek(3, new Date('January 14, 1970')); // Dec 28, 1968
roundWeek(3, new Date('January 22, 1970')); // next three weeks
roundWeek(3, new Date('May 16, 2018')); // since today. Sundaay May 6
Since leap years don't change how long a week is, they should be irrelevant.

Javascript - unexpected behavior in dates calculations

I'm a newbie and recently started to read Beginning Javascript, by McPeak and Wilton. The authors propose an exercise about dates calculation. This is the exercise
Using the Date type, calculate the date 12 months from now.
I tried to solve it with this code
//gets today's date
var today = new Date();
//this line transforms the date in milliseconds
var daysAsMilliseconds = 1000* 60 * 60 * 24 * today.getDate();
//creates a new Date object
console.log(new Date(today.setDate(365) + daysAsMilliseconds));
The result I get here is correct(August 11th 2018).
Later, I wonder if it was really necessary to create 2 variables and tried this solution:
var today = new Date();
console.log(new Date(today.setDate(365) + (1000 * 60 * 60 * 24 * today.getDate())));
Here the solution was incorrect. The console showed August 31 2018. Why?
If necessary, here you will find the repl.it with the code
You call setDate, before you call getDate , therefore getDate will always return 365. Simply swapp it:
new Date((1000 * 60 * 60 * 24 * today.getDate()) + today.setDate(365))
Or its may easier to work with months directly:
today.setMonth(today.getMonth() + 12);
var intwelvemonths = today;
All you need to do is add 1 to the year:
var yearFromNow = new Date();
yearFromNow.setYear(yearFromNow.getFullYear() + 1);
Setting the date to 365 makes no sense; .setDate() is for day-of-month, so setting it to that constant moves the date a year (usually) from the last day of the previous month. And you don't need to do any other math outside of the date API; just increment the year, and you're done.
You're calling today.setDate(365) before you're adding the results of today.getDate(): today.getDate() will give the date that you set, not today's date.
Changing the order of operations will do the trick:
var today = new Date();
new Date((1000 * 60 * 60 * 24 * today.getDate()) + today.setDate(365));
I recommend you to use a package as moment.js because it manage a lot of date formats, and it has very good implementations for date managing.
Using moment js for add.
moment().add(Number, String);
Example
var m = moment(new Date(2011, 2, 12, 5, 0, 0));
m.hours(); // 5
m.add(1, 'days').hours(); // 5
For more docs see moment().add() docs

How to alert the starting and ending dates of previous week

How to Alert all the starting and ending dates of previous weeks.
var weekCount = 0;
$(".week-prev").live('click', function() {
var weekdate = new Date();
var fromweek = weekdate.setTime(weekdate.getTime() - 7 * 24 * 60 * 60 * 1000);
var toweek = weekdate.setTime(weekdate.getTime() - (weekdate.getDay() ? weekdate.getDay() : 7) + weekCount * 24 * 60 * 60 * 1000);
var prevweekstart = new Date(fromweek);
var prevweekends = new Date(toweek);
prevweekstart = prevweekstart.toLocaleString(),
prevweekends = prevweekends.toLocaleString(),
between = [];
alert(prevweekstart);
alert(prevweekends);
});
I would suggest to use moment.js for all date manipulations in Javascript
moment().startOf('week'); // set to the first day of this week, 12:00 am
moment().startOf('isoWeek'); // set to the first day of this week according to ISO 8601, 12:00 am
moment().endOf('week'); // set to the last day of this week, 12:00 am
moment().endOf('isoWeek'); // set to the last day of this week according to ISO 8601, 12:00 am
As of version 2.1.0, moment#startOf('week') uses the locale aware week start day.
For your example with the previous week you would use:
moment().subtract('weeks', 1).startOf('week');

Categories

Resources