I have two dates date and meeting.date coming from two APIs. I want to check, if the dates are equal.
// date = "28.02.2022";
// meeting.date = "2022-02-08 14:30:00";
const firstDate = new Date(`${date.split(".").reverse().join("-")}`);
const secondDate = new Date(`${meeting.date.split(" ")[0]}`)
firstDate.setHours(0,0,0,0);
secondDate.setHours(0,0,0,0);
console.log(firstDate, secondDate, firstDate === secondDate);
This logs me
[Log] Mon Feb 28 2022 00:00:00 GMT+0100 (CET) – Mon Feb 28 2022 00:00:00 GMT+0100 (CET) – false
I expect that to be true?
I found the solution, setting the hours to zero here on stackoverflow, but I'd say, that this is gratuitous, as I don't pass the time the Date. Anyhow, what am I doing wrong?
What you are doing here is comparing two different instances (two different references) of Date object, which lead to an unexpected result
You could try to compare the millisecond of these by using getTime
const date = "28.02.2022";
const meeting = { date: "2022-02-28 14:30:00" }
const firstDate = new Date(`${date.split(".").reverse().join("-")}`);
const secondDate = new Date(`${meeting.date.split(" ")[0]}`)
firstDate.setHours(0,0,0,0);
secondDate.setHours(0,0,0,0);
console.log(firstDate, secondDate, firstDate.getTime() === secondDate.getTime());
You are comparing the Date objects themselves - and they will never be equal unless it is the same "object" pointed to by 2 different variables, e.g.
const dateOne = dateTwo = new Date();
You must either compare the date parts as Strings, e.g.
console.log(
firstDate,
secondDate,
firstDate.toISOString().substr(0, 10) === secondDate.toISOString().substr(0, 10)
);
or compare the dates as Numbers (in milliseconds) which is the recommended way:
console.log(
firstDate,
secondDate,
firstDate.getTime() === secondDate.getTime()
);
You can use .getTime() method to convert both of the dates to the number of milliseconds since the ECMAScript epoch and then compare them.
firstDate.setHours(0,0,0,0).getTime();
secondDate.setHours(0,0,0,0).getTime();
console.log(firstDate, secondDate, firstDate === secondDate);
Related
Works:
const date = new Date();
temp = date.toISOString();
Doesn't work:
const date = new Date();
temp = date.setDate(date.getDate() - date.getDay()).toISOString();
Works too:
const date = new Date();
temp = date.setDate(date.getDate() - date.getDay()).toString();
What may be the reason for toISOString() not working?
Because .toString() can be called on almost any value while .toISOString() can only be called on Date objects1.
This code:
const date = new Date();
temp = date.setDate(date.getDate() - date.getDay()).toISOString();
is effectively the same as
const date = new Date();
const setDateReturnValue = date.setDate(date.getDate() - date.getDay());
setDateReturnValue.toISOString();
Note that date and setDateReturnValue hold two different values. The date is the Date object and setDateReturnValue is the return value of Date.prototype.setDate(), which is a number.
A number doesn't have a .toISOString() method, which is what is causing the error. A Date does have a .toISOString() method, which is why your first code snippet works fine.
Both a Date and a number have a .toString() method2, which is why those work fine, but do realize that the string they return is different in a different format. (The number will return the number as a string, where the date will return something like "Wed Sep 07 2022 16:17:40 GMT+0200 (Central European Summer Time)")
[1]: Unless of course you or a library defines this function for different types.
[2]: Technically speaking: a number a primitive and as such, doesn't have a .toString() method (or any method for that matter), but when calling a method on a number, it will be boxed into a Number object, which does have a .toString() method.
I create date in two ways:
new Date('some date').getTime();
new Date().getTime('some date');
I did it before I had read on MDN, that Date.prototype.getTime() doesn't have parameter. It means second way is wrong. Nevertheless, it gives the same date value the right way gives (new Date('*some date*').getTime();) but amount of milliseconds is different and I don't get why.
Could someone explain me?
(function () {
let dateToCount = "Jan 01, 2022 00:00:00";
let date1 = new Date(dateToCount).getTime();
let date2 = new Date().getTime(dateToCount);
console.log(Date(date1).toString()); // Tue Oct 19 2021 22:41:59 GMT+0300 (Eastern European Summer Time)
console.log(Date(date2).toString()); // Tue Oct 19 2021 22:41:59 GMT+0300 (Eastern European Summer Time)
console.log(`date1 = ${date1} ms`); // date1 = 1640988000000 ms
console.log(`date2 = ${date2} ms`); // date2 = 1634672519002 ms
console.log(`date1 - date2 = ${+date1 - (+date2)} ms`); // date1 - date2 = 6315480998 ms
})();
it gives the same date value the right way gives
No, it doesn't - it just that when you were debugging with console.log(Date(date1).toString()); you fell in yet another trap: missing the new operator in the call the Date. As MDN puts it:
Calling the Date() function (without the new keyword) returns a string representation of the current date and time, exactly as new Date().toString() does. Any arguments given in a Date() function call (without the new keyword) are ignored; regardless of whether it’s called with an invalid date string — or even called with any arbitrary object or other primitive as an argument — it always returns a string representation of the current date and time.
So if you fix that as well, you'll realise that the two different millisecond values you get back from getTime() actually do represent two different dates:
const dateToCount = "Jan 01, 2022 00:00:00";
const date1 = new Date(dateToCount).getTime();
const date2 = new Date().getTime(dateToCount);
console.log(new Date(date1).toString()); // Sat Jan 01 2022 00:00:00, as expected
console.log(new Date(date2).toString()); // Surprise!
console.log(`date1 = ${date1} ms`);
console.log(`date2 = ${date2} ms`);
I am trying to write a function that will take a string like 07/2020 and then return whether it is more than three months away.
I have written a function isMoreThan3MonthsHence that I am reasonably sure works correctly:
const isMoreThan3MonthsHence = ({ utcYear, utcMonth },
now = new Date,
target = new Date(Date.UTC(utcYear, utcMonth)),
threeMonthsAway = new Date(now.valueOf()).setUTCMonth(now.getUTCMonth() + 3)) =>
(target > threeMonthsAway)
console.log(isMoreThan3MonthsHence({ utcYear: 2020, utcMonth: 7 })) // true (correct!)
The problem comes when I try to construct a Date object to use to populate the arguments for isMoreThan3MonthsHence.
const validate = (str,
[localMonth, localYear] = str.split('/'),
date = new Date(+localYear, (+localMonth)-1)) =>
isMoreThan3MonthsHence({ utcYear: date.getUTCFullYear(), utcMonth: date.getUTCMonth() })
// Note: input is one-based months
console.log(validate('07/2020')) // false (but should be true!)
I think the reason is that new-ing up a Date in validate without specifying the timezone will use the local timezone in effect at the supplied date, which will be BST (UTC+1).
Wed Jul 01 2020 00:00:00 GMT+0100 (British Summer Time)
This time is actually 2300hrs on June 30th in UTC. So the month is actually 5 in zero-based terms. But I don't want this behavior. I want it so specifying July actually means July in UTC.
How can I fix this?
It looks like you're mixing the usage of Date.UTC and not when instantiating dates. For example, if you use the following for your validate function:
const validate = (str,
[month, year] = str.split('/'),
date = new Date(Date.UTC(+year, (+month)-1))) =>
isMoreThan3MonthsHence({ utcYear: date.getUTCFullYear(), utcMonth: date.getUTCMonth() })
// Note: input is one-based months
console.log(validate('07/2020')) // Now true
It works as expected: JSFiddle
Removing the usage of Date.UTC altogether would perform the calculation in the user's local timezone, with any applicable daylight saving adjustment included. This could be seen as a valid approach, however would result in the behaviour you have described.
Note I've renamed the local prefixed variables based on feedback from Bergi. Using Date.UTC implies you're passing in UTC arguments.
Other than mixing UTC and local dates, the way you're adding 3 months will cause an incorrect response for dates like 31 March, where adding 3 months simply by incrementing the month number results in a date for 1 July. See Adding months to a Date in JavaScript.
So validate('07,2020') will return false if run on 31 March.
To fix that, when adding months, check that the updated date is still on the same day in the month, otherwise it's rolled over so set it to the last day of the previous month.
function validate(s) {
let testDate = addMonths(new Date(), 3);
let [m, y] = s.split(/\D/);
return testDate < new Date(y, m-1);
};
function addMonths(date, months) {
let d = date.getDate();
date.setMonth(date.getMonth() + +months);
// If rolled over to next month, set to last day of previous month
if (date.getDate() != d) {
date.setDate(0);
}
return date;
}
// Sample
console.log('On ' + new Date().toDateString() + ':');
['07/2020', '04/2020'].forEach(
s => console.log(s + ' - ' + validate(s))
);
To avoid day light saving issues with date objects, I use UTC. For example:
new Date(2019,8,20, 9, 0) gives 2019-09-20T08:00:00.000Z
new Date(Date.UTC(2019,8,20, 9, 0)) gives 2019-09-20T09:00:00.000Z -- what I want
My issue now is that when I add that date to a dictionary, It uses local timezone somehow. For example:
const b = {}
b[Date(Date.UTC(2019,8,20, 9, 0))] = true
gives the following:
{ 'Fri Sep 20 2019 10:00:00 GMT+0100 (IST)': true }
you can do the following to get the UTC time -
var utcDate = new Date(Date.UTC(2019,8,20,9,0)).toUTCString()
b[utcDate] = true
EDIT
You should use ISOString() format to get format like 2019-09-20T09:00:00.000Z
var utcDate = new Date(Date.UTC(2019,8,20,9,0)).toISOString()
b[utcDate] = true
I am getting false for both conditions
localStorage.getitem("dl-visited-date") // "Mon Oct 07 2013 13:58:18 GMT-0400 (EDT)";
currentDate // Tue Oct 08 2013 14:18:26 GMT-0400 (EDT)
currentDate > localStorage.getItem("dl-visited-date") //false
currentDate < localStorage.getItem("dl-visited-date") //false
localStorage.getitem does return a string (your Date object was implicitly stringified when you stored it in the localstorage). If you compare this with a Date object, both will be casted to numbers, but while this works for the Date object the string will become NaN. And that compares false to anything.
You will need to parse it before (using the Date constructor):
var date = new Date(localStorage.getitem("dl-visited-date")),
currentDate = new Date();
If you want to test them for equality, you will need to use plain numbers instead. Use Date.parse then:
var dateStamp = Date.parse(localStorage.getitem("dl-visited-date")),
currentDateStamp = Date.now();
$(function () {
var dateformate = localStorage.getItem("selectedFormat");
alert(dateformate);
});