This question already has answers here:
How to add days to Date?
(56 answers)
Closed 6 months ago.
I'm building a weekly picker. For the most part it works as intended, I actually get the right week when I click on it, but the selected days within the calendar portion of the picker are displaying a day behind. For example, in the screenshot below, the week picked is 2020-06-08 to 2020-06-14 yyyy-mm-dd format by the way. But as you can see in the picker, it displays the week shifted - 1
I'll post the relevant code but hard as I tried, I couldn't make a codesandbox for you. Way too many dependencies
Here is the convertDate function for the formatting. This is not related to the problem but in case you're wondering what was in it from the main function
const convertDate = (date) => {
let dt = new Date(date);
var yyyy = dt.getFullYear();
var mm = dt.getMonth() + 1; // getMonth() is zero-based
var dd = dt.getDate();
return `${yyyy}-${(mm > 9 ? '' : '0') + mm}-${(dd > 9 ? '' : '0') + dd}`;
};
And this the actual function that renders the days in the picker
EDIT (with help from Sergei
const handleClick = (e) => {
setDate(new Date(date.setDate(e.target.id)));
// added this to calculate the offset to my local timezone
let localDate = new Date(date.setDate(e.target.id));
var localoffset = new Date().getTimezoneOffset();
var timeZoneFromDB = -4.00;
var tzDifference = timeZoneFromDB * localoffset + localDate.getTimezoneOffset();
var offsetTime = new Date(localDate.getTime() + tzDifference * localoffset * 1000);
const firstDay = new Date(
offsetTime.setDate(offsetTime.getDate() - offsetTime.getDay() + 1)
);
const lastDay = new Date(
offsetTime.setDate(offsetTime.getDate() - offsetTime.getDay() + 7)
);
setWeek({ firstDay, lastDay });
const value = e.target.value;
setState({
...state,
[e.target.name]: value,
startdate: convertDate(firstDay),
enddate: convertDate(lastDay)
})
};
const renderDays = () => {
let month = date.getMonth() + 1;
let ar = [];
for (let i = 1; i <= days[month]; i++) {
let currentDate = new Date(date).setDate(i);
let cName = "single-number ";
if (
new Date(state.startdate).getTime() <= new Date(currentDate).getTime() &&
new Date(currentDate).getTime() <= new Date(state.enddate).getTime()
) {
cName = cName + "selected-week";4
console.clear();
console.log(new Date().getTimezoneOffset());
console.log("start date: ", new Date(state.startdate).getTime());
console.log("converted start date: ", convertDate(new Date(state.startdate).getTime()));
console.log("current date: ", new Date(currentDate).getTime());
console.log("converted current date: ", convertDate(new Date(currentDate).getTime()));
console.log("end date: ", new Date(state.enddate).getTime());
console.log("converted end date: ", convertDate(new Date(state.enddate).getTime()));
}
ar.push(
<div key={v4()} id={i} className={cName} onClick={handleClick}>
{i}
</div>
);
}
const displayDate = new Date(date).setDate(1);
let dayInTheWeek = new Date(displayDate).getDay();
let empty = [];
for (let i = 1; i < dayInTheWeek; i++) {
empty.push(<div key={v4()} id={i} className="single-number empty"></div>);
}
return [...empty, ...ar];
};
Here's a pic of what I am console.logging so you can see that I am capturing the intended dates (ignore the undefined). This is the state being console logged in the useEffect() But also check out the individual logs from within the renderDays(). They're a day behind
I just need the days in the picker to + 1 in the view Thanks in advanced you for your help
With the help of Sergei and Heretic in the comments I was able to get it to work by adding the following helper function outside of the main view object
function addDays(date, days) {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
Then I updated my render function to conditionally check this way
let currentTime = new Date(currentDate).getTime()
let startdayinview = new Date(state.startdate).getTime()
let enddayinview = new Date(state.enddate).getTime()
if (
addDays(startdayinview, -1) <= addDays(currentTime, -2) &&
addDays(currentTime, 0) <= addDays(enddayinview, 1)
) {
cName = cName + "selected-week";
}
As Heretic mentioned, the Date object is not ideal, but we gotta work with what we're given!
I have Contract_End_Date 2 version : 2020-1-1 and 2020-1-11
Result will be like: 2020-01-01 or 2020-01-11
What is solution here?
var updates = {};
var removes = {};
let Contract_End_Date = '2020-1-11';
if (typeof Contract_End_Date !== 'undefined' && Contract_End_Date != null) {
var arr = Contract_End_Date.split(" ");
if (arr.length == 2) {
var firstPart = arr[0];
var dateParts = firstPart.split("-");
if (dateParts.length == 3) {
var day = parseInt(dateParts[2]);
if (day < 10) {
day = "0" + day;
}
var month = parseInt(dateParts[1]);
if (month < 10) {
month = "0" + month;
}
var year = dateParts[0];
updates["Contract_End_Date"] = year + "-" + month + "-" + day;
}
}
}
console.log(updates);
For working with dates in JS, I can just recommend "Moment.js".
It makes your code much more simple and readable.
In your case:
let Contract_End_Date = '2020-1-11';
let formattedDate = moment(Contract_End_Date, 'YYYY-MM-DD').format('YYYY-MM-DD');
console.log(formattedDate);
// 2020-01-11
For more information: https://momentjs.com/
EDIT: Since Moment.js won't get updated with the newest features, it may be better to use other libaries like Luxon
I got lot of selected data from fullcalendar. I need to get those selected date from one whole year. How to check that in for loop?
I tried few answers to add days one by one to my condition from some answers ,but its not working for me.
Here is my code I tried:
var t=$(#dttbl).datatable();
var arr = new Array();
var date = new Date(),
var Id = 1;
var d = date.getDate(),
month = date.getMonth(),
year = date.getFullYear()
var day1 = y + '-01-01';
var day365 = y + '-12-31';
for (i = day1; i < day365; day1.setdate(day1.getdate() + 1)) {
if (($(i.cell).css('backgroundColor', 'blue'))) {
arr.push(([Id,i,'test']));
Id++;
}
}
for (i = 0; i < arr.length; i++) {
t.row.add([
arr[i][0],
arr[i][1],
arr[i][2]
]).draw();
}
I tried this getdate(), day1.add(1).day(); , day1=moment(day1).add(1, 'days') to add one by one day to check my condition for full year? These are not working for me. Is there any other way to do it?
You can use the following as #mplungjan commented.
var arr = [];
var date = new Date('01-01-2019');
var DAY = 1000 * 60 * 60 * 24;
var day1 = date.getTime();
var day365 = day1+ 365*DAY;
var iDay = day1;
while(iDay < day365){
// pushing the value in arr for example.
arr.push(new Date(iDay));
// do your logic
iDay = iDay + DAY;
}
You can use daysInMonth function of moment.js to find how many days in each month. After that you can create your array.
var dates = [];
var year = new Date().getFullYear();
for (var i = 1, l = 12; i <= l; i++){
var daysInMonth = moment("2012-" + i, "YYYY-M").daysInMonth();
console.log("month : " + i)
console.log("days in month : " + daysInMonth)
for (i1 = 1, l1 = daysInMonth; i1 <= l1; i1++) {
dates.push(year + "-" + i + "-" + i1)
}
}
console.log(dates);
I am working on a Onchange() event form.
Form example
By default, the Present Value as of date is today. If a user enters Remaining payments = 12 months then the
End of Lease = Present Value as of date + Remaining payment (i.e months).
For my onchange event i am trying to calculate Start of Lease automatically.
Here, Start of Lease = End of lease - Remaining payment.
Here is my code so far. The issue i am having is that the Start of Lease date is getting reflected but it's returning a day less than End of Lease. However, the first part calculating the End of Lease itself is working fine.
function PopulateEndDate() {
debugger;
var d2;
var paymentDays;
var stDate;
var pDate;
var etDate;
var ddlFrequency = document.getElementById("ddFrequency");
var selectedFrequency = ddlFrequency.options[ddlFrequency.selectedIndex].value;
if (document.getElementById("startDate"))
stDate = document.getElementById("startDate").value;
if (document.getElementById("presentDate"))
pDate = document.getElementById("presentDate").value;
var today = new Date();
if (stDate)
d2 = new Date(stDate);
else
d2 = new Date(pDate);
if (document.getElementById("paymentRemaining")) {
if (selectedFrequency == "D") {
paymentDays = document.getElementById("paymentRemaining").value;
}
else if (selectedFrequency == "Q") {
paymentDays = document.getElementById("paymentRemaining").value * 3;
}
}
if (paymentDays && paymentDays != "")
d2.setMonth(d2.getMonth() + parseInt(paymentDays));
if (document.getElementById("endDate"))
document.getElementById("endDate").value = getCurrentDay(d2);
var endDate = document.getElementById("endDate").value;
if (endDate)
etDate = new Date(endDate);
if (stDate == null && paymentDays && paymentDays != "")
{
etDate.setMonth(etDate.getMonth() - parseInt(paymentDays));
}
if (document.getElementById("startDate"))
document.getElementById("startDate").value = getCurrentDay(etDate);
}
I am not sure what i am doing wrong here. Any help will be greatly appreciated. Thank you.
if (endDate){
var etDate = new Date(endDate);
var eDay = etDate.getUTCDate()+1;
var eMonth = etDate.getUTCMonth()+1;
var eYear = etDate.getUTCFullYear()-1;
var sDate = eYear + "-" + eMonth + "-" + eDay;
if (stDate == null)
{
sDate.setMonth(sDate.getDay() - parseInt(paymentDays));
}
if (document.getElementById("startDate"))
document.getElementById("startDate").value = getCurrentDay(sDate);
This helped solve my problem.
From JavaScript is there a way to get list of days between two dates from MySQL format. I don't want to use any library for this.
This is what i did.
function generateDateList(from, to) {
var getDate = function(date) { //Mysql Format
var m = date.getMonth(), d = date.getDate();
return date.getFullYear() + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d);
}
var fs = from.split('-'), startDate = new Date(fs[0], fs[1], fs[2]), result = [getDate(startDate)], start = startDate.getTime(), ts, end;
if ( typeof to == 'undefined') {
end = new Date().getTime();
} else {
ts = to.split('-');
end = new Date(ts[0], ts[1], ts[2]).getTime();
}
while (start < end) {
start += 86400000;
startDate.setTime(start);
result.push(getDate(startDate));
}
return result;
}
console.log(generateDateList('2014-2-27', '2014-3-2'));
I test it from chrome and nodejs below are the result.
[ '2014-02-27',
'2014-02-28',
'2014-02-29',
'2014-02-30',
'2014-02-31',
'2014-03-01',
'2014-03-02' ]
yeh big leap year:-D..., how can i fix this? or is there any better way.?
const listDate = [];
const startDate ='2017-02-01';
const endDate = '2017-02-10';
const dateMove = new Date(startDate);
let strDate = startDate;
while (strDate < endDate) {
strDate = dateMove.toISOString().slice(0, 10);
listDate.push(strDate);
dateMove.setDate(dateMove.getDate() + 1);
};
Take the start date and increment it by one day until you reach the end date.
Note: MySQL dates are standard format, no need to parse it by hand just pass it to the Date constructor: new Date('2008-06-13').
const addDays = (date, days = 1) => {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
};
const dateRange = (start, end, range = []) => {
if (start > end) return range;
const next = addDays(start, 1);
return dateRange(next, end, [...range, start]);
};
const range = dateRange(new Date("2014-02-27"), new Date("2014-03-02"));
console.log(range);
console.log(range.map(date => date.toISOString().slice(0, 10)))
Here I use a recursive function, but you could achieve the same thing using a while (see other answers).
I have used this one from
https://flaviocopes.com/how-to-get-days-between-dates-javascript/
const getDatesBetweenDates = (startDate, endDate) => {
let dates = []
//to avoid modifying the original date
const theDate = new Date(startDate)
while (theDate < new Date(endDate)) {
dates = [...dates, new Date(theDate)]
theDate.setDate(theDate.getDate() + 1)
}
dates = [...dates, new Date(endDate)]
return dates
}
Invoke the function as follows:
getDatesBetweenDates("2021-12-28", "2021-03-01")
Note - I just had to fix issues with the Date object creation (new Date()) in the while loop and in the dates array. Other than that the code is pretty much same as seen on the above link
dateRange(startDate, endDate) {
var start = startDate.split('-');
var end = endDate.split('-');
var startYear = parseInt(start[0]);
var endYear = parseInt(end[0]);
var dates = [];
for(var i = startYear; i <= endYear; i++) {
var endMonth = i != endYear ? 11 : parseInt(end[1]) - 1;
var startMon = i === startYear ? parseInt(start[1])-1 : 0;
for(var j = startMon; j <= endMonth; j = j > 12 ? j % 12 || 11 : j+1) {
var month = j+1;
var displayMonth = month < 10 ? '0'+month : month;
dates.push([i, displayMonth, '01'].join('-'));
}
}
return dates;
}
var oDate1 = oEvent.getParameter("from"),
oDate2 = oEvent.getParameter("to");
var aDates = [];
var currentDate = oDate1;
while (currentDate <= oDate2) {
aDates.push(new Date(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
}
I expanded Công Thắng's great answer to return {years, months, days}, thought it was worth sharing:
function getDates(startDate, endDate) {
const days = [],
months = new Set(),
years = new Set()
const dateMove = new Date(startDate)
let date = startDate
while (date < endDate){
date = dateMove.toISOString().slice(0,10)
months.add(date.slice(0, 7))
years.add(date.slice(0, 4))
days.push(date)
dateMove.setDate(dateMove.getDate()+1) // increment day
}
return {years: [...years], months: [...months], days} // return arrays
}
console.log(getDates('2016-02-28', '2016-03-01')) // leap year
/* =>
{
years: [ '2016' ],
months: [ '2016-02', '2016-03' ],
days: [ '2016-02-28', '2016-02-29', '2016-03-01' ]
}
*/
const {months} = getDates('2016-02-28', '2016-03-01') // get only months
Basically the function just increments the built-in Date object by one day from start to end, while the Sets capture unique months and years.