I have this very simple function that doesnt work on Firefox or IE. Just wondering if you have some insight.
function compareDates(obj, fecha){
var date1 = new Date( Date.parse(obj.value.replace(/-/g, " ")) );
var date2 = new Date( Date.parse(fecha.value.replace(/-/g, " ")) );
if(date1 < date2){
alert("Invalid Date");
}
}
This function receives a 10-JUL-13 and a 20-JUL-13, for examples.
In IE, I don't get the alert, in Chrome, I do get the alert. Please see http://jsfiddle.net/ZDtVv/
Date.parse requires an ISO date, which requires the full year. Chrome and Firefox try to figure it out for you, you shouldn't rely on that.
// This works
compareDates({value: '10-JUL-2013'}, {value: '20-JUL-2013'})
See http://jsfiddle.net/ZDtVv/1/
Those date strings are not valid date strings, so you get Date objects that have NaN as their actual timestamp. And NaN < NaN tests false.
Per spec, behavior for invalid date strings is undefined; a JavaScript implementation can turn them into NaN or use whatever heuristics it wants to for parsing them. For example, those dates could be year 13 or year 1913 or year 1413 and those would all be valid behaviors per spec.
Related
I am allowing the user to add a date manually in the date field.
If the user enters the date as 1/1/13 I am expecting a result as 01/01/2013.
This is what I am using.
Code:
moment("1/1/13").format('MM/DD/YYYY')
In chrome it is working fine but not working in FF and IE it shows 01/01/1913 instead of 01/01/2013.
Fiddle
You need to give moment the format of the data it's parsing, using moment(string, string). In fact, if you look in your web console, moment is telling you that:
Deprecation warning: moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.
So:
moment("1/1/13", "M/D/YY").format("MM/DD/YYYY");
// ^^^^^^^^^^----- the format to parse with
...assuming the date is in month/day/year order (since that's what you're outputting).
Example (I've changed the date slightly so we can tell days from months):
console.log(moment("1/2/13", "M/D/YY").format("MM/DD/YYYY"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
In a comment you've said:
I am allowing them to add mm/dd/yyyy and mm/dd/yy format. this is not working for 1/1/1999
See the docs linked above, if you want to support a variable number of digits in the year, use YYYY for the year:
console.log(moment("1/2/13", "M/D/YYYY").format("MM/DD/YYYY"));
console.log(moment("1/2/1999", "M/D/YYYY").format("MM/DD/YYYY"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
This is because Moment.js uses the Date object when creating a new moment, and unfortunately that works differently in Firefox and Chrome.
To test it simply try creating a new date in both browsers.
new Date('1/1/13');
Frankly, I am surprised that Chrome interprets this as 2013. To be safe and cross-browser compliant, just write out the full year. If you are getting this from an outside source, you should simply be able to parse it and reformat it to a safer shortened ISO format like so:
dateString.replace(/^(\d\d?)\/(\d\d?)\/(\d\d{2,4})$/, (day, month, year) => {
day = day.length === 1 ? '0' + day : day;
month = month.length === 1 ? '0' + month : month;
year = year.length === 2 ? '20' + year : year;
if (year.length === 3) {
throw new Error('Invalid date format. Year must either be 2 or 4 characters long.);
}
return [day, '-', month, '-', year].join('');
};
It's working perfectly in Chrome and Mozilla
moment(`${day}/${month}/${year}`, "DD/MMM/YYYY").format("MMMM/DD/YYYY");
//January/01/2021
If you take the following:
var s = "2/8888/2016";
var d = new Date(s);
alert(d);
In Chrome, you'll get:
Invalid Date
But in IE and Firefox, you'll get:
Fri Jun 01 2040 00:00:00 GMT-0500 (Central Daylight Time)
It appears to be just adding 8888 days to Feb 01. Instead, I would expect the date to be considered invalid. Is there a way I can make FireFox and IE think this date string is invalid?
Short answer:
It's a misbehaviuor of the browsers you're mentioning.
You have to check date is in correct format on your own. But it's quite trivial, I suggest this approach:
Split the date in year y, month m, day d and create the Date object:
var date = new Date( y, m - 1, d ); // note that month is 0 based
Then compare the original values with the logical values obtained using the Date methods:
var isValid = date.getDate() == d &&
date.getMonth() == m-1 &&
date.getFullYear() == y;
Before doing all of this you may want to check if the date string is valid for any browser:
Detecting an "invalid date" Date instance in JavaScript
Long answer:
Firefox (and IE) accepting "2/8888/2016" as a correct string sate format seem to be a bug / misbehaviour.
In fact according to ECMAScript 2015 Language Specification when Date() is invoked with a single string argument should behave just as Date.parse()
http://www.ecma-international.org/ecma-262/6.0/#sec-date-value
The latter
attempts to parse the format of the String according to the rules (including extended years) called out in Date Time String Format (20.3.1.16)
..that is specified here
http://www.ecma-international.org/ecma-262/6.0/#sec-date-time-string-format
where you can read
The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
[...]
MM is the month of the year from 01 (January) to 12 (December).
DD is the day of the month from 01 to 31.
It seems that Firefox is interpreting the string value as when Date() is invoked with multiple arguments.
From
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
Note: Where Date is called as a constructor with more than one argument, if values are greater than their logical range (e.g. 13 is provided as the month value or 70 for the minute value), the adjacent value will be adjusted. E.g. new Date(2013, 13, 1) is equivalent to new Date(2014, 1, 1), both create a date for 2014-02-01 (note that the month is 0-based). Similarly for other values: new Date(2013, 2, 1, 0, 70) is equivalent to new Date(2013, 2, 1, 1, 10) which both create a date for 2013-03-01T01:10:00.
This may explain how "2/8888/2016" turns into 2040-05-31T22:00:00.000Z
There's no way to make IE and FF think it's invalid, except:
you could change their javascript implementations
you use a library instead to deal with that.
We can also expect that Javascript, as a language, evolves and we can cross our fingers that browsers decide to follow a more strict specification. The problem of course is that every "fix" must be also backward compatible with previous versions of the language (does not happen always, Perl for example).
So the best thing by now is to use some library just like momentjs as suggested by Derek in the post comments.
You have stumbled across yet another reason why you should manually parse date strings.
When Date is provided a single string argument, it is treated as a date string and parsed according to the rules in Date.parse. The rules there first attempt to parse it as an ISO 8601 format string. If that doesn't work, it may fall back to any parsing algorithm it wants.
In the case of "2/8888/2016", browsers will first attempt to parse it as an ISO format and fail. It seems from experimentation that IE and Firefox determine that the string is in month/day/year format and effectively call the Date constructor with:
new Date(2016,1,8888);
However, other browsers may attempt to validate the values and decide that 8888 is not a valid date or month, so return an invalid date. Both responses are compliant with ECMA-262.
The best advice is to always manually parse date strings (a library can help, but generally isn't necessary as a bespoke parse function with validation is 3 lines of code) then you can be certain of consistent results in any browser or host environment.
I want to put the following string: '10-10-2013 03:04' in a Date object.
It's working in Chrome but Firefox tells me it's an invalid Date. (I guess they mean format?)
I tried to use Date.parse on it but that makes it a NaN.
What to do?
UPDATE:
I used the answer of thefourtheye, but now Chrome actually says it's an invalid date ..
var dateString = '10-10-2013 03:04';
dateString = dateString.replace(/-/g, ' ');
var DateToUse = new Date(dateString);
Returns an invalid date in Chrome.
<script>
var myDate = new Date("10 10 2013 03:04");
console.log(myDate);
</script>
According to the standard, https://www.rfc-editor.org/rfc/rfc2822#page-14, space can be used to separate date, month and year. The above example works perfectly in Chrome and Firefox.
I've been banging my head over this one all day. No matter how I initialize a Javascript Date I cannot seem to get a valid Date object... I'm assuming the Date is invalid and not working properly by inspecting it with Chrome's debugger, which has the value '__proto__: Invalid Date'.
I've tried all of the following:
var d = new Date();
var d = new Date('2012-10-08');
var d = new Date('2012-10-08 00:00:00');
var d = new Date(Date('2012-10-08'));
var d = new Date(Date.parse('2012-10-08'));
var d = new Date(2012,10,08);
var d = new Date("October 13, 1975 11:13:00");
Along with countless other attempts.
This is presenting a problem in iOS where I'm trying to get values from these Date objects but every function just returns NaN. I'd prefer to avoid having to use external libraries or have to convert YYYY-MM-DD format into any other format since I'm trying to get this to work with an HTML5 input type="date" with minimal code for a mobile site.
Essentially this boils down to: What are the parameters that make a Date object valid?!
Do not trust the Date object to parse strings, you must do it manually. Given the format 2012-10-08,
function stringToDate(s) {
s = s.match(/\d+/g);
if (s) {
return new Date(s[0], --s[1], s[2]);
}
}
You may want to do some validation of the input string and the resulting date object, the above just shows the conversion.
Edit
BTW, the only string format that seems to be parsed consistently in all browsers is the US-specific month/date/year format. There is no specification to support its use, nor is there any reason to believe browsers will continue to support it other than pragmatism and "legacy" reasons.
For the vast majority of regions, '2/3/2012' is interpreted as 2 March, so getting 3 February might be unexpected.
Once older versions of IE are no longer in use (probably a few years yet), it should be safe to use the ISO8601 extended format per ECMA-262. However, even browsers that support it are inconsitent. e.g given:
new Date('2011-02-29');
Firefox 15 returns 'Invalid Date', IE 9 and Chrome 22 return a date object for 1 March, 2011.
There are three ways of calling the method:
The number of milliseconds from the epoch:
new Date(milliseconds)
Any IETF-compliant RFC 2822 timestamp:
new Date("November 2, 1988 10:00:00");
Individual args:
new Date(year, month, day [, hour, minute, second, millisecond])
new Date(1988,11,02,10,0,0);
If your main concern is about parsing, have a look at Moment.js which is clearly superior to parsing things yourself. (IMHO)
Turns out jQuery doesn't bind the .change() event to input type="date" properly in iOS. Changed the event to .blur() and everything seems to work now. However, it still seems it is impossible to create a valid date object in Chrome... an issue for another day.
Thanks for the help everyone!
I have a date string "2011-11-24T09:00:27+0000" fetched from the graph.facebook API.
When I run
var timestamp = Date.parse(facebookDate);
in chrome. I get a timestamp that relates to the date! perfect!
But in EVERY other major browser... I get "NaN" !!! ?
Surely all these browsers use the same javascript parse function right?
Can anybody explain why the same javascript function give different results?
And can anybody also tell me how to fix this issue...
Thanks in advance
Alex
Here is a fix for Firefox and IE/Safari (with the help from JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse
) :
DEMO
var noOffset = function(s) {
var day= s.slice(0,-5).split(/\D/).map(function(itm){
return parseInt(itm, 10) || 0;
});
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
var offsetString = s.slice(-5)
var offset = parseInt(offsetString,10)/100;
if (offsetString.slice(0,1)=="+") offset*=-1;
day.setHours(day.getHours()+offset);
return day.getTime();
}
From MDN
JavaScript 1.8.5 note
A subset of ISO 8601 formatted date strings can now also be parsed.
Alternatively, the date/time string may be in ISO 8601 format. Starting with JavaScript 1.8.5 / Firefox 4, a subset of ISO 8601 is supported. For example, "2011-10-10" (just date) or "2011-10-10T14:48:00 (date and time) can be passed and parsed. Timezones in ISO dates are not yet supported, so e.g. "2011-10-10T14:48:00+0200" (with timezone) does not give the intended result yet.