Javascript - sort and manipulate array of dates - javascript

I'm trying to prep a table which would have a header be an array of months/year. So the table would look roughly like such:
month1/year, month2/year, month3/year, etc....
field1:
field2:
field3:
The particular months/years are based upon a start and end date provided by a user. Based on some answers here, I have the logic working, however I hit a snag. By the way I've gone about getting the month (using getMonth()), it returns it as the index (so 0 for Jan, etc.). My first thought was just to +1, but clearly I then run into an issue with December -> January. My javascript skills are weak, so my only thought is to write in an if statement and adjust the final array after the fact.
Here's what I have so far:
function dateRange(startDate, endDate, steps = 1) {
const dateArray = [];
let currentDate = new Date(startDate);
while (currentDate <= new Date(endDate)) {
dateArray.push(new Date(currentDate));
// Use UTC date to prevent problems with time zones and DST
currentDate.setUTCDate(currentDate.getUTCDate() + steps);
}
console.log("dateArray: ", dateArray)
const monthSet = dateArray.map(i => `${i.getMonth()}/${i.getFullYear()}`)
const header = [...new Set(monthSet)]
return header;
}
const dates = dateRange(isStart, isEnd);
console.log(dates);

It's not entirely clear what you're asking, sorry. But if you're wondering how to increment the month index without getting numbers like 13, 14, etc., you can use the modulo operator:
1 % 12 === 1;
2 % 12 === 2;
3 % 12 === 3;
10 % 12 === 10;
12 % 12 === 0;
13 % 12 === 1;
You should be safe simply adding 1 to .getMonth(), since that function will only ever yield values 0 though 11.

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

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

Get all specific day in specific end date in JavaScript

I am trying to get all day (input by me) in a specific end date (input by me).
example :
I have day 1 and I have end date 10/12/2021
beginning from new Date():
output must be: 1/10/2021 1/11/2021 1/12/2021
day 1 for this month is not included because we are in day 20 and day 20 > day 1
Same, I chose day 20 (example) and end date = 19/12/2021 day 20 in end date not included because day 20 > end date day
I have already tried that as simple using if condition, but not great work because in this case, I have 8 conditions!
I want a simple code that works for this situation.
Hope that is what you wanted. You can simplify it more if you want.
const getRemainingDates = function(beginningDay, endDate){
const today = new Date()
const [endDateDay,endDateMonth,endDateYear] = endDate.split("/");
const remainingMonth = endDateMonth - (today.getMonth()+1);
for(let i = 0; i <= remainingMonth; i++){
if(i === 0){
if(beginningDay>today.getDate() && beginningDay>endDateDay){
console.log(`${beginningDay}/${today.getMonth()+1+i}/${today.getFullYear()}`)
}
else {}
}
if(i !== 0)console.log(`${beginningDay}/${today.getMonth()+1+i}/${today.getFullYear()}`)
}
}
getRemainingDates(21,"12/12/2021");
console.log()
getRemainingDates(1,"12/12/2021");

How to generate an array of quarter numbers of a year along with year number based on current date using moment.js in node js?

I want to create an array of quarter numbers along with year number using current timestamp in node js.
For example, current quarter is, Q1 and year is, 2020. Now, I want to create an array like the following.
quarters = ['Q2-2019','Q3-2019','Q4-2019','Q1-2020']
In the above array, Q1 is of year 2020 and remaining 3 are from year 2019
Basically my requirement is to create array of quarters including present quarter number and past 3 quarter numbers along with year number.
Right now, am getting an array like, ['Q2','Q3','Q4','Q1'] by using the following code given by #Santhosh S. The code is,
let quarters = [ 0, 1, 2, 3 ].map(i =>
moment().subtract(i, 'Q').format('[Q]Q')
);
console.log(quarters);
Is there anyway to generate this array?
use moment().quarter(); to get current quarter.
Edit: use subtract and format to Quarter. Sample code below
let format = '[Q]Q';
let quarters = [
moment().format(format),
moment().subtract(1, 'Q').format(format),
moment().subtract(2, 'Q').format(format),
moment().subtract(3, 'Q').format(format)
];
console.log(quarters);
<script src="https://momentjs.com/downloads/moment.min.js"></script>
Or a more concise version:
let quarters = [ 0, 1, 2, 3 ].map(i =>
moment().subtract(i, 'Q').format('[Q]Q')
);
console.log(quarters);
<script src="https://momentjs.com/downloads/moment.min.js"></script>
You could get the actual month and add one for the next quarter and the quarter count and get the remainder with four for mapping the quarters.
var month = new Date().getMonth(),
quarters = ['Q1', 'Q2', 'Q3', 'Q4'].map((_, i, a) => a[Math.floor(month / 3 + 1 + i) % 4]);
console.log(quarters);
Using moment.js
const moment = require('moment');
let out = Array(4).fill().map((_, i) => 'Q' + moment().subtract(9-(3*i), 'months').quarter())
console.log(out)
Please check MomentJs Quarters: here
Something like moment().quarter(Number); based on the current day and create your Q-array.
Try with the following
function getQuarter(date) {
// `getMonth` returns an int from 0 to 11.
return Math.floor(date.getMonth() / 3) + 1;
}
function buildQuartersList(currentQuarter) {
// `fill` is needed, otherwise, `map` won't run.
const quartersList = new Array(4).fill().map((element, index) => {
const quarter = ((index + currentQuarter - 1) % 4) + 1;
return `Q${quarter}`;
});
return quartersList.reverse();
}
function getQuartersList(date) {
const currentQuarter = getQuarter(date);
return buildQuartersList(currentQuarter);
}
console.log(getQuartersList(new Date()));

get todays date in javascript in format yyyy-mm-ddT00:00:00

Hello i am new to javascript , i tried a lot i cant get this format
yyyy-mm-ddT00:00:00, i want to get this format in java script to compare it with other dates in an array and then get the next valid date that will come .
also if some one can show me a function on how to compare and get the closest greater date than today .
datesarray = ['2017-12-09T00:00:00' ,'2017-12-13T00:00:00' ,'2017-12-02T00:00:00' ,'2017-12-16T00:00:00']
let diffDate = Infinity;
let now = Date.now;
for (let i = 0; i < datesarray.length; i++) {
let closest = datesarray[0];
if (closest > now && closest < diffDate)
{
diffDate = closest;
}
}
this is what i tried but its never getting into the if statement .
PS : i have other dates in an array but i did not show them here .
I think you have two separate questions here, to get an iso formatted date string you would use Date.prototype.toISOString(), but to compare dates and find the closest you would need to turn those strings into date objects and compare
let datesArray = ['2017-12-09T00:00:00' ,'2017-12-13T00:00:00' ,'2017-12-02T00:00:00' ,'2017-12-16T00:00:00'];
let diffDate = Infinity;
let now = Date.now();
for (let i = 0, len = datesArray.length; i < len; i++) {
let closest = new Date(datesArray[i]);
if (closest > now && closest < diffDate) {
diffDate = closest;
}
}
console.log(diffDate.toISOString());
Edit 1
In answer to your question, I can't duplicate your undefined problem using the code above, and to illustrate that diffDate is set correctly I moved it outside of the loop, if you run the snippet you should see the closest date print.
That being said, this might be a more concise way to handle your problem as long as modern JS syntax is workable for your issue.
const datesArray = ['2017-12-09T00:00:00' ,'2017-12-13T00:00:00' ,'2017-12-02T00:00:00' ,'2017-12-16T00:00:00'];
const dateCompare = (closest, current) => {
const t = new Date(current);
return (t > Date.now() && t < closest) ? t : closest;
}
let closest = datesArray.reduce(dateCompare, Infinity)
console.log(closest.toISOString());
Edit 2
To handle timezone precision problems if possible you want your date array to have dates in iso format 'yyyy-mm-ddThh:mm:ssZ' | '2017-12-02T00:00:00Z' if you can't edit your date array format you should make sure to append that 'Z' before creating your date: new Date(current + 'Z');
For your first question, use the ISOString() function of the Date object.
https://www.w3schools.com/jsref/jsref_toisostring.asp
For the next one, either create date object of each time, and then compare, or if you need to support equality check, convert all to milliseconds from the date object.
Use the Date() object. There are many different ways to enter the date. One is what you are using.
var dateArray = [new Date('2017-12-09T00:00:00'), new Date(2017, 11, 13), new Date(2017, 11, 2), new Date(2017, 11, 16)];
var today = new Date();
var closestDate = new Date(5000, 0, 0);
for (var i = 0; i < dateArray.length; i++) {
var curr = dateArray[i];
if(curr > today && curr < closestDate) {
closestDate = new Date(curr);
}
}
console.log(closestDate); // Prints Sat Dec 02 2017 00:00:00 GMT-0500 as of 10/19/2017

Categories

Resources