-2

Input date string is 2016-01-11 23:00:00.

$scope.formDate = function(date) {
  return new Date(date).getTime();
}

The output in Chrome is 1452549600000, Safari is NaN.

How can I make this cross-browser compliant?

nimrod
  • 5,595
  • 29
  • 85
  • 149
  • @mef—it's a duplicate of the question, however the answer there is not a good one. – RobG Jan 30 '16 at 21:31

2 Answers2

1

How can I make this cross-browser compliant?

By breaking the string into its constituent parts and then feeding them to the proper Date constructor:

$scope.formDate = function(date) {
    var matches = date.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);

    if (matches == null) {
        // An invalid date was entered
        return null;
    }

    var resultDate = new Date(
        parseInt(matches[1]), 
        parseInt(matches[2]) - 1, // months are 0 based in javascript
        parseInt(matches[3]),
        parseInt(matches[4]),
        parseInt(matches[5]),
        parseInt(matches[6])
    );

    return resultDate.getTime();
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

You should always manually parse date strings, a library can help but usually isn't necessary.

The format in the OP is not a valid ISO string, which means browsers can treat it however they wish (and Safari is compliant with the language specification when treating it as NaN, i.e. an invalid date string). The closest ISO 8601 format is "2016-01-11T23:00:00". ISO compliant strings without a timezone should be treated as local.

However, browsers may be treated as UTC, local or NaN depending on the browser. A simple function to parse it as a local time is:

/**
* Parse an ISO string without validation
* @param {string} s - date string in format yyyy-mm-dd hh:mm:ss
* @returns {Date} parsed as a local date
*/
function parseISOSimple(s) {
  var b = s.split(/\D/);
  return new Date(b[0],b[1]-1,b[2],b[3],b[4],b[5]);
}

document.write('Simple: ' + parseISOSimple('2016-01-11 23:00:00'))
RobG
  • 142,382
  • 31
  • 172
  • 209