Does V8 automatically parse ascii characters from strings? - javascript

I noticed some inconsistencies in Chrome vs. Firefox. I was basically trying to create a new date from a string I scraped off the Dom.
// Assume dateString was pull from a Dom node.
var dateString = 'Nov\xa025, 2013';
var date = new Date(dateString);
You will notice that dateString contains the ascii non-breaking space character in it. So when ran in the Chrome console, date == valid date. Firefox on the other hand doesn't like the ascii character and date != valid date.
The remedy would be to just replace the ascii with an actual space. I am curious as to if V8 is doing this cleaning of string for us, not just for new Date()?

No, both browsers parse string literals identically:
> 'Nov\xa025, 2013'.charCodeAt(3)
160
> 'Nov 25, 2013'.charCodeAt(3)
32
However, the Date constructors differ between the browsers. The EMCAScript specification requires only one date format (namely, YYYY-MM-DDTHH:mm:ss.sssZ) but custom date formats may be freely supported by an implementation:
If the String does not conform to that [ECMAScript-defined] format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
Apparently Chrome supports a custom date format that allows non-breaking spaces, where Firefox does not.

It leaves the string as is, you can try
dateString.charCodeAt(3)
to confirm that.

Related

JS Date() - Leading zero on days

A leading zero for the day within a string seems to break the Javascript Date object in Chrome. There are also some inconsistencies between browsers, since Firefox handles the leading zero correctly, but fails when the zero is not included. See this example: https://jsfiddle.net/3m6ovh1f/3/
Date('2015-11-01'); // works in Firefox, not in Chrome
Date('2015-11-1'); // works in Chrome, not in Firefox
Why? Is there a good way to work around/with the leading zero?
Please note, the strings are coming from MySQL via AJAX and all dates will contain the leading zero, and I can fix this by formating the dates server-side. What format would work the best?
EDIT
Just to specify what my problem was, it looks like Chrome is applying a time zone to the YYYY-MM-DD format, which reverts the Nov. 1st date back to the Oct. 31st date (because of my EDT local time).
According to ECMA-262 (5.1):
The function first attempts to parse the format of the String according to the rules called out in Date Time String Format (15.9.1.15). If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
The date/time string format as described in 15.9.1.15 is YYYY-MM-DDTHH:mm:ss.sssZ. It can also be a shorter representation of this format, like YYYY-MM-DD.
2015-11-1 is not a valid date/time string for Javascript (note it's YYYY-MM-D and not YYYY-MM-DD). Thus, the implementation (browser) is able to do whatever it wants with that string. It can attempt to parse the string in a different format, or it can simply say that the string is an invalid date. Chrome chooses the former (see DateParser::Parse) and attempts to parse it as a "legacy" date. Firefox seems to choose the latter, and refuses to parse it.
Now, your claim that new Date('2015-11-01') doesn't work in Chrome is incorrect. As the string conforms to the date/time string format, Chrome must parse it to be specification compliant. In fact, I just tried it myself -- it works in Chrome.
So, what are your options here?
Use the correct date/time format (i.e. YYYY-MM-DD or some extension of it).
Use the new Date (year, month, date) constructor, i.e. new Date(2015, 10, 1) (months go from 0-11) in this case.
Whichever option is up to you, but there is a date/time string format that all specification compliant browsers should agree on.
As an alternative, why not use unix timestamps instead? In JavaScript, you would would multiply the timestamp value by 1000,
e.g
var _t = { time: 1446220558 };
var _d = new Date( _t.time*1000 );
Test in your browser console:
new Date( 14462205581000 );
// prints Fri Oct 30 2015 11:55:58 GMT-0400 (EDT)
There's a little benefit in it as well (if data comes via JS) - you'd save 2 bytes on every date element '2015-10-30' VS 1446220558 :)

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 to deserialize JSON text into a date type using Windows 8 JSON.parse?

I'm building a Windows 8 Metro app (aka "Modern UI Style" or "Windows Store app") in HTML5/JavaScript consuming JSON Web Services and I'm bumping into the following issue: in which format should my JSON Web Services serialize dates for the Windows 8 Metro JSON.parse method to deserialize those in a date type?
I tried:
sending dates using the ISO-8601 format, (JSON.parse returns a string),
sending dates such as "/Date(1198908717056)/" as explained here (same result).
I'm starting to doubt that Windows 8's JSON.parse method supports dates as even when parsing the output of its own JSON.stringify method does not return a date type.
Example:
var d = new Date(); // => a new date
var str = JSON.stringify(d); // str is a string => "\"2012-07-10T14:44:00.000Z\""
var date2 = JSON.parse(str); // date2 is a string => "2012-07-10T14:44:00.000Z"
Here's how I got this working in a generic way (though it I'd rather find a format supported out-of-the-box by Windows 8's JSON.parse method):
On the server, I'm serializing my strings using:
date1.ToString("s");
This uses the ISO 8601 date format which is always the same, regardless of the culture used or the format provider supplied (see here for more information).
On the client-side, I specified a "reviver" callback to JSON.parse which looks for dates using a regexp and converts them into a date object automatically.
In the end, the deserialized object will contain actual JavaScript date types and not strings.
Here's a code sample:
var responseResult = JSON.parse(request.responseText, function dateReviver(key, value) {
if (typeof value === 'string') {
var re = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)$/
var result = re.exec(value);
if (result) {
return new Date(Date.UTC(+result[1], +result[2] - 1, +result[3], +result[4],+result[5], +result[6]));
}
});
Hope this helps,
Carl
This is not something that's unique to Windows 8's JSON.parse – it's the by-design behavior of the ECMA standard JSON parser. Therefore, there is (and can be) no "out-of-the-box support" for dates.
Per spec, JSON values can only be a String, Number, Boolean, Array, Object, or null. Dates are not supported. (IMO, this is an oversight on the part of the spec, but it's what we have to live with.)
Since there is no date type, your app has to work out how to handle dates on its own. The best way to handle this is to send dates as ISO 8601 strings (yyyy-MM-dd'T'HH:mm:ss'Z') or as milliseconds since the epoch (Jan 1 1970 00:00:00 UTC). The important part here is to make sure time is in UTC.
If performance is important, I would not use a reviver callback with JSON.parse. I did a lot of testing, and the overhead involved with invoking a function for every single property in your object cuts performance in half.
On the other hand, I was honestly surprised with how well testing a regex against every string value stood up against only parsing known property names. Just make sure you define the regex once, outside the loop!
Obviously, the absolute fastest ways to turn JSON values into Dates is if you know exactly what properties need to be parsed for dates. However, given the surprisingly good performance of the regex-based search methods, I don't think it's worth the extra complexity unless you really need the extra performance.
A note on using ISO strings vs milliseconds since epoch: tested independently, milliseconds wins. In IE, there's no difference, but Firefox really seems to struggle with ISO strings. Also note that the Date constructor takes milliseconds in all browsers. It also takes a the ISO string, but not in IE ≤ 8.

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]);
}

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