Javascript JSON Date parse in IE7/IE8 returns NaN

34,512

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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

Solution 5

@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.
Share:
34,512
Josiah
Author by

Josiah

Updated on December 07, 2020

Comments

  • Josiah
    Josiah over 3 years

    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!

  • segFault
    segFault about 11 years
    This is returning 5/24 in IE8 instead of 6/24 can you please update the function to work properly???
  • kennebec
    kennebec about 11 years
    Didn't change the function, just ++incremented the date.getMonth() in the alert to return a 1 based month.
  • jackocnr
    jackocnr almost 11 years
    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
  • Dzmitry Lazerka
    Dzmitry Lazerka over 10 years
    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).
  • fbtb
    fbtb over 10 years
    mention "For ie7/8" in my previous post.
  • Dzmitry Lazerka
    Dzmitry Lazerka over 10 years
    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`.
  • visum
    visum about 10 years
    @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.
  • Gurpreet Singh
    Gurpreet Singh about 10 years
    i was facing the same problem with IE8, .replace('-', '/') solved the issue. Thanks a lot !
  • Mike Gledhill
    Mike Gledhill over 9 years
    Nope. In IE8, this gave me a string of "2015/01/12T08:05:02.68", which it convert into a "Invalid Date" value.
  • Aaron Breckenridge
    Aaron Breckenridge over 9 years
    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.
  • Estin Chin
    Estin Chin about 9 years
    @breckenedge, you are right. It must use ISO format 00.000Z
  • Nicholas E.
    Nicholas E. almost 9 years
    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.
  • The Dembinski
    The Dembinski over 7 years
    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)
  • Szymon
    Szymon over 7 years
    thaaaaaaanks :)