Why does parsing a locale date string result in an invalid date? - javascript

Can someone explain why the following snippets result in an invalid date object?
new Date(new Date().toLocaleString())
// or
Date.parse(new Date().toLocaleString())

This is expressly permitted by the ES5 specification's definition of Date.parse (emphasis mine):
...all of the following expressions should produce the same numeric value in that implementation, if all the properties referenced have their initial values:
x.valueOf()
Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())
However, the expression
Date.parse(x.toLocaleString())
is not required to produce the same Number value as the preceding three expressions and, in general, the value produced by Date.parse is implementation-dependent when given any String value that does not conform to the Date Time String Format (15.9.1.15) and that could not be produced in that implementation by the toString or toUTCString method.
Since toLocaleString is not required to produce a string conformant to the Date Time String Format YYYY-MM-DDTHH:mm:ss.sssZ, it is allowable for its output not to be parsed correctly by Date.parse.

new Date().toLocaleString() returns the current date in a format new Date() can't parse, resulting in unexpected dates.

Related

Difference in new Date() output in Javascript

I tried with two methods to generate Date first by passing whole date string and second with year, month, day combination. But I am getting different outputs while the same date is being provided. The Day is not right. It should be 30 June in the first too.
const oldDate = new Date('2020-06-30');
const newDate = new Date('2020', '05', '30');
console.log(oldDate.toString(), newDate.toString());
When you instantiate a Date by passing a string, it's supposed to be a full ISO 8601 string which specifies the time zone. As you dont specify it, it takes GMT+0, and you seem to be located at GMT-7. You should write this instead:
console.log(new Date('2020-06-30T00:00:00-07:00').toString());
The Date constructor that accepts multiple arguments expects them to be numbers, and accepts the month number as a 0-based value (0 = January). The values are expected to be in local time.
The Date constructor accepting a single string argument parses the string according to the specified rules (which apply to your example) and, possibly, unspecified fallback rules the JavaScript engine implementer chose to add (in your case, though, the fallback isn't necessary). When there's no timezone indicator on the string, Date-only forms such as yours are parsed in UTC (date/time forms are parsed in local time).
(The Date constructor accepting a single number expects that number to be milliseconds-since-The-Epoch [Jan 1st, 1970 at midnight, UTC].)
Below format is considered as GMT time and it tries to convert to your local timezone. That's why you notice 7 hours subtracted.
new Date('2020-06-30')
whereas,
Below format is considered as local timezone and no further conversion happen.
new Date('2020', '05', '30');
According to MDN docs:
dateString
A string value representing a date, specified in a format recognized by the Date.parse() method. (These formats are IETF-compliant RFC 2822 timestamps, and also strings in a version of ISO8601.)
Note: Parsing of date strings with the Date constructor (and Date.parse(), which works the same way) is strongly discouraged due to browser differences and inconsistencies.
Support for RFC 2822 format strings is by convention only.
Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
Therefore, when you create date via new Date("2020-06-30") it creates date object in 0 timezone and adjusts time to show it equal to your time zone.

new Date() producing valid date from invalid input string [duplicate]

This question already has answers here:
Detecting an "invalid date" Date instance in JavaScript
(52 answers)
Closed 3 years ago.
When I pass "test 2" string in new Date(), I am getting an actual date, how?
I am trying to whether it is a date or not.
console.log(new Date("test 2"));
Passing a string to new Date is the same as using Date.parse.
When a non-standard date string is passed, the result is implementation-dependent; the browser can do whatever it wants, including guessing. On Chrome, your input results in a date, but not on Firefox (NaN is returned).
test isn't part of a date string, so it looks like Chrome just parses the 2:
console.log(new Date('2'));
console.log(new Date('1'));
console.log(new Date('0'));
Essentially, this is undefined behavior, so strange results aren't surprising. Unless the passed string conforms to the format defined in the specification - that is, something like "2011-10-10" or "2011-10-10T14:48:00" or "2011-10-10T14:48:00.000+09:00", the results are unpredictable.
Consider instead figuring out what sort of string format you'd be expecting as an input, and then checking if the format is followed with a regular expression. If so, pass to new Date and see if it gives you a meaningful results; otherwise, don't.
As per MDN:
The ECMAScript specification states: If the String does not conform to the standard format the function may fall back to any implementation–specific heuristics or implementation–specific parsing algorithm.
Google Chrome tries to parse your date and picks up the number as a month. Other browsers may reject the passed value or return something totally different.
Hence please consider the following note:
Parsing of date strings with the Date constructor (and Date.parse(), which works the same way) is strongly discouraged due to browser differences and inconsistencies.
MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Parameters
From mdn:
A string representing a simplification of the ISO 8601 calendar date extended format (other formats may be used, but results are implementation-dependent).
You're encountering an implementation-specific attempt to parse your string as a date. It is not recommended to depend on this behaviour.
Because your test text includes a number. See, it's interpreting a number like 1 as January, 2 as February,3 as March, and so on.
new Date( "3")
will give you
Thu Mar 01 2001 00:00:00 GMT+0530 (India Standard Time)
If you use text with no number, e.g. new Date("test") it will throw invalid date.

Why can i parse invalid date string? [duplicate]

This question already has answers here:
Why does Date.parse give incorrect results?
(11 answers)
Closed 3 years ago.
I use a function that check if entered value is a valid text for specific purpose in my application.
valid value is a string where it's not valid date or number neither true or false.
checkText(str) {
return isNaN(str) && isNaN(Date.parse(str)) && ['true', 'false'].indexOf(str) == -1;
}
It works properly, but i faced an issue with this string: "New Item 3".
Date.parse("New Item 3") returns a number, but why!!? also, if you changed 3 into any number less than 13 it will return number!
Anyone here can explain to me what happens?
Lesson learned: Date.parse is not a date validator.
Even MDN says:
It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated).
And further down
The ECMAScript specification states: If the String does not conform to the standard format the function may fall back to any implementation–specific heuristics or implementation–specific parsing algorithm. Unrecognizable strings or dates containing illegal element values in ISO formatted strings shall cause Date.parse() to return NaN.
However, invalid values in date strings not recognized as simplified ISO format as defined by ECMA-262 may or may not result in NaN, depending on the browser and values provided
In fact the problem here is coming from Date.parse() method, if you check:
Date.parse("New Item 3");
It will return:
983401200000
console.log(Date.parse("New Item 3"));
So the fact here is that Date.parse() will behave according the browser specifications and may or not return a Number. It depends on the browser.
And you can see from the Date.parse() MDN reference that:
The ECMAScript specification states: If the String does not conform to the standard format the function may fall back to any implementation–specific heuristics or implementation–specific parsing algorithm. Unrecognizable strings or dates containing illegal element values in ISO formatted strings shall cause Date.parse() to return NaN.
However, invalid values in date strings not recognized as simplified
ISO format as defined by ECMA-262 may or may not result in NaN,
depending on the browser and values provided.

Parsing ISO8601-like date in JavaScript: new Date() doesn't work across browsers

How do I convert a date string coming from a database into a new Date() object?
If I do the following:
var x = new Date('2013-11-05 11:01:46:0');
alert(x);
It works in Chrome, but in Safari it gives me the string "Invalid Date".
Here's the fiddle.
The format of strings accepted by new Date(string) is implementation-dependent. If the browser correctly implements the ES5 specification, however, a strict subset of legal ISO 8601 strings should be accepted. Basically, you need to use UTC instead of local time, put a "T" instead of a space between the date and time, use a decimal point instead of a colon between integral and fractional seconds, and append a "Z" on the end of the whole thing:
2013-11-05T11:01:46.000Z
Perhaps you can get your database to output the dates in that format; otherwise, you should look into a third-party library, such as moment.js.

How can I parse this date string consistently across browsers?

I'm using Javascript's Date object to parse a string into a milliseconds timestamp. I'm using Date.parse(), and the strings I'm parsing are of the following format: "2012-07-06 12:59:36-0600"
Date.parse performs nicely in Chrome, parsing into the correct timestamp I'd anticipate. However, every other browser returns "NaN" when I run the string through Date.parse().
I know that the Date object implementation is browser-specific, but I'd like to find a javascript solution that's capable of parsing strings of this type for any browser. Any suggestions on what else I could use in Javascript to achieve this?
Convert the input to valid ISO 8601:
Date.parse("2012-07-06 12:59:36-0600".replace(' ', 'T'));
This was tested (and works) in Firefox.
Note:
Note that while time zone specifiers are used during date string
parsing to properly interpret the argument, they do not affect the
value returned, which is always the number of milliseconds between
January 1, 1970 00:00:00 UTC and the point in time represented by the
argument.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/parse
Have you tried DateJS? Maybe you don't want to add another library, but it will solve your crossbrowser problem.
If the format is consistent, you can parse it yourself:
var date = "2012-07-06 12:59:36-0600";
function parseDatetime(input) {
var match = input.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})([-+]\d{4})/);
match.shift(); // discard the "full match" index
match[2]--;
match[4] += parseInt(match[6],10);
return new Date(match[0],match[1],match[2],match[3],match[4],match[5]);
}

Categories

Resources