getDay() errors with Invalid Date in some browsers - javascript

I have the following string: "2012-12-10T23:40:41Z"
My goal is to get the day as a number (0-6)... sun-sat
I pass this string as follows:
var input = "2012-12-10T23:40:41Z";
var day = new Date(input).getDay();
alert(day);
This works just fine in Chrome, but in the adobe air webkit view, it errors with, "Invalid Date"
Any suggestions on finding a way to get the day that is supported by older browsers?

Prior to ES5, there was no standard way of parsing a date (each host implemented their own way of parsing). Since ES5, dates must be in the ISO8601 format in order to be parseable in strict mode.
For maximum portability, you should parse the date manually.

More of a comment.
To manually parse a javascript ISO8601 date string, split it into parts and pass it to the date constructor. Note that javascript date strings should always be UTC (Z), so:
function parseISOdateString(s) {
s = s.split(/\D/);
return new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5]))
}
You can add bells and whistles to the above to validate the string and the resultant date object if you like.
Note that according to ES5, invalid date strings given to Date.parse (e.g. 2012-12-00) should return NaN, but some browsers will create a date object for 2012-11-30. The above will return a date object for invalid strings, so if consistency with the spec is required:
function parseISOdateString(s) {
s = s.split(/\D/);
var d = new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5]))
return (d.getUTCFullYear() == s[0] && d.getUTCDate() == s[2])? d : NaN;
}
That will return NaN for invalid strings like "2012-12-00"

This page should prove helpful, even though it is a bit old. The issue is that ISO 8601 style dates only got support in Javascript 1.8.5.

Related

Why moment(date).isValid() returns wrong result

when I check the following date it returns true result, Why?
const value = "3";
if (moment(new Date(value), "DD-MM-YYYY HH:mm", true).isValid()) // true
{ }
or
const value = "3";
if (moment(new Date(value)).isValid()) // true
{ }
That is because new Date("3") is valid date and
console.log(new Date("3"))
This is one of those cases that shows you need to sanitize your date strings and should not depend on the native parser, unless you are sure your strings have already been validated and are conformant.
ECMA-262 Date(value) constructor specs
Date.parse
If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
So it's not conformant to "Date Time String Format", which requires the string to start with "YYYY", so it goes to an implementation specific parsing that is similar to the rules for above, but using the form: "MM-DD-YYYY".
The purpose of using strict mode (setting third argument of moment() to true) is to let moment do the string parsing and determine if it fits the formats that you provide (to for example avoid unexpected parsing behavior like this). If you use Date() to parse, you are no longer using moment's strict mode to validate the string fits your required format.
let value = "3";
function checkDate(value){
console.log(value,
moment(value, "DD-MM-YYYY HH:mm", true).isValid() ? 'valid' : 'invalid')
}
value = "01-01-2011 11:22"
checkDate(value)
value = "01-01-2011 11:22Z"
checkDate(value)
value = "3"
checkDate(value)
value = new Date("3").toString()
checkDate(value)
value = new Date('INVALID DATE')
checkDate(value)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.25.3/moment-with-locales.min.js" integrity="sha256-8d6kI5cQEwofkZmaPTRbKgyD70GN5mDpTYNP9YWhTlI=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.28/moment-timezone-with-data.js" integrity="sha256-O1PdKrSbpAYWSBteb7yX/CMmHhu3US31mtCbsryGwaY=" crossorigin="anonymous"></script>
If you don't need to validate the date string (for example to prevent unexpected parsing behavior), don't need to worry about non-modern browsers, and really just need to parse conforming Date strings and format to basic string formats, you could just use native Date() with Intl.DateTimeFormat or Date.prototype.toLocaleString.
TL;DR the way you are using it right now implies that you don't actually need moment
Because 3 is a valid Date, the Date also supports only the year or only month format.
If you try new Date("YYYY") --> It's a valid date
If you try new Date("MM") --> It's a valid format
So, for new Date("{1 to 12}") It will accept
For new Date("{13 to 31}") It's invalid
Also, from new Date("{32 to 49}") It considers as year, for two digits it will add the current century that is (2000 + number you specified), for e.g.
new Date("32") is the year 2032 and for new Date("{50 to 99}") it adds in the previous century i.e. (1900 + number you specified), for e.g. new Date("99") is the year "1999"
For three-digit, till "100000" on-wards it's pretty straightforward what input it is will be a year, for e.g. new Date("100") is year 100 and new Date("100000") is the year 100000. The rest are invalid.
The above is valid as of today, instead of taking care of the above information it's always advisable to use Null, NaN, and Undefined values where the date field is not present

Wrong DateTime Conversion in JS [duplicate]

I have some code that tries to parse a date string.
When I do alert(Date("2010-08-17 12:09:36"));
It properly parses the date and everything works fine but I can't call the methods associated with Date, like getMonth().
When I try:
var temp = new Date("2010-08-17 12:09:36");
alert(temp);
I get an "invalid date" error.
Any ideas on how to parse "2010-08-17 12:09:36" with new Date()?
Date()
With this you call a function called Date(). It doesn't accept any arguments and returns a string representing the current date and time.
new Date()
With this you're creating a new instance of Date.
You can use only the following constructors:
new Date() // current date and time
new Date(milliseconds) //milliseconds since 1970/01/01
new Date(dateString)
new Date(year, month, day, hours, minutes, seconds, milliseconds)
So, use 2010-08-17 12:09:36 as parameter to constructor is not allowed.
See w3schools.
EDIT: new Date(dateString) uses one of these formats:
"October 13, 1975 11:13:00"
"October 13, 1975 11:13"
"October 13, 1975"
The following format works in all browsers:
new Date("2010/08/17 12:09:36");
So, to make a yyyy-mm-dd hh:mm:ss formatted date string fully browser compatible you would have to replace dashes with slashes:
var dateString = "2010-08-17 12:09:36";
new Date(dateString.replace(/-/g, "/"));
The difference is the fact (if I recall from the ECMA documentation) is that Date("xx") does not create (in a sense) a new date object (in fact it is equivalent to calling (new Date("xx").toString()). While new Date("xx") will actually create a new date object.
For More Information:
Look at 15.9.2 of http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
I know this is old but by far the easier solution is to just use
var temp = new Date("2010-08-17T12:09:36");
Correct ways to use Date : https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date
Also, the following piece of code shows how, with a single definition of the function "Animal", it can be a) called directly and b) instantiated by treating it as a constructor function
function Animal(){
this.abc = 1;
return 1234;
}
var x = new Animal();
var y = Animal();
console.log(x); //prints object containing property abc set to value 1
console.log(y); // prints 1234
Any ideas on how to parse "2010-08-17 12:09:36" with new Date()?
Until ES5, there was no string format that browsers were required to support, though there are a number that are widely supported. However browser support is unreliable an inconsistent, e.g. some will allow out of bounds values and others wont, some support certain formats and others don't, etc.
ES5 introduced support for some ISO 8601 formats, however the OP is not compliant with ISO 8601 and not all browsers in use support it anyway.
The only reliable way is to use a small parsing function. The following parses the format in the OP and also validates the values.
/* Parse date string in format yyyy-mm-dd hh:mm:ss
** If string contains out of bounds values, an invalid date is returned
**
** #param {string} s - string to parse, e.g. "2010-08-17 12:09:36"
** treated as "local" date and time
** #returns {Date} - Date instance created from parsed string
*/
function parseDateString(s) {
var b = s.split(/\D/);
var d = new Date(b[0], --b[1], b[2], b[3], b[4], b[5]);
return d && d.getMonth() == b[1] && d.getHours() == b[3] &&
d.getMinutes() == b[4]? d : new Date(NaN);
}
document.write(
parseDateString('2010-08-17 12:09:36') + '<br>' + // Valid values
parseDateString('2010-08-45 12:09:36') // Out of bounds date
);
I was having the same issue using an API call which responded in ISO 8601 format.
Working in Chrome this worked:
`
// date variable from an api all in ISO 8601 format yyyy-mm-dd hh:mm:ss
var date = oDate['events']['event'][0]['start_time'];
var eventDate = new Date();
var outputDate = eventDate.toDateString();
`
but this didn't work with firefox.
Above answer helped me format it correctly for firefox:
// date variable from an api all in ISO 8601 format yyyy-mm-dd hh:mm:ss
var date = oDate['events']['event'][0]['start_time'];
var eventDate = new Date(date.replace(/-/g,"/");
var outputDate = eventDate.toDateString();
You can also create single Date object and update it using the static function Date.now() :
<!doctype html>
<html> <head></head>
<body>
<h1 id="datetime"></h1>
<script>
elem_datetime = document.getElementById('datetime');
var date = new Date();
function sometimer()
{
setTimeout(sometimer, 1*1000); // wait 1 second and call again
date.setTime(Date.now());
elem_datetime.innerHTML = date.toDateString() + ' ' + date.toLocaleTimeString();
}
sometimer();
</script>
</body>
</html>
You're not getting an "invalid date" error.
Rather, the value of temp is "Invalid Date".
Is your date string in a valid format?
If you're using Firefox, check Date.parse
In Firefox javascript console:
>>> Date.parse("2010-08-17 12:09:36");
NaN
>>> Date.parse("Aug 9, 1995")
807944400000
I would try a different date string format.
Zebi, are you using Internet Explorer?
I recently ran into this as well and this was a helpful post. I took the above Topera a step further and this works for me in both chrome and firefox:
var temp = new Date( Date("2010-08-17 12:09:36") );
alert(temp);
the internal call to Date() returns a string that new Date() can parse.

How to do a date format in Javascript?

I need to understand how to do date formattting in javascript.
i have date as,
var date="12/02/1994";// dd/mm/yyy
var date1=new Date(date);
date1.getDate();// this gives me Month which is 02
date1.getMonth();// this gives me date which is 12.
How do i get the exact date i have in var date in get date and getmonth function? Please help
The answer is pretty simple: JavaScript uses mm/dd/yyyy data format.
It doesn't support dd/mm/yyyy format, so, if you need to parse this format, then you will have to do this manually like this:
function parseDdmmyyyy(str)
{
var spl = str.split('/');
return new Date(spl[2], spl[1] - 1, spl[0]);
}
or you will have to use external libraries like Moment.js.
Javascript date() expects date in mm/dd/yy and not in dd/mm/yy. And months start from 0 and not 1.
var from = "12/02/1994".split("/");
var date1 = new Date(from[2], from[1] - 1, from[0]);
date1.getDate();
date1.getMonth();
Use new Date('02/12/1994'), new Date('1994-02-12') or new Date(1994, 02-1, 12), because in js months start from 0 and american date format is used where month goes first
you can use the simple JS file DateFormat.js which has some very good example through the URL mattkruse (Date Funtion)
from this JS file you can validate the incoming date is a true format even you can add format date within a several ways.
Presumably you want to know how to format strings so they are consistently parsed by browsers. The short answer, is there is no guarantee that any particular string will be correctly parsed by all browsers in use (or perhaps even most).
So the bottom line is: don't parse strings with the Date constructor, ever. It's largely implementation dependent and even the one format specified in ES5 and ECMAScript 2015 is poorly and inconsistently supported.
How browsers treat a string like "12/02/1994" is entirely implementation dependent, however most will treat it as the peculiar US month/day/year format, i.e. 2 December and getMonth will return 11, since months are zero indexed.
So you should always manually parse strings (a library can help, but a simple parsing function is only 2 lines, 3 if validation is required), e.g.
// Parse a date string as d/m/y
// If s is not a valid date, return a Date object with its
// time value set to NaN.
function parseDMY(s) {
var b = s.split(/\D/);
var d = new Date(b[2], --b[1], b[0]);
return d && b[1] == d.getMonth()? d : new Date(NaN);
}
document.write(parseDMY('12/02/1994'));

Date.parse() in safari

I am trying to parse a date in safari so that my website will be compatible with IOS as well as everything else, but when I parse a date, it only returns NaN.
The date that I am trying to parse looks like this:
"2015-06-29T23:59:59"
I've looked around for different ways to do this, but I still haven't found a solution to this problem.
Is there anyone who knows a function that will parse the date in safari or a work-around to this problem?
The original approach was: Date.parse("2015-06-29T23:59:59");
Thanks.
The only reliable way to parse a date string is to do it manually, do not rely on Date.parse or passing strings to the Date constructor (which is essentially the same thing).
Before ECMAScript ed 5 (ES5), parsing of strings was entirely implementation dependent. ES5 specified various ISO formats, however there were further changes to parsing with ed 6, so even ISO formats are unreliable and may return local, UTC or NaN dates.
The string "2015-06-29T23:59:59" will be parsed as UTC under ES5, local under ed 6 and before then anything goes (IE8 returns NaN, other browsers from that era may too).
A simple parser, assuming es 6 behaviour and local timezone is:
function parseISO(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);
}
Validating the values and ensuring 2 digit years requires a couple more lines:
function parseISO(s) {
var b = s.split(/\D/);
var d = new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);
d.setFullYear(b[0]);
return d && d.getMinutes() == b[4] && d.getMonth() == b[1]-1 && d.getDate() == b[2]? d : new Date(NaN);
}
According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse safari should work with
Date.parse("2015-06-29T23:59:59");
Perhaps post a code snippet that returns NaN, you may be doing something wrong
Having said that, the following may help if safari in IOS is different to the safari referred to in the MDN article
function parseDate(s) {
var dateTime = s.split('T');
var dateBits = dateTime[0].split('-');
var timeBits = dateTime[1].split(':');
return new Date(dateBits[0], parseInt(dateBits[1]) - 1, dateBits[2], timeBits[0], timeBits[1], timeBits[2]).valueOf();
}
parseDate("2015-06-29T23:59:59");
Returns the same value as
Date.parse("2015-06-29T23:59:59");
In firefox, so, that's a start I guess

javascript giving wrong date after conversion from string to date in IE 8

I'm having date from my app in the format eg.
2013-05-01T00:00:00
when i'm converting this to Date
var d = '2013-05-01T00:00:00'
var result = new Date(d);
getting result as NaN
when i do,
var result = new Date(d.replace(/-/g, '/'));
getting result as,
Tue Apr 30 22:30:00 UTC+0530 2013
what could be the reason that i'm getting date 1 day before..
You should always parse date strings yourself, browsers are notoriously bad at it. For examle, some browsers will treat '2013-05-01T00:00:00' as UTC and others as local. It should be treated as UTC (since the timezone is missing), so:
function parseDateString(s) {
s = s.match(/\d+/g);
return new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5], (s[6] || 0));
}
which will create a date object using the above values as UTC and with a timezone offset based on current system settings. So if your current timezone is UTC+0530, you should get the equivalent of:
2013-05-01T05:30:00+0530
however you seem to be getting a value for UTC-0130. I have no clue about that.
Oh, when you do:
new Date(d.replace(/-/g, '/'));
you are totally mangling the string so it is not an ISO 8601 string and you are completely at the mercy of an implementation dependent date parser (i.e. every implementation may be different, if that's possible).

Categories