How do I convert this date from momentjs to plain JavaScript - javascript

I have a timestamp that I am trying to roundto the nearest UTC Monday 00:00:00:00:000Z
My code in moment looks like this
let now = Date.now()
moment.unix(now / 1000).utc().startOf("isoWeek").valueOf()
I am trying to do this in plain JS without moment and I am not getting the same answer
const nearestMonday = date => {
const monday = 1;
const currentDay = date.getDay();
const distance = (monday + 7 - currentDay) % 7;
const newDate = new Date(date.getTime());
newDate.setDate(date.getDate() + distance);
newDate.setHours(0, 0, 0, 0);
return newDate;
}
> d = Date.now()
1545989455067
> nearestMonday(new Date(d)).getTime()
1546194600000
> m.unix(Date.now() / 1000).utc().startOf("isoWeek").valueOf()
1545609600000
I am in GMT + 530 zone , what do I change to get the same answer as moment

Ok, so we have a few problems here:
First: Timezones
Date works with your local timezone, so when you do newDate.setHours(0, 0, 0, 0); and stuff like that, it sets the object to that hours in your timezone. When you do .getTime(), however, it does return millis from epoch in UTC.
The result of this being: if you are in gmt+530 (India, I believe) when you do a .getTime() the millis from epoch will be off by that difference (5h 30m).
To compensate that, you can use getTimezoneOffset():
const nearestMonday = date => {
const monday = 1;
const currentDay = date.getDay();
const distance = (monday + 7 - currentDay) % 7;
const newDate = new Date(date.getTime());
newDate.setDate(date.getDate() + distance);
newDate.setHours(0, 0, 0, 0);
newDate.setTime(newDate.getTime()-1000*60*newDate.getTimezoneOffset());
return newDate;
}
On the other hand, your code using moment will work properly with timezones, so there's no need to change it.
Second: What monday?
Your function nearestMonday calculates the next Monday.
The function startOf('isoWeek') sets the date to the Monday of the current week.
If you want both to calculate the current, you should modify your nearestMonday like:
const nearestMonday = date => {
const monday = 1;
const currentDay = date.getDay();
const distance = monday - currentDay;
console.log('dist', distance);
const newDate = new Date(date.getTime());
newDate.setDate(date.getDate() + distance);
newDate.setHours(0, 0, 0, 0);
newDate.setTime(newDate.getTime()-1000*60*newDate.getTimezoneOffset());
return newDate;
}
Last: Sundays?
getDay() on Sunday will return a 0. Therefore, the "nearestMonday" will be the day after that. I haven't corrected it since I don't know if that's the desired behaviour, but noting it just for completion sake

I think this may do what you want:
const nearestMonday = date => {
const day = 1000*60*60*24;
const week = day*7;
return new Date(Math.floor(date.getTime()/week)*week-3*day);
}

Related

Display year to date

I am trying to display data for a "Year to Date" range. I need it to show all the dates ranging from the first day of January 2021 until the current date (whatever day today is).
I previously had the data showing only the previous 30 days and had:
const today = new Date();
const startDate =
this.startDate || new Date(today.getFullYear(), today.getMonth(), today.getDate() - 30);
const endDate = this.endDate || today;
How can I get the data to show from January 1st, 2021 to whatever the current day is?
Here is how to create an array dateArray of all dates between the first of this year and today:
Date.prototype.addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
const today = new Date()
const startDate = new Date(today.getFullYear(), 0, 1);
var dateArray = new Array();
var currentDate = startDate;
while (currentDate <= today) {
dateArray.push(new Date(currentDate));
currentDate = currentDate.addDays(1);
}
console.log(dateArray)
This will work for every current year
const aDay = 24*60*60*1000;
const end = new Date()
// normalise - otherwise I would see last day of previous year until yesterday due to timezones
end.setHours(15,0,0,0);
const start = new Date(end.getFullYear(),0,0,15,0,0,0); // 31/12/previous year to get date 0
const days = (end.getTime()-start.getTime())/aDay
let t = start.getTime();
const dates = [...Array(days)] // create an array of days
.map(() => new Date(t+=aDay).toISOString().split('T')[0])
console.log(dates)
Using while
const aDay = 24*60*60*1000;
const end = new Date()
// normalise - otherwise I would see last day of previous year until yesterday due to timezones
end.setHours(15,0,0,0);
const start = new Date(end.getFullYear(),0,0,15,0,0,0); // 31/12/previous year to get date 0
const days = (end.getTime()-start.getTime())/aDay
let t = start.getTime();
const endTime = end.getTime();
const dates = [];
while (t<endTime) {
dates.push(new Date(t+=aDay).toISOString().split('T')[0])
}
console.log(dates)
As others have answered, just "better" — IMHO of course. :-)
// Default end is current date
function getDateRange(startDate, endDate = new Date()) {
// Default start to 1 Jan of endDate year
if (!startDate) {
startDate = new Date(endDate.getFullYear(), 0);
// Otherwise copy startDate so don't affect original
} else {
startDate = new Date(+startDate);
}
let result = [];
// Push timestamps into an array until endDate
while (startDate <= endDate) {
// Push date in YYYY-MM-DD format into result array
result.push(startDate.toLocaleDateString('en-CA'));
// Increment startDate
startDate.setDate(startDate.getDate() + 1);
}
return result;
}
// Dates from 1 Jan to today
console.log(getDateRange());

MomentJS getting previous dates relative to today

Is there anyway to get the days past the current day using MomentJS?
For example suppose it is January 5, 2018, how would I get the previous dates from January 1, 2018 through to January 5, 2018 ?
My current code looks like this:
const monthArr = [];
const dayArr= [];
const currentDate = moment(new Date()).format("DD");
for (let i = 0; i < +currentDate; i++) {
const month = moment(new Date())
.subtract(i, "day")
.format("MMYYYY");
const day = moment(new Date())
.subtract(i, "day")
.format("MMDDYYYY");
console.log("month" + month);
console.log("day" + day);
let monthObj = {};
let dailyObj = {};
monthArr.push(
(monthObj = {
data: {
[month]: Object.assign({}, document)
}
})
);
day.push(
(dailyObj = {
data: {
[day]: Object.assign({}, document)
}
})
);
monthly(user_id, monthArr[i]) &&
daily(user_id, dayArr[i]);
}
The code in the OP seems very inefficient and far more complex than required.
To generate a series of formatted strings for dates from today to the start of the month only needs one Date and some very simple arithmetic and formatting. It really doesn't need a library nor any date arithmetic, e.g.
// Pad single digit number with leading zero
function pad(n){
return (n < 10? '0' : '') + n;
}
var today = new Date(),
year = today.getFullYear(),
month = pad(today.getMonth() + 1),
day,
i = today.getDate();
do {
day = pad(i);
console.log(`Month: ${month + year}`);
console.log(`Day: ${month + day + year}`);
} while (--i)
There are a number of other issues with your code, but they're not directly related to the question.

Generate the start and end ranges for a specific JavaScript Date and identifier (month, day, year, week)?

Is there a way to intelligently find the beginning and end times of a specific Date object in JavaScript for a certain time window (month, day, year, week)?
I'd like to be able to give it any date, then an identifier (like month, week, day, or year), then a boolean for whether or not it should use UTC time. It should return a JavaScript object with two keys (startTime, endTime) where the values for these keys are the epoch milliseconds (or date objects) representing my range.
I began writing a function to do this (see below), just wondering if there is a smarter way to go about doing it:
/**
* #param rangeValue; String ('year', 'month', 'week', 'day')
* #param dateTime; JavaScript Date Object.
* #param useUTC; Boolean. Determines whether or not UTC is to be used or default browser time
* #returns {{}}; startTime and endTime, in epoch milliseconds
*/
function generateTimeRange(rangeValue, dateTime, useUTC) {
var dateRange = {};
var year = dateTime.getUTCFullYear();
var month = dateTime.getUTCMonth();
var dayOfWeek = dateTime.getUTCDay();
var day = dateTime.getUTCDate();
if (!useUTC) {
year = dateTime.getFullYear();
month = dateTime.getMonth();
dayOfWeek = dateTime.getDay();
day = dateTime.getDate();
}
if (rangeValue === 'year') {
dateRange.startTime = new Date(year, 0, 0, 0, 0, 0, 0).getTime();
dateRange.endTime = new Date(year + 1, 0, 0, 0, 0, 0, 0).getTime() - 1;
} else if (rangeValue === 'month') {
dateRange.startTime = new Date(year, month, 0, 0, 0, 0, 0).getTime();
month += 1;
if (month > 11)
year += 1;
dateRange.endTime = new Date(year + 1, month % 12, 0, 0, 0, 0, 0).getTime() - 1;
} else if (rangeValue === 'week') {
// Do week calculation
} else if (rangeValue === 'day' {
// Do day calculation
}
return dateRange;
}
EDIT: Just discovered that Moment.js has startOf and endOf methods. Is there an elegant way to do this without external libraries?
This is probably more suitable in a code review forum.
It doesn't seem sensible to get all the UTC parts, then see if you need them and get local parts if not. Just get the ones you want. And since UTC should be used everywhere if required, then:
var UTC = useUTC? 'UTC' : '';
Now you just do:
var year = dateTime.['get' + UTC + 'FullYear']();
var month = dateTime.['get' + UTC + 'Month']();
and so on. But there's no need to do those unless you must. Then there's:
if (rangeValue === 'year') {
that is pretty strict, you might want it case–insensitive so:
if (/^year$/i.test(rangeValue))
then
dateRange.startTime = new Date(year, 0, 0, 0, 0, 0, 0).getTime();
will get 31 December of the previous year since you've set the date to 0. It will also be 00:00:00 for the host system timezone, not UTC (if it was specified). If you only provide the year and month, all the other values are zero (except for date, it's 1) by default, and you want to use UTC if specified so:
dateRange.startTime = (UTC? new Date(Date.UTC(year,0)) : new Date(year,0)).getTime();
Similarly for end time:
dateRange.endTime = (UTC? new Date(Date.UTC(+year+1,0)) : new Date(+year+1,0)).getTime() - 1;
You actually don't need getTime since the subtraction will coerce the value to a number anyway, but it keeps things consistent. To do month is similar:
// Get the month
var month = dateTime['get' + UTC + 'Month']();
// If month range is required
if (/^month$/i.test(rangeValue)) {
// Get the start of the month
var monthStart = UTC? new Date(Date.UTC(year,month)) : new Date(year,month);
// Assign the time value
dateRange.startTime = monthStart.getTime();
// Adjust to end of month.
// The setTime method returns the time value, so no need for getTime
dateRange.endTime = monthStart['set' + UTC + 'Month'](monthStart['get' + UTC + 'Month']() + 1, 1) - 1;
return dateRange;
}
So putting that part together:
function generateTimeRange(rangeValue, dateTime, useUTC) {
var dateRange = {};
var UTC = useUTC? 'UTC' : '';
var year = dateTime['get' + UTC + 'FullYear']();
if (/^year$/i.test(rangeValue)) {
dateRange.startTime = (UTC? new Date(Date.UTC(year,0)) : new Date(year,0)).getTime();
dateRange.endTime = (UTC? new Date(Date.UTC(year+1,0)) : new Date(year+1,0)).getTime() - 1;
return dateRange;
}
var month = dateTime['get' + UTC + 'Month']();
if (/^month$/i.test(rangeValue)) {
var monthStart = UTC? new Date(Date.UTC(year,month)) : new Date(year,month);
dateRange.startTime = monthStart.getTime();
// The setMonth method returns the time value, so no need for getTime
dateRange.endTime = monthStart['set' + UTC + 'Month'](monthStart['get' + UTC + 'Month']() + 1, 1) - 1;
return dateRange;
}
// Add week, day, etc.
}
var dr = generateTimeRange('year', new Date(), false);
console.log('Start: ' + new Date(dr.startTime) + '\nEnd: ' + new Date(dr.endTime));
dr = generateTimeRange('month', new Date(), false);
console.log('Start: ' + new Date(dr.startTime) + '\nEnd: ' + new Date(dr.endTime));
// UTC tests, note if west of GMT will seem to be one day early:
dr = generateTimeRange('year', new Date(), true);
console.log('Start: ' + new Date(dr.startTime) + '\nEnd: ' + new Date(dr.endTime));
dr = generateTimeRange('month', new Date(), true);
console.log('Start: ' + new Date(dr.startTime) + '\nEnd: ' + new Date(dr.endTime));

How to check if date is in this week in javascript?

I have this date "2016-04-23T11:45:00Z" and I want to check this date in this week or not ?
Thanks,
Dates are hard, I would always suggest using a library dedicated to date handling as it reduces the chances of errors in your code.
MomentJS is a good one.
var now = moment();
var input = moment("2016-04-17T11:45:00Z");
var isThisWeek = (now.isoWeek() == input.isoWeek())
Edit: Please note as of 2020 moment may not be a good choice for new projects
This seems to be working for me.
function isDateInThisWeek(date) {
const todayObj = new Date();
const todayDate = todayObj.getDate();
const todayDay = todayObj.getDay();
// get first date of week
const firstDayOfWeek = new Date(todayObj.setDate(todayDate - todayDay));
// get last date of week
const lastDayOfWeek = new Date(firstDayOfWeek);
lastDayOfWeek.setDate(lastDayOfWeek.getDate() + 6);
// if date is equal or within the first and last dates of the week
return date >= firstDayOfWeek && date <= lastDayOfWeek;
}
const date = new Date();
const isInWeek = isDateInThisWeek(date);
<div ng-app="myApp">
<div class="container" ng-controller="Ctrl_List">
<h1>{{currentDate}}</h1>
<h1>{{numberCurrentDateWeeks}}</h1>
<h1>{{yourDate}}</h1>
<h1>{{numberYourDateWeeks}}</h1>
</div>
</div>
......
angular.module('myApp', [])
.controller("Ctrl_List", ["$scope", "$filter", function(s, $filter) {
s.yourDate = '2016-04-23T11:45:00Z'
s.currentDate = new Date();
s.numberCurrentDateWeeks = $filter('date')(s.currentDate, "w");
s.numberYourDateWeeks = $filter('date')(s.yourDate, "w");
}]);
then you got the Week numbers just compare or do whatever you like
cheers !
You can do that without any libraries by checking if the date.getTime() (milliseconds since epoch) is between last monday and next monday:
const WEEK_LENGTH = 604800000;
function onCurrentWeek(date) {
var lastMonday = new Date(); // Creating new date object for today
lastMonday.setDate(lastMonday.getDate() - (lastMonday.getDay()-1)); // Setting date to last monday
lastMonday.setHours(0,0,0,0); // Setting Hour to 00:00:00:00
const res = lastMonday.getTime() <= date.getTime() &&
date.getTime() < ( lastMonday.getTime() + WEEK_LENGTH);
return res; // true / false
}
(one week in ms = 24 * 60 * 60 * 1000 * 7 = 604,800,000)
May not be the most optimal solution, but I think it's quite readable:
function isThisWeek (date) {
const now = new Date();
const weekDay = (now.getDay() + 6) % 7; // Make sure Sunday is 6, not 0
const monthDay = now.getDate();
const mondayThisWeek = monthDay - weekDay;
const startOfThisWeek = new Date(+now);
startOfThisWeek.setDate(mondayThisWeek);
startOfThisWeek.setHours(0, 0, 0, 0);
const startOfNextWeek = new Date(+startOfThisWeek);
startOfNextWeek.setDate(mondayThisWeek + 7);
return date >= startOfThisWeek && date < startOfNextWeek;
}
This link explaines, how to do this without using any js libraries. https://gist.github.com/dblock/1081513
Code against link death:
function( d ) {
// Create a copy of this date object
var target = new Date(d.valueOf());
// ISO week date weeks start on monday
// so correct the day number
var dayNr = (d.getDay() + 6) % 7;
// Set the target to the thursday of this week so the
// target date is in the right year
target.setDate(target.getDate() - dayNr + 3);
// ISO 8601 states that week 1 is the week
// with january 4th in it
var jan4 = new Date(target.getFullYear(), 0, 4);
// Number of days between target date and january 4th
var dayDiff = (target - jan4) / 86400000;
// Calculate week number: Week 1 (january 4th) plus the
// number of weeks between target date and january 4th
var weekNr = 1 + Math.ceil(dayDiff / 7);
return weekNr;
}
I managed to do it with this simple trick and without any external library.
Considering monday as the first day of the week, the function takes as parameter a date string and do the validation before checking if the day indeed is in the current week.
function isInThisWeek(livr){
const WEEK = new Date()
// convert delivery date to Date instance
const DATEREF = new Date(livr)
// Check if date instance is in valid format (depends on the function arg)
if(DATEREF instanceof Date && isNaN(DATEREF)){
console.log("invalid date format")
return false}
// Deconstruct to get separated date infos
const [dayR, monthR, yearR] = [DATEREF.getDate(), DATEREF.getMonth(), DATEREF.getFullYear()]
// get Monday date
const monday = (WEEK.getDate() - WEEK.getDay()) + 1
// get Saturday date
const sunday = monday + 6
// Start verification
if (yearR !== WEEK.getFullYear()) { console.log("WRONG YEAR"); return false }
if (monthR !== WEEK.getMonth()) { console.log("WRONG MONTH"); return false }
if(dayR >= monday && dayR <= sunday) { return true }
else {console.log("WRONG DAY"); return false}
}
In the comments I saw that you stated that your week starts on Monday.
In that case, I guess it'd be a good idea to calculate the ISO week number of the 2 dates and see if you get the same week number for both of them.
To calculate the ISO week number, check this answer:
In case anyone else's week starts on Sunday instead, you can use this answer to calculate the week number accordingly.
then you can do something like this:
function isSameWeek(date1, date2) {
return date1.getWeekNumber() === date2.getWeekNumber();
}
const isDateInThisWeek = (date) => {
const today = new Date();
//Get the first day of the current week (Sunday)
const firstDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay())
);
//Get the last day of the current week (Saturday)
const lastDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay() + 6)
);
//check if my value is between a minimum date and a maximum date
if (date >= firstDayOfWeek && date <= lastDayOfWeek) {
return true;
} else {
return false;
}
};

JavaScript - get the first day of the week from current date

I need the fastest way to get the first day of the week. For example: today is the 11th of November, and a Thursday; and I want the first day of this week, which is the 8th of November, and a Monday. I need the fastest method for MongoDB map function, any ideas?
Using the getDay method of Date objects, you can know the number of day of the week (being 0=Sunday, 1=Monday, etc).
You can then subtract that number of days plus one, for example:
function getMonday(d) {
d = new Date(d);
var day = d.getDay(),
diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday
return new Date(d.setDate(diff));
}
getMonday(new Date()); // Mon Nov 08 2010
Not sure how it compares for performance, but this works.
var today = new Date();
var day = today.getDay() || 7; // Get current day number, converting Sun. to 7
if( day !== 1 ) // Only manipulate the date if it isn't Mon.
today.setHours(-24 * (day - 1)); // Set the hours to day number minus 1
// multiplied by negative 24
alert(today); // will be Monday
Or as a function:
# modifies _date_
function setToMonday( date ) {
var day = date.getDay() || 7;
if( day !== 1 )
date.setHours(-24 * (day - 1));
return date;
}
setToMonday(new Date());
CMS's answer is correct but assumes that Monday is the first day of the week.
Chandler Zwolle's answer is correct but fiddles with the Date prototype.
Other answers that add/subtract hours/minutes/seconds/milliseconds are wrong because not all days have 24 hours.
The function below is correct and takes a date as first parameter and the desired first day of the week as second parameter (0 for Sunday, 1 for Monday, etc.). Note: the hour, minutes and seconds are set to 0 to have the beginning of the day.
function firstDayOfWeek(dateObject, firstDayOfWeekIndex) {
const dayOfWeek = dateObject.getDay(),
firstDayOfWeek = new Date(dateObject),
diff = dayOfWeek >= firstDayOfWeekIndex ?
dayOfWeek - firstDayOfWeekIndex :
6 - dayOfWeek
firstDayOfWeek.setDate(dateObject.getDate() - diff)
firstDayOfWeek.setHours(0,0,0,0)
return firstDayOfWeek
}
// August 18th was a Saturday
let lastMonday = firstDayOfWeek(new Date('August 18, 2018 03:24:00'), 1)
// outputs something like "Mon Aug 13 2018 00:00:00 GMT+0200"
// (may vary according to your time zone)
document.write(lastMonday)
First / Last Day of The Week
To get the upcoming first day of the week, you can use something like so:
function getUpcomingSunday() {
const date = new Date();
const today = date.getDate();
const currentDay = date.getDay();
const newDate = date.setDate(today - currentDay + 7);
return new Date(newDate);
}
console.log(getUpcomingSunday());
Or to get the latest first day:
function getLastSunday() {
const date = new Date();
const today = date.getDate();
const currentDay = date.getDay();
const newDate = date.setDate(today - (currentDay || 7));
return new Date(newDate);
}
console.log(getLastSunday());
* Depending on your time zone, the beginning of the week doesn't has to start on Sunday, it can start on Friday, Saturday, Monday or any other day your machine is set to. Those methods will account for that.
* You can also format it using toISOString method like so: getLastSunday().toISOString()
Check out Date.js
Date.today().previous().monday()
var dt = new Date(); // current date of week
var currentWeekDay = dt.getDay();
var lessDays = currentWeekDay == 0 ? 6 : currentWeekDay - 1;
var wkStart = new Date(new Date(dt).setDate(dt.getDate() - lessDays));
var wkEnd = new Date(new Date(wkStart).setDate(wkStart.getDate() + 6));
This will work well.
I'm using this
function get_next_week_start() {
var now = new Date();
var next_week_start = new Date(now.getFullYear(), now.getMonth(), now.getDate()+(8 - now.getDay()));
return next_week_start;
}
Returns Monday 00am to Monday 00am.
const now = new Date()
const startOfWeek = new Date(now.getFullYear(), now.getMonth(), now.getDate() - now.getDay() + 1)
const endOfWeek = new Date(now.getFullYear(), now.getMonth(), startOfWeek.getDate() + 7)
This function uses the current millisecond time to subtract the current week, and then subtracts one more week if the current date is on a monday (javascript counts from sunday).
function getMonday(fromDate) {
// length of one day i milliseconds
var dayLength = 24 * 60 * 60 * 1000;
// Get the current date (without time)
var currentDate = new Date(fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate());
// Get the current date's millisecond for this week
var currentWeekDayMillisecond = ((currentDate.getDay()) * dayLength);
// subtract the current date with the current date's millisecond for this week
var monday = new Date(currentDate.getTime() - currentWeekDayMillisecond + dayLength);
if (monday > currentDate) {
// It is sunday, so we need to go back further
monday = new Date(monday.getTime() - (dayLength * 7));
}
return monday;
}
I have tested it when week spans over from one month to another (and also years), and it seems to work properly.
Good evening,
I prefer to just have a simple extension method:
Date.prototype.startOfWeek = function (pStartOfWeek) {
var mDifference = this.getDay() - pStartOfWeek;
if (mDifference < 0) {
mDifference += 7;
}
return new Date(this.addDays(mDifference * -1));
}
You'll notice this actually utilizes another extension method that I use:
Date.prototype.addDays = function (pDays) {
var mDate = new Date(this.valueOf());
mDate.setDate(mDate.getDate() + pDays);
return mDate;
};
Now, if your weeks start on Sunday, pass in a "0" for the pStartOfWeek parameter, like so:
var mThisSunday = new Date().startOfWeek(0);
Similarly, if your weeks start on Monday, pass in a "1" for the pStartOfWeek parameter:
var mThisMonday = new Date().startOfWeek(1);
Regards,
a more generalized version of this... this will give you any day in the current week based on what day you specify.
//returns the relative day in the week 0 = Sunday, 1 = Monday ... 6 = Saturday
function getRelativeDayInWeek(d,dy) {
d = new Date(d);
var day = d.getDay(),
diff = d.getDate() - day + (day == 0 ? -6:dy); // adjust when day is sunday
return new Date(d.setDate(diff));
}
var monday = getRelativeDayInWeek(new Date(),1);
var friday = getRelativeDayInWeek(new Date(),5);
console.log(monday);
console.log(friday);
Simple solution for getting the first day of the week.
With this solution, it is possible to set an arbitrary start of week (e.g. Sunday = 0, Monday = 1, Tuesday = 2, etc.).
function getBeginOfWeek(date = new Date(), startOfWeek = 1) {
const result = new Date(date);
while (result.getDay() !== startOfWeek) {
result.setDate(result.getDate() - 1);
}
return result;
}
The solution correctly wraps on months (due to Date.setDate() being used)
For startOfWeek, the same constant numbers as in Date.getDay() can be used
setDate() has issues with month boundaries that are noted in comments above. A clean workaround is to find the date difference using epoch timestamps rather than the (surprisingly counterintuitive) methods on the Date object. I.e.
function getPreviousMonday(fromDate) {
var dayMillisecs = 24 * 60 * 60 * 1000;
// Get Date object truncated to date.
var d = new Date(new Date(fromDate || Date()).toISOString().slice(0, 10));
// If today is Sunday (day 0) subtract an extra 7 days.
var dayDiff = d.getDay() === 0 ? 7 : 0;
// Get date diff in millisecs to avoid setDate() bugs with month boundaries.
var mondayMillisecs = d.getTime() - (d.getDay() + dayDiff) * dayMillisecs;
// Return date as YYYY-MM-DD string.
return new Date(mondayMillisecs).toISOString().slice(0, 10);
}
Here is my solution:
function getWeekDates(){
var day_milliseconds = 24*60*60*1000;
var dates = [];
var current_date = new Date();
var monday = new Date(current_date.getTime()-(current_date.getDay()-1)*day_milliseconds);
var sunday = new Date(monday.getTime()+6*day_milliseconds);
dates.push(monday);
for(var i = 1; i < 6; i++){
dates.push(new Date(monday.getTime()+i*day_milliseconds));
}
dates.push(sunday);
return dates;
}
Now you can pick date by returned array index.
An example of the mathematically only calculation, without any Date functions.
const date = new Date();
const ts = +date;
const mondayTS = ts - ts % (60 * 60 * 24 * (7-4) * 1000);
const monday = new Date(mondayTS);
console.log(monday.toISOString(), 'Day:', monday.getDay());
const formatTS = v => new Date(v).toISOString();
const adjust = (v, d = 1) => v - v % (d * 1000);
const d = new Date('2020-04-22T21:48:17.468Z');
const ts = +d; // 1587592097468
const test = v => console.log(formatTS(adjust(ts, v)));
test(); // 2020-04-22T21:48:17.000Z
test(60); // 2020-04-22T21:48:00.000Z
test(60 * 60); // 2020-04-22T21:00:00.000Z
test(60 * 60 * 24); // 2020-04-22T00:00:00.000Z
test(60 * 60 * 24 * (7-4)); // 2020-04-20T00:00:00.000Z, monday
// So, what does `(7-4)` mean?
// 7 - days number in the week
// 4 - shifting for the weekday number of the first second of the 1970 year, the first time stamp second.
// new Date(0) ---> 1970-01-01T00:00:00.000Z
// new Date(0).getDay() ---> 4
It is important to discern between local time and UTC. I wanted to find the start of the week in UTC, so I used the following function.
function start_of_week_utc(date, start_day = 1) {
// Returns the start of the week containing a 'date'. Monday 00:00 UTC is
// considered to be the boundary between adjacent weeks, unless 'start_day' is
// specified. A Date object is returned.
date = new Date(date);
const day_of_month = date.getUTCDate();
const day_of_week = date.getUTCDay();
const difference_in_days = (
day_of_week >= start_day
? day_of_week - start_day
: day_of_week - start_day + 7
);
date.setUTCDate(day_of_month - difference_in_days);
date.setUTCHours(0);
date.setUTCMinutes(0);
date.setUTCSeconds(0);
date.setUTCMilliseconds(0);
return date;
}
To find the start of the week in a given timezone, first add the timezone offset to the input date and then subtract it from the output date.
const local_start_of_week = new Date(
start_of_week_utc(
date.getTime() + timezone_offset_ms
).getTime() - timezone_offset_ms
);
I use this:
let current_date = new Date();
let days_to_monday = 1 - current_date.getDay();
monday_date = current_date.addDays(days_to_monday);
// https://stackoverflow.com/a/563442/6533037
Date.prototype.addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
It works fine.
Accepted answer won't work for anyone who runs the code in UTC-XX:XX timezone.
Here is code which will work regardless of timezone for date only. This won't work if you provide time too. Only provide date or parse date and provide it as input. I have mentioned different test cases at start of the code.
function getDateForTheMonday(dateString) {
var orignalDate = new Date(dateString)
var modifiedDate = new Date(dateString)
var day = modifiedDate.getDay()
diff = modifiedDate.getDate() - day + (day == 0 ? -6:1);// adjust when day is sunday
modifiedDate.setDate(diff)
var diffInDate = orignalDate.getDate() - modifiedDate.getDate()
if(diffInDate == 6) {
diff = diff + 7
modifiedDate.setDate(diff)
}
console.log("Given Date : " + orignalDate.toUTCString())
console.log("Modified date for Monday : " + modifiedDate)
}
getDateForTheMonday("2022-08-01") // Jul month with 31 Days
getDateForTheMonday("2022-07-01") // June month with 30 days
getDateForTheMonday("2022-03-01") // Non leap year February
getDateForTheMonday("2020-03-01") // Leap year February
getDateForTheMonday("2022-01-01") // First day of the year
getDateForTheMonday("2021-12-31") // Last day of the year
Extending answer from #Christian C. Salvadó and information from #Ayyash (object is mutable) and #Awi and #Louis Ameline (set hours to 00:00:00)
The function can be like this
function getMonday(d) {
var day = d.getDay(),
diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday
d.setDate(diff);
d.setHours(0,0,0,0); // set hours to 00:00:00
return d; // object is mutable no need to recreate object
}
getMonday(new Date())
Check out: moment.js
Example:
moment().day(-7); // last Sunday (0 - 7)
moment().day(7); // next Sunday (0 + 7)
moment().day(10); // next Wednesday (3 + 7)
moment().day(24); // 3 Wednesdays from now (3 + 7 + 7 + 7)
Bonus: works with node.js too

Categories

Resources