2

Is there a string format of a date that a Date object can be built from (i.e. new Date('date string')) that works in all browsers and localities/timezones?

We've tried using the format suggested in the HTML5 spec of yyyy-mm-ddThh:mm:ss+hh:mm, but ran into issues with Safari and IE. We've tried using the less-formal format of mm/dd/yyyy hh:ss:mm which works but, as far as I know, "month before day" formatting can be ambiguous if your locale settings assume the first number to be a day (non-American countries). Also, it doesn't attach a timezone which would have issues with different timezones.

KOVIKO
  • 1,349
  • 1
  • 17
  • 26
  • I think it would be better and more stable (long-term, for example if some crazy browser appears, or specification changes) to use some custom format, manually split it and pass it to different Date constructor. – bezmax Feb 20 '12 at 15:11
  • Where is the date originating from? Do you have control over exporting sections of the date to pass to the construct? The Date construct can accept year, month, day, as well as using methods such as `setHours`, `setMonth`, etc. – Brad Christie Feb 20 '12 at 15:12
  • Think you might have to write your own, use a milliseconds constructor parameter, or use something like http://www.datejs.com/. – Paul Grime Feb 20 '12 at 15:13

4 Answers4

3

In short that's an almost impossible promise to make as the implementation is UA dependent. I would recommend using the iso8601 format as it will be standard going forward and use a shim to aid in the date parsing here is one I wrote for my own use:

(function() {

var d = window.Date,
    regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,3})(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/;

if (d.parse('2011-11-29T15:52:30.5') !== 1322581950500 ||
    d.parse('2011-11-29T15:52:30.52') !== 1322581950520 ||
    d.parse('2011-11-29T15:52:18.867') !== 1322581938867 ||
    d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 ||
    d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 ||
    d.parse('2011-11-29') !== 1322524800000 ||
    d.parse('2011-11') !== 1320105600000 ||
    d.parse('2011') !== 1293840000000) {

    d.__parse = d.parse;

    d.parse = function(v) {

        var m = regexIso8601.exec(v);

        if (m) {
            return Date.UTC(
                m[1],
                (m[2] || 1) - 1,
                m[3] || 1,
                m[4] - (m[8] ? m[8] + m[9] : 0) || 0,
                m[5] - (m[8] ? m[8] + m[10] : 0) || 0,
                m[6] || 0,
                ((m[7] || 0) + '00').substr(0, 3)
            );
        }

        return d.__parse.apply(this, arguments);

    };
}

d.__fromString = d.fromString;

d.fromString = function(v) {

    if (!d.__fromString || regexIso8601.test(v)) {
        return new d(d.parse(v));
    }

    return d.__fromString.apply(this, arguments);
};

})();

Now instead use Date.fromString(....) and everyone will be happy in the land of OZ!

works in all major browsers, used these references:

http://dev.w3.org/html5/spec/common-microsyntaxes.html

http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15

http://msdn.microsoft.com/en-us/library/windows/apps/ff743760(v=vs.94).aspx

http://msdn.microsoft.com/en-us/library/windows/apps/wz6stk2z(v=vs.94).aspx

http://msdn.microsoft.com/en-us/library/windows/apps/k4w173wk(v=vs.94).aspx

https://connect.microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail-on-valid-formats

hope this helps -ck

UPDATE: (1/21/2013)

It should be noted that the behavior of what's considered "standards-compliant behavior" is going to change from ECMAScript-262 v5.1 to ECMAScript-262 v6.0. See: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.9.1.15

The language went from: The value of an absent time zone offset is “Z”. to If the time zone offset is absent, the date-time is interpreted as a local time.

The pickle right now is: chrome, opera and mobile safari follow ES5.1, whereas IE10, firefox and desktop safari seem to be following ES6. So it's kind of a split decision right now... So as such there needs to be a second ES6 standard-compliant version of this script, and here ya go:

(function() {

    var d = window.Date,
        regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,})(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/,
        lOff, lHrs, lMin;

    if (d.parse('2011-11-29T15:52:30.5') !== 1322599950500 ||
        d.parse('2011-11-29T15:52:30.52') !== 1322599950520 ||
        d.parse('2011-11-29T15:52:18.867') !== 1322599938867 ||
        d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 ||
        d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 ||
        d.parse('2011-11-29') !== 1322524800000 ||
        d.parse('2011-11') !== 1320105600000 ||
        d.parse('2011') !== 1293840000000) {

        d.__parse = d.parse;

        lOff = -(new Date().getTimezoneOffset());
        lHrs = Math.floor(lOff / 60);
        lMin = lOff % 60;

        d.parse = function(v) {

            var m = regexIso8601.exec(v);

            if (m) {
                return Date.UTC(
                    m[1],
                    (m[2] || 1) - 1,
                    m[3] || 1,
                    m[4] - (m[8] ? m[9] ? m[9] + m[10] : 0 : lHrs) || 0,
                    m[5] - (m[8] ? m[9] ? m[9] + m[11] : 0 : lMin) || 0,
                    m[6] || 0,
                    ((m[7] || 0) + '00').substr(0, 3)
                );
            }

            return d.__parse.apply(this, arguments);

        };
    }

    d.__fromString = d.fromString;

    d.fromString = function(v) {

        if (!d.__fromString || regexIso8601.test(v)) {
            return new d(d.parse(v));
        }

        return d.__fromString.apply(this, arguments);
    };

})();
ckozl
  • 6,751
  • 3
  • 33
  • 50
  • I agree, ISO 8601 is *the* standard for dates and is independent from the locale. More info about the standard: http://en.wikipedia.org/wiki/ISO_8601 – Pablo Pazos Oct 13 '14 at 01:11
1

Afaik 'yyyy-mm-dd hh:mm:ss' is a format from which you can build a date in every time zone (using new Date(''yyyy-mm-dd hh:mm:ss')).

e.g. (in the Netherlands)

new Date('1933-03-17 12:33:03'); 
   //=> Fri Mar 17 1933 12:33:03 GMT+0100 (West-Europa (standaardtijd))
new Date('1933-03-17 12:33:03').toUTCString()
   //=> Fri, 17 Mar 1933 11:33:03 GMT
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • This implies that I would handle localization on the server-side, which I will not be doing. – KOVIKO Feb 20 '12 at 15:31
  • Let's say the server responds with the string '1933-03-17 12:33:03' to a user in the EST timezone. If I don't handle localization on the server side, then the same string will be sent to a user in the PST timezone. This same string represents a different point in time depending on the timezone of the user. – KOVIKO Feb 20 '12 at 16:26
  • The interchanges of dates between user and server in different time zones should include the offset using the ISO 8601 format [+-]hhmm or include the Z, letting the other side know that the date is UTC. – Pablo Pazos Oct 13 '14 at 01:14
0

Koviko,

I think someone else asked the same question -

JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse

Community
  • 1
  • 1
Glen J Fergo
  • 134
  • 1
  • 1
  • 9
0

I am not sure if there is a string format, but using new Date(2012,1,20,15,10,0)​ should work. That is, Date(Years, Months, Days, Hours, Mins, Seconds), with month being 0 indexed.

eeerahul
  • 1,629
  • 4
  • 27
  • 38
Kit Barnes
  • 725
  • 3
  • 11
  • 17