Problems during Date Time comparison in JavaScript - javascript

I have a scenario where i have to compare two DateTime objects
Start DateTime and End DateTime
EndDatetime should be greater than StartDateTime
EndDateTime should be greater than CurrentTime
Now i am trying with simple code as suggested in many of sites and blogs, using ">" or "<" symbols.
E.g: if((Date.parse(startdate)) > (Date.parse(enddate)))
{
alert("Please enter enddate greater than startdate");
}
This works fine if DateTime is in same Month. Even after entering valid datetime range like start datetime being Feb 20th 2011 and End datetime being March 3rd 2011, i still get above alert which is actually wrong.
Can anyone please help, in figuring what is wrong or any one who can provide JS function to compare two DateTime objects.
Thanks.

You should use ".getTime()" to get the timestamp integer and then comparing those.
if(Date.parse(startdate).getTime() > Date.parse(enddate).getTime())
{
alert("Please enter enddate greater than startdate");
}
My guess is that when you try to compare the objects themselves, only their string representations get compared lexicographically (not 100% sure about this though).

Related

Javascript date conversion is adding an hour from 0200 to 0300 on Daylight Savings Time. I want to prevent that from happening

I hit a recent problem where I'm validating dates to make sure a start date is not greater than an end date. The dates entered are
start: 3/13/2022 02:30
end: 3/13/2022 03:15
When I convert these to dates in my code an extra hour is applied to the start date making it 03:30.The end date converts as expected and remained 03:30. Because of this my validation is getting hit and we see an error stating "start date cannot be greater than end date".
Am I missing something or how do I prevent this hour from being added?
I've tried changing the format of the date, but that didn't seem to make a difference.
I think it depends on your system's local timezone, to compare those two dates, have you tried to convert them to timestamp ?
Maybe you could log the dates to the console using the date.toISOString() to see what they look like when converted to utc+0

Comparing dates in Javascript for fullcalendar [duplicate]

This question already has answers here:
JavaScript Date Object Comparison
(7 answers)
Closed 2 years ago.
I'm trying to check dates in Javascript for a calendar (fullcalendar), essentially I just want it to not be able to choose past dates:
dateClick: function(info) {
var today = Date.now();
var check = new Date(info.dateStr)
if(check < today)
{
alert('You cannot request dates in the past');
return;
}
else
{
alert('this is the future');
}
},
I'm getting some odd results in that, it seems to calculate the past fine, but also calculates the current day as the past AS well as tomorrow. The day after tomorrow it calculates as the future. No sure what's going on.
info.dateStr gives the format YYYY-mm-dd.
You should coerce to number using +Date or use .getTime() to make sure you are comparing the numeric timestamp values. You're probably fine since you're using Date.now(), which returns a timestamp.
Parsing using the string parsing for Date is strongly discouraged, due to issues like the one in OP:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
Use Date(yyyy, mm, dd, ...) constructor (which uses local time zone) by parsing string manually instead of built-in Date string parsing (which uses UTC if timezone isn't provided).
Using end of the day by adding 24*60*60*1000 to the getTime() value, as that's most likely what you're expecting (same date as today being past is not what most people usually want).
eg: with date to check 05-29-2020, you actually want anything before 05-29-2020 23:59:999
ie: check=05-29-2020 23:59:999 < today=05-29-2020 22:00:000 === false (not past)
or to put it another way the actual intention when:
05-29-2020 => anything from 05-29-2020 00:00 to 05-29-2020 23:59 => actually same as checking 05-30-2020 00:00 - 1 millisecond
dateClick = function(info) {
var today = Date.now()
var check = (([y,m,d])=>new Date(+y,+m-1,+d))(info.dateStr.split(/\D/)).getTime()
+ 24*60*60*1000-1 // add full day so same date as today is not past
console.log(today,check)
if(check < today)
{
alert('You cannot request dates in the past');
return;
}
else
{
alert('this is the future');
}
}
dateClick({dateStr:'2020-05-28'})
dateClick({dateStr:'2020-05-29'})
dateClick({dateStr:'2020-05-30'})
dateClick({dateStr:'2020-05-31'})
you want to compare dates like this: date1.getTime() - date2.getTime()
also, keep in mind, if your goal is to make sure a user is inputing a date that is not in the past, you can use html5 date input with a min set:
<input type="date" min="2020-05-29">

Moment js Date values comparison across time-zones

I am getting 4 dates as inputs mentioned below from an external source.
Dates with time element:
"InitialDate": "2019-02-19T12:03:22.129Z",
"updateDate": "2019-02-28T05:26:57.115Z",
Dates without time element:
"startDate": "2019-02-18",
"endDate": "2020-02-16",
I am coverting InitialDate and updateDate and creating actualInitDatE out of them using a moment format as below, as they are getting time element also in it.
I don't want time element and i only want date elements of all the 4 dates.
const actualInitDatE = moment(InitialDate).format('MM-DD-YYYY') ||
moment(updateDate).format('MM-DD-YYYY');
Now, I am converting the startDate and endDate which are having only date element in it (and no time element) and finally creating actualStartDate and actualEndDateW variables,
const actualStartDateW = moment(startDate).format('MM-DD-YYYY');
const actualEndDateW = moment(endDate).format('MM-DD-YYYY');
Now I am comparing them with the below logic and is working fine in IST,
if (actualInitDatE >= actualStartDateW && actualInitDatE <= actualEndDateW) {
console.log('Compared and True');
}
My Doubt is will this work correctly in UTC and other time zones as well? I am doubtful because some of the dates have time elements and some of them have only the date elements.
I have gone through this and implemented the approach. Is this approach is correct or do we need to use any offset?
javascript Date timezone issue
Can someone help me in this regard and let me know if this code works across timeZones?
I believe the core issue here is that you must specify a timezone for startDate and endDate. If you don't, moment.js will assume local time, for example IST or let's say you were in the US, Pacific time. The problem with this approach is that the code will give inconsistent results (depending on the machine).
You can demonstrate this by running the snippet below in your browser (Chrome is best) and changing your machine timezone. You'll see that parsing the startDate (and endDate) would result in different times depending on your timezone.
So the combination of a timestamp and a timezone give us a clear, unambiguous point in time for the most robust code. If we don't set a timezone when parsing the start and end date, the code could give a different result depending on the machine it is running on.
The best approach is to specify what timezone the startDate and endDate are in, e.g. are they in IST, or in UTC?
This way you can be sure your dates will parse consistently.
I would also suggest creating a function, say, parseDate that accepts a datestring, a format, and a timezone. This is makes all assumptions clear to anyone who reads the code.
There is no issue with InitialDate or updateDate, since they are specified as UTC times (the Z timezone specifier), so they are both clear and unambiguous.
const dates = {
startDate: "2019-02-18",
endDate: "2020-02-16"
}
const startDateNoTimezoneSpecified = moment(dates.startDate);
console.log("StartDate (No Timezone Specified):", startDateNoTimezoneSpecified.toISOString());
function parseDate(dateString, format, timezone) {
return moment.tz(dateString, format, timezone)
}
// Parse start date, assuming it is in IST (I'm assuimg IST refers to India Standard Time , if it's Israel Standard Time replace with Asia/Jerusalem!
console.log("Parse date result (IST):", parseDate(dates.startDate, "YYYY-MM-DD","Asia/Kolkata").toISOString());
console.log("Parse date result (UTC):", parseDate(dates.startDate, "YYYY-MM-DD","UTC").toISOString());
// You can also use moment.utc instead of moment.tz(date, "UTC").. it's simpler!
const startDateUTC = moment.utc(dates.startDate);
console.log("StartDate (UTC (moment.utc)):", startDateUTC.toISOString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data-1970-2030.js"></script>
You seem to be over complicating things.
Your conversion of UTC timestamps to local dates is OK, but the format doesn't make sense. MM-DD-YYYY is pretty useless for anything, I'd suggest using ISO 8601 YYYY-MM-DD.
Date-only timestamps should be treated as local, so no conversion is necessary for the second two dates. Using ISO 8601 format, the strings can be compared directly:
let initialDate = '2019-02-19T12:03:22.129Z';
let updateDate = '2019-02-28T05:26:57.115Z';
// Get local date in required format
let actualInitDatE = moment(initialDate || updateDate).format('YYYY-MM-DD');
// Use these as they are
let startDate = '2019-02-18';
let endDate = '2020-02-16';
if (actualInitDatE >= startDate &&
actualInitDatE <= endDate) {
console.log('Compared and True');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
You can also keep the values as moment objects after setting them to the start of the day and use various moment methods for comparison, but I think the string version is pretty simple so why make it harder than it has to be?
Whether "this code works across timeZones" is unknown as you haven't explained what you are actually trying to achieve.

javascript Date.parse assumes 31 days in February and all months?

It seems to me that Date.parse assumes all months have 31 days. Including months with 30 days and including February(which should only ever have 28/29 days).
I checked this question 31 days in February in Date object
But the answer there suggested there was nothing wrong with Date in his issue..Somebody said something to the questioner about zero indexing and he pretty much said "oh ok", and determined that it was his mistake and not a mistake of Date.
Another question Date is considering 31 days of month the guy was doing some subtraction was a number of lines of code and he seemed to not put the error down to Date in the end.
But this example that I have seems to be a bit different and more clear cut. It involves Date.parse and can be demonstrated with one/two lines of code.
Date.parse is aware that there are not 32 days in a month, that's good
Date.parse("2000-01-32");
NaN
But In February it thinks there can be 30 or 31 days
Date.parse("2013-02-30");
1362182400000
Date.parse("2013-02-31");
1362268800000
In fact it looks like it thinks all months have 31 days. That is really strange for a method that is meant to parse a date.
And there's no issue of zero indexing here. As Date.parse("...") doesn't use zero indexing (And even if it did, it wouldn't cause it tot make the error of thinking there are 31 days in February - that is more than one off!
Date.parse("01-00-2000");
NaN
Date.parse("00-01-2000");
NaN
According to the specification for Date.parse() (emphasis mine):
The function first attempts to parse the format of the String according to the rules called out in Date Time String Format. […] Unrecognisable Strings or dates containing illegal element values in the format String shall cause Date.parse to return NaN.
And according to the specification for Date Time String Format (emphasis mine):
ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
Where the fields are as follows: […] DDis the day of the month from 01 to 31.
Therefore, any date with a day of month greater than 31 is illegal and Date.parse() returns NaN.
Please notice that the standard defines a date format, not a date: the static method isn't required to make additional verifications, and everything else is implementation-specific. For instance, Date.parse('2013-02-30') and Date.parse('2013-04-31') both return NaN on Firefox.
The implementation differs between browsers. IE, Edge and Chrome will parse strings that doesn't represent actual dates, but Firefox will return NaN for those strings. The safe thing to do is to consider the result from Date.parse as undefined for date strings where the day falls outside the range of the month.
Browsers that allow parsing of non-existent dates will return a different date. Parsing "2015-04-31" will return the date 2015-05-01. This is the same behaviour as when using new Date(2015, 3, 31), where numbers out of range is allowed and will wrap around into a different month or year. That means that the result is still usable, if you don't mind that some invalid dates turn into other dates in some browsers.
The standard isn't very clear about what values are valid:
Illegal values (out-of-bounds as well as syntax errors) in a format
string means that the format string is not a valid instance of this
format.
The day component is defined as having a range from 1 to 31:
DD is the day of the month from 01 to 31.
However, the format is based on ISO 8601, and that is not a format for parsing strings into dates, that is a format for representing dates as string. Clearly you can't represent a date that doesn't even exist as a string.
Right, so how to check if a date string has a valid value?
with moment is very easy:
export function dateStringIsValid(aDateString){
return (moment(aDateString, "DD/MM/YYYY", true).isValid())
}

JavaScript validate existence of date

I have a date in the format YYMMDD. Is there anyway I can validate it in JavaScript?
By validation I don't mean easier things like length, characters etc but rather if the date exists in real life.
I'm hoping there is a faster / better way than breaking it in 3 chunks of 2 characters and checking each individually.
Thank you.
try to convert it to a date and if it fails, you get the dreaded NaN then you know it is not a valid date string? Not Pretty but it should work
var myDate = new Date(dateString);
// should write out NaN
document.write("Date : " + myDate);
You date string would have to be in a valid format for javascript I don't think what you have in your question YYMMDD is supported
The format YYMMDD is not supported by Javascript Date.parse so you have to do some processing of it like breaking it in parts.
I would suggest building a function that splits it in 3 2 char strings and then builds an american style date
MM/DD/YY and try to parse that with Date.parse.
If it returns anything but NaN then its a valid date.
The Date parser in JavaScript is pretty useless. The actual formats it accepts vary greatly across browsers; the only formats guaranteed to work by the ECMAScript standard are whatever formats the implementation's toString and toUTCString methods produce. In ECMAScript Fifth Edition you will also get ISO-8166 format, which is nearer to your format but still not quite.
So, the best solution is usually to parse it yourself.
var y= parseInt(s.slice(0, 2), 10)+2000;
var m= parseInt(s.slice(2, 4), 10)-1;
var d= parseInt(s.slice(4, 6), 10);
var date= new Date(Date.UTC(y, m, d));
Now you've got a Date object representing the input date in UTC. But that's not enough, because the Date constructor allows bogus months like 13 or days like 40, wrapping around. So to check the given day was a real day, convert back to year/month/day and compare:
var valid= date.getUTCFullYear()===y && d.getUTCMonth()===m && d.getUTCDate()===d;

Categories

Resources