The title says it all. I'm using MomentJS in other areas, so I am comfortable with a solution that uses moment (or not - either way is fine). In this solution, the function would return the shortest path to the compared date. e.g. comparing 12-31 to 01-01 would return 1, not 364. Basically this is what I am looking to do:
var today = '08-06'; // august 6th
var dateOne = '09-03' // september 3rd
var dateTwo = '02-29' // february 29th
var dateThree = '01-01' // january 1st
getDifferenceInDays(today, dateOne); // => 28
getDifferenceInDays(today, dateTwo); // => -159
getDifferenceInDays(today, dateThree); // => 147
This works with MomentJS. The caveat is that when you initialize MomentJS date it implicitly adds the year to this year. So, the assumption is that these values are calculated for this year
function getDifferenceInDays(date1, date2) {
var day1 = moment(date1,'MM-DD').dayOfYear();
var day2 = moment(date2,'MM-DD').dayOfYear();
var diff1=(day2 - day1)
var diff2=365- Math.abs(diff1)
if (Math.abs(diff1)>Math.abs(diff2)) {
return diff2;
} else {
return diff1;
}
}
var today = '08-06'; // august 6th
var dateOne = '09-03' // september 3rd
var dateTwo = '02-29' // february 29th
var dateThree = '01-01' // january 1st
console.log(";;;;")
console.log(getDifferenceInDays(today, dateOne)); // => 28
console.log(getDifferenceInDays(today, dateTwo)); // => -159
console.log(getDifferenceInDays(today, dateThree)); // => 147
http://jsfiddle.net/r2brgf4r/
You should be able to do this pretty easily with MomentJS by getting the month and day of the month from your Date object.
var getDifferenceInDays = function(date1, date2) {
var day1 = date1.dayOfYear();
var day2 = date2.dayOfYear();
if (Math.abs(day1 - day2) < (365 - Math.abs(day2 - day1))) {
return Math.abs(day1 - day2);
} else {
return (365 - Math.abs(day1 - day2));
}
}
Moment's "dayOfYear()" function returns the day of the year (a number between 1 and 366). Hope this helps!
Related
I am trying to get the date range of the past Wednesday to past Tuesday(7 days) from today's date.
Say the current date is 2022-05-01(May 1st), I am expecting the result to be the past Tuesday(end date) to Past Wednesday (start date = Past Tuesday -7 days)
i.e 20 April 2022 to 26 April 2022
function getStartAndEndDates () {
var now = new Date('2022-05-01'); //May 1st 2022
var day = now.getDay();
var diff = (day <= 2) ? (7 - 2 + day ) : (day - 2);
var PastTuesday = new Date();
var PastWednesday = new Date(PastTuesday.setDate(now.getDate() - diff));
console.log('End date is', PastTuesday.toISOString());
PastWednesday.setDate(PastTuesday.getDate() - 6);
console.log('Start Date is',PastWednesday.toISOString());
return[PastWednesday,PastTuesday];
}
Output obtained is:
End date is 2022-03-27T19:25:35.726Z //here month is set to March
Start Date is 2022-03-21T19:25:35.726Z
Expected Result is
End date is 2022-04-26T19:25:35.726Z // month is supposed to be April
Start Date is 2022-04-20T19:25:35.726Z
How can I change the code to get the expected result?
You should do something like
function getLastWeek(date) {
var today = new Date(date);
var lastWeek = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 7);
return lastWeek;
}
// Your DATE
date = '2022-05-01'
//
var lastWeek = getLastWeek(date);
var lastWeekMonth = lastWeek.getMonth() + 1;
var lastWeekDay = lastWeek.getDate();
var lastWeekYear = lastWeek.getFullYear();
var lastWeekDisplay = lastWeekMonth + "/" + lastWeekDay + "/" + lastWeekYear;
console.log(lastWeekDisplay);
In your code:
var now = new Date('2022-05-01'); //May 1st 2022
Dates in the format YYYY-MM-DD are parsed as UTC, so the above will create a date object representing 2022-05-01T00:00:00Z.
var day = now.getDay();
This will return the local day number. For users with a zero or positive offset, it will return 0 (Sunday) but for users with a negative offset, it will return 6 (Saturday) because their local date is still the previous day.
var diff = (day <= 2) ? (7 - 2 + day ) : (day - 2);
Given day is 0 (for me), the above sets diff to 5.
var PastTuesday = new Date();
This creates a date for "now", which for me is 17 April.
var PastWednesday = new Date(PastTuesday.setDate(now.getDate() - diff));
In the above, now.getDate returns 1, and 1 - 5 is -4, so it sets the date for PastTuesday to -4. Now PastTuesday is in April, so it is set to 4 days prior to the start of April, i.e. 27 March.
Note that this adjusts PastTuesday and creates a copy for PastWednesday at the same time.
console.log('End date is', PastTuesday.toISOString());
Shows the equivalent UTC date and time, with the time representing the time that the code was run.
PastWednesday.setDate(PastTuesday.getDate() - 6);
Sets PastWednesday to 6 days prior to PastTuesday.
Anyhow, what is required is to do everything either as UTC or local, don't mix the two.
Sticking to code as closely as possible to the original and assuming a timestamp in YYYY-MM-DD format is parsed to the function, consider the following, which does everything as local:
// Parse timestamp in YYYY-MM-DD format as local
function parseISOLocal(s = new Date().toLocaleDateString('en-CA')) {
let [y, m, d] = s.split(/\D/);
return new Date(y, m-1, d);
}
// Get week Wed to Tue prior to passed date
function getStartAndEndDates (date) {
// Parse timestamp as local
var pastTuesday = parseISOLocal(date);
// Adjust pastTuesday to previous Tuesday
var day = pastTuesday.getDay();
var diff = (day <= 2) ? (7 - 2 + day ) : (day - 2);
var pastWednesday = new Date(pastTuesday.setDate(pastTuesday.getDate() - diff));
console.log('End date is', pastTuesday.toDateString());
// Adjust pastWednesday to previous Wednesday
pastWednesday.setDate(pastTuesday.getDate() - 6);
console.log('Start Date is',pastWednesday.toDateString());
return [pastWednesday, pastTuesday];
}
// Sunday 1 May 2022
console.log(getStartAndEndDates('2022-05-01').map(d => d.toDateString()));
// Current date
console.log(getStartAndEndDates().map(d => d.toDateString()));
I have a date (usually the first day of a month but not necessary, it could be any date) and I want a new date corresponding to the first Monday of that month.
example:
findFirstMonday('1 jul 2021') -> 7 jul 2021
findFirstMonday('1 aug 2021') -> 2 aug 2021
findFirstMonday('13 aug 2021') -> 2 aug 2021
Here is my code that doesn't work:
const selectedDate = new Date();
const daysInSelectedDate = daysInMonth(selectedDate);
const lastDayPreviousMonth = addDays(selectedDate, daysInSelectedDate - selectedDate.getDate() + 1);
const firstDayPreviousMonth = removeDays(
lastDayPreviousMonth,
daysInMonth(lastDayPreviousMonth),
);
console.log('firstDayPreviousMonth: ', firstDayPreviousMonth);
let firstMonday = firstDayPreviousMonth;
while (firstDayPreviousMonth.getDay() !== 1) {
console.log('firstMonday: ', firstMonday, firstMonday.getDay());
firstMonday.setDate(firstMonday.getDate() + 1);
}
console.log('firstMonday: ', firstMonday, firstMonday.getDay());
function addDays(date, days) {
const result = new Date(date)
result.setDate(result.getDate() + days)
return result
}
function removeDays(date, days) {
const result = new Date(date)
result.setDate(result.getDate() - days)
return result
}
function daysInMonth(date) {
return new Date(date.getFullYear(), date.getMonth(), 0).getDate()
}
What am I wrong?
Thanks a lot
I came up with the following code. Some explanations about the general idea:
For a given date get the first date in the month of the given date. This is quite easy by generating a new Date object with day = 1 and the year and month of the given date.
Get the weekday of the first date.
Depending on the weekday of the first date, you must calculate which day number the first Monday has. This number is calculated by ((8 - firstWeekdayInMonth) % 7). You can easily verify yourself, that this always yields a Monday. The modulo is important for Sundays and Mondays, where you would otherwise add 8 and 7 respectively, which would not yield the first Monday anymore.
console.log(findFirstMonday('1 jul 21'))
console.log(findFirstMonday('1 aug 21'))
console.log(findFirstMonday('13 aug 21'))
function findFirstMonday(dateString) {
let targetDate = new Date(dateString);
let targetMonth = targetDate.getMonth();
let targetYear = targetDate.getFullYear();
let firstDateInMonth = new Date(targetYear, targetMonth, 1);
let firstWeekdayInMonth = firstDateInMonth.getDay();
let firstMondayDate = 1 + ((8 - firstWeekdayInMonth) % 7);
return new Date(targetYear, targetMonth, firstMondayDate).toLocaleDateString();
}
Edit:
console.log(findFirstMondayMonth('1 jul 2021').toLocaleDateString())
console.log(findFirstMondayMonth('1 aug 2021').toLocaleDateString())
console.log(findFirstMondayMonth('2 aug 2021').toLocaleDateString())
console.log(findFirstMondayMonth('13 aug 2021').toLocaleDateString())
function findFirstMonday(dateString) {
let date = new Date(dateString)
let diffDay = date.getDay() - 1
if (diffDay == -1) {
diffDay = 6
}
let mondayDate = new Date(dateString);
mondayDate.setHours(mondayDate.getHours() - diffDay*24)
return mondayDate
}
function findFirstMondayMonth(dateString) {
let date = new Date(dateString)
if (date.getMonth() == findFirstMonday(date).getMonth()) {
let dateOneWeekBefore = new Date(dateString)
dateOneWeekBefore.setHours(dateOneWeekBefore.getHours() - 24 * 7)
if (date.getMonth() == dateOneWeekBefore.getMonth()) {
return findFirstMondayMonth(dateOneWeekBefore)
} else {
return findFirstMonday(date)
}
} else {
let dateOneWeekAfter = new Date(dateString)
dateOneWeekAfter.setHours(dateOneWeekAfter.getHours() + 24 * 7)
return findFirstMonday(dateOneWeekAfter)
}
}
Sorry for the last answer, I think it was the first monday of week and I don't see Sunday.getMonth() == -1
I'm supposed to write a code for codewars to find out the number of times a month ends with a Friday within a range of years.
To start off, I did research and found out several solutions but I still couldn't figure out the results in the console.log.
The first solution is from this tutorial:
In this code, the solution is
let LastDay = new Date(1998, 5 + 1, 0).getDate();
I was able to get the date, but it wasn't clear which day the date falls upon.
Then I found another solution at w3schools. This solution also set the date to be the last day of this month:
var d = new Date();
d.setMonth(d.getMonth() +1, 0);
document.getElementById("demo").innerHTML = d;
However, it works if it displays it as innerHTML = Sat Nov 30 2019 00:57:09 GMT-0500 (Eastern Standard Time). However, when I tried to rewrite the code and console.log it like in this example:
let d = new Date();
let month = d.getMonth()+1;
let lastday = d.setMonth(month, 0);
console.log(lastday);
The result I got was 1575093343211. I don't understand how it displays those numbers instead of the dates I was expecting. I thought that if it does display the dates, starting with the day, I can convert the date to string or array and check if the first element is Friday and then add it to the counter in the code I'm writing. How do I get the code to display the way I want it to.
something like this will work...
function LastDayOfMonth(Year, Month) {
return new Date((new Date(Year, Month, 1)) - 1);
}
var d = LastDayOfMonth(new Date().getYear(), new Date().getMonth())
//var d = LastDayOfMonth(2009, 11)
var dayName = d.toString().split(' ')[0];
console.log(dayName)
The result I got was 1575093343211. I don't understand how it displays those numbers instead of the dates I was expecting
Because you console.log the output of the setMonth method, not the date object:
let lastday = d.setMonth(month, 0);
console.log(lastday);
According to the documentation, the setMonth method returns:
The number of milliseconds between 1 January 1970 00:00:00 UTC and the updated date.
Instead you should use that output to create a new instance of the date object:
let lastday = new Date(d.setMonth(month, 0));
console.log(lastday);
Algorithms to get the last day of the month are generally based on setting a date to day 0 of the following month, which ends up being the last day of the required month.
E.g. to get the last day for June, 2019 (noting that 6 is July, not June):
let endOfJune = new Date(2019, 6, 0):
Once you have the date, you can get the day where 0 is Sunday, 1 is Monday, etc. and 5 is Friday:
let endOfJuneDay = endOfJune.getDay();
The set* methods modify the Date they're called on and return the time value for the modified date. So you don't need to assign the result to anything:
let d = new Date();
let month = d.getMonth() + 1;
// Set date to the new month
d.setMonth(month, 0);
console.log(d);
So if you want to loop over the months for a range of years and get the number that end with a Friday (or any particular day), you might loop over the months something like:
/*
** #param {number} startYear - start year of range
** #param {number} endYear - end year of range
** #param {number} dat - day number, 0 = Sunday, 1 = Monday, etc.
** default is 0 (Sunday)
*/
function countEOMDay(startYear, endYear, day = 0) {
// startYear must be <= end year
if (startYear > endYear) return;
// Start on 31 Jan of start year
let start = new Date(startYear, 0, 31);
// End on 31 Dec of end year
let end = new Date(endYear, 11, 31);
let count = 0;
// Loop over months from start to end
while (start <= end) {
// Count matching days
if (start.getDay() == day) {
++count;
}
// Increment month to end of next month
start.setMonth(start.getMonth() + 2, 0);
}
return count;
}
console.log(countEOMDay(2019, 2019, 5)); // 1
console.log(countEOMDay(2018, 2019, 5)); // 3
You can use setMonth() method to set the month of a date object. The return value of setMonth() method is milliseconds between the date object and midnight January 1 1970. That's what you get from console.log(lastday);
Your return value,
1575093343211
is milliseconds between your date object (d) and midnight January 1 1970.
If you want to get the expected date, you have to console log your date object instead the lastday, as follows:
let d = new Date();
let month = d.getMonth()+1;
let lastday = d.setMonth(month, 0);
console.log(d);
output: Sat Nov 30 2019 00:02:47 GMT+0530 (India Standard Time)
This is an alternative solution I wrote to solve your problem. This will return the number of times a month ends with a Friday within a range of years. Hope this will help you :)
var days = [];
var count = 0;
function getLastFridaysCount(startYear, endYear) {
for (var year = startYear; year <= endYear; year++) {
days = [
31,
0 === year % 4 && 0 !== year % 100 || 0 === year % 400 ? 29 : 28,
31, 30, 31, 30, 31, 31, 30, 31, 30, 31
];
for (var month = 0; month <= 11; month++) {
var myDate = new Date();
myDate.setFullYear(year);
myDate.setMonth(month);
myDate.setDate(days[month]);
if(myDate.getDay() == 5)
{
count++;
}
}
}
return count;
}
console.log("count", getLastFridaysCount(2014, 2017));
this is the solution, in the code can find the comments "//" explaining of what happens in each iteration.
function lastDayIsFriday(initialYear, endYear) {
let count = 0;
//according to when the year ends starts the loop
if (endYear !== undefined) {
let start = new Date(initialYear, 0, 31);
let end = new Date(endYear, 11, 31);
while(start <= end) { //check if the start date is < or = to the end
//The getDay() method returns the day of the week (from 0 to 6) for the specified date.
if(start.getDay() === 5) { //if = to FriYAY!!!
count++; //count the day
}
start.setMonth(start.getMonth()+2, 0);// returns the month (from 0 to 11) .getMonth
} //& sets the month of a date object .setMonth
return count;
} else {
let start = new Date(initialYear, 0, 31);
console.log(start.toString());
for(let i = 0; i < 12; i++) {
if(start.getDay() === 5) {
count++;
}
start.setMonth(start.getMonth() + 2, 0);
// console.log(start.toString());
}
return count;
}
}
I've a variable that has value of date in YYYYMM format. For example:
var givenDate = "201704"
How can I find out the last day of the given month and append to it. For example,
//last day of 2017 04 (April) is 30th so append value to givenDate + lastDate;
//that will be 20170430
var newFullGivenDate = "20170430";
const date = "201704";
const year = parseInt(date.substring(0, 4));
const month= parseInt(date.substring(4, 6));
const lastDay = (new Date(year, month, 0)).getUTCDate();
const newFullGivenDate = date + lastDay;
console.log(newFullGivenDate);
var givenDate = "201704";
var month = givenDate.substring(4, givenDate.length); // retrieves 04
var year = givenDate.substring(0, 4); // retrieves 2017
var d = new Date(year, month, 0);
alert(d.getDate());
Reference: MDN
To achieve expected result, use below option
last day of month - new Date(year,month ,0)
var givenDate = "201704";
var currDate = new Date(givenDate.substr(0,3),givenDate.substr(4) ,0)
var newFullGivenDate = givenDate + currDate.getDate();
console.log(newFullGivenDate)
Codepen URL for reference - https://codepen.io/nagasai/pen/OmgZMW
I would break it down into two functions:
// Get last day from year and month
let lastDayOf = (year, month) => (new Date(year, month, 0)).getDate();
// Add last day to string only if input is correct
let addLastDay = (input) => {
// In case you pass number (201705) instead of string ("201705")
if (Number.isInteger(input)) input = input.toString();
// Check if input is in correct format - 6 digit string
if (typeof input !== "string" || !input.match(/^\d{6}$/)) {
return input; // You can implement desired behavour here. I just return what came
}
const year = input.substr(0, 4);
const month = input.substr(4, 2);
return input + lastDayOf(year, month);
}
// Tests
console.assert(addLastDay("201704"), "20170430");
console.assert(addLastDay("201702"), "20170228");
console.assert(addLastDay("201202"), "20120229");
console.assert(addLastDay(201705), "20170531");
console.assert(addLastDay(20170), 20170); // Wrong input
// Interactive example
document.getElementsByTagName('button')[0].addEventListener('click', () => {
let input = document.getElementsByTagName('input')[0];
input.value = addLastDay(input.value);
});
<input type="text" value="201704"><button>Calculate</button>
If you are using moment js you can yry this:
var date = moment(newFullGivenDate ).format('YYYYMMDD');
date = date.add(-1 * parseInt(date.format('DD')), 'days').add(1, 'months');
How would I write this expression in JavaScript?
It is to represent a date that is 2 weeks, counted by each passing Thursday, but excludes the thursday of the week the date was made.
NeededDay = Today + (18 - DayOfWeek(today))
or since it is Wednesday, it could be written?
var date = new Date();
var NeededDate = date.getDay() + (18-3);
or
I wrote this but I do not know if it is right?
var value = 3;
var GivenDate = value;
var GivenDay = value.getDay();
var daysToSecondThursday = Givenday2.setDate(GivenDay + Givenday2.setDate(18 - GivenDay));
alert("two weeks after next thursday is = " + daysToSecondThursday.val());
what is the correct way? ?
You could use:
function GetThursdayIn2Weeks(date)
{
var day = date.getDay();
// Add 2 weeks.
var newDate = new Date(date.setTime(date.getTime() + (14 * 86400000)));
// Adjust for Thursday.
var adjust = 4 - day;
if (adjust <= 0) // Might need to be changed - See comments!
adjust +=7;
// Apply Thursday adjustment.
newDate = new Date(newDate.setTime(newDate.getTime() + (adjust * 86400000)));
return newDate;
}
If the date passed in is Thursday, then it will return two weeks from the following Thursday. If this is not what you want, then adjust the if (adjust <= 0) code above to be:
if (adjust < 0)
Here is a jsFiddle: http://jsfiddle.net/kgjertsen/ec7vnezn/