40

I'm parsing a date from a JSON event feed - but the date shows "NaN" in IE7/8:

// Variable from JSON feed (using JQuery's $.getJSON)
var start_time = '2012-06-24T17:00:00-07:00';

// How I'm currently extracting the Month & Day
var d = new Date(start_time);
var month = d.getMonth();
var day = d.getDate();

document.write(month+'/'+day);// "6/24" in most browsers, "Nan/Nan" in IE7/8

What am I doing wrong? Thanks!

3

5 Answers 5

69

In older browsers, you can write a function that will parse the string for you.

This one creates a Date.fromISO method- if the browser can natively get the correct date from an ISO string, the native method is used.

Some browsers got it partly right, but returned the wrong timezone, so just checking for NaN may not do.

Polyfill:

(function(){
    var D= new Date('2011-06-02T09:34:29+02:00');
    if(!D || +D!== 1307000069000){
        Date.fromISO= function(s){
            var day, tz,
            rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
            p= rx.exec(s) || [];
            if(p[1]){
                day= p[1].split(/\D/);
                for(var i= 0, L= day.length; i<L; i++){
                    day[i]= parseInt(day[i], 10) || 0;
                };
                day[1]-= 1;
                day= new Date(Date.UTC.apply(Date, day));
                if(!day.getDate()) return NaN;
                if(p[5]){
                    tz= (parseInt(p[5], 10)*60);
                    if(p[6]) tz+= parseInt(p[6], 10);
                    if(p[4]== '+') tz*= -1;
                    if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
                }
                return day;
            }
            return NaN;
        }
    }
    else{
        Date.fromISO= function(s){
            return new Date(s);
        }
    }
})()

Result:

var start_time = '2012-06-24T17:00:00-07:00';
var d =  Date.fromISO(start_time);
var month = d.getMonth();
var day = d.getDate();

alert(++month+' '+day); // returns months from 1-12
Sign up to request clarification or add additional context in comments.

6 Comments

This is returning 5/24 in IE8 instead of 6/24 can you please update the function to work properly???
Didn't change the function, just ++incremented the date.getMonth() in the alert to return a 1 based month.
This works great, thanks you. Would really appreciate it if you could comment the code a bit to help us understand why you've done certain things e.g. +D!==1307000069000
@jackocnr That took me a minute, too. The + casts D to a number. If it's a valid date, it's the same as D.getTime(), or 1307000069000. Otherwise, NaN. Not terribly readable, but clever.
The regex should be updated to: rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/ Adding the question mark after the last colon, making it optional. The timezone offset often does not include the colon. (ex: "-400", "+0000") This is the format in PHP for the constant DateTime::ISO8601 yields no colon.
|
25

For ie7/8 i just did:

var ds = yourdatestring;
ds = ds.replace(/-/g, '/');
ds = ds.replace('T', ' ');
ds = ds.replace(/(\+[0-9]{2})(\:)([0-9]{2}$)/, ' UTC\$1\$3');
date = new Date(ds);

This replaces all occurrences of "-" with "/", time marker "T" with a space and replaces timezone information with an IE-friendly string which enables IE7/8 to parse Dates from Strings correctly. Solved all issues for me.

5 Comments

Nope, it will return different date instances. Compare new Date('2013/01/01') in Chrome and in IE8. The correct would be new Date('2013-01-01Z) (note Z at the end).
mention "For ie7/8" in my previous post.
You're right, 'Z' matters only when slashes are used in Chrome, sorry. We just do replace dashes with slashes in all browsers to avoid browser detection. So we need 'Z`.
i was facing the same problem with IE8, .replace('-', '/') solved the issue. Thanks a lot !
Nope. In IE8, this gave me a string of "2015/01/12T08:05:02.68", which it convert into a "Invalid Date" value.
5

See RobG's post at Result of toJSON() on a date is different between IE8 and IE9+.

Below function worked for me in IE 8 and below.

// parse ISO format date like 2013-05-06T22:00:00.000Z
function convertDateFromISO(s) {
  s = s.split(/\D/);
  return new Date(Date.UTC(s[0], --s[1]||'', s[2]||'', s[3]||'', s[4]||'', s[5]||'', s[6]||''))
}

You can test like below:

var currentTime = new Date(convertDateFromISO('2013-05-06T22:00:00.000Z')).getTime();
alert(currentTime);

2 Comments

Heads up, this doesn't work for the date as formatted in the question. You must use the 00.000Z format for timestamps, the -07:00 in the question wont work.
@breckenedge, you are right. It must use ISO format 00.000Z
3

I suggest http://momentjs.com/ for cross browser date issues.

1 Comment

moment.js is a decent option. My issue is the size, so much of its girth is dedicated to handling things I dont care about. (eg. hebrew characters in date-time stamps)
1

@gib Thanks for the suggestion on Moment.js. This small library really helps out with dealing with dates and JavaScript.

Moment.js solved the problem described in the original question that I was also having. IE8 was displaying JSON ISO dates as NaN when parsed into a new Date() object.

Quick solution (include moment.js in your page, or copy the code to your js functions include)

If you just need to display a date on your page, loaded from a JSON ISO date, do this:

order_date = moment(data.OrderDate); //create a "moment" variable, from the "data" object in your JSON function in Protoype or jQuery, etc.

$('#divOrderDate).html(order_date.calendar()); //use Moment's relative date function to display "today", "yesterday", etc.

or

order_date = moment(data.OrderDate); //create a "moment" variable, from the "data" object in your JSON function in Protoype or jQuery, etc.

$('#divOrderDate).html(order_date.format('m/d/YYYY')); //use Moment's format function to display "2/6/2015" or "10/19/2014", etc.  

If you must have a Date() object (say for use with jQuery Components), do the following so successfully populate your JSON provided ISO date. (This assumes you are already inside the function of handling your JSON data.)

var ship_date = new Date(moment(data.ShipDate).format('m/d/YYYY'));  //This will successfully parse the ISO date into JavaScript's Date() object working perfectly in FF, Chrome, and IE8.

//initialize your Calendar component with the "ship_date" variable, and you won't see NaN again.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.