2

I have been using some extensions on the Date prototype to perform some operations (Advice: do not do that, it screws the date object; too late for me in my current project) and lately have been having some more issues than usual.

To parse strings in H:m format, I made a custom function and assigned it to the Date prototype like this:

Date.__parse = Date.parse;

Date.parse = function(string){
    var pattern = /^\d{1,2}:\d{1,2}/ig;

    var today = new Date();

    if ( pattern.exec(string) ){
        var year = today.getFullYear();
        var month = today.getMonth()+1;
        var day = today.getDate();

        var t = year+"-"+month+"-"+day+" "+string;
        var timestamp = Date.__parse(t);

        return new Date(timestamp);
    }
    else{
        return new Date(Date.__parse(string));
    }
}

Ugly when you try to log the date object but working until recently.

For a time, Date.parse seems to work with dates in "d-m-Y" format, but lately it is returning "invalid date" when I do it.

Did something change in the way major browsers parse the dates, or some change to the specification, or must I assume that the error was there before, and it didn´t trigger "Invalid Date" because I was lucky? (I mostly use the function to validate input fields, so it could very well pass unnoticed).

Guess I will have to write my own date scripts and totally forget the js Date object, it´s really horrible (tried to use moment.js, but the performance in the component where I use it was very poor, that´s why I had to make custom functions).

EDIT

For a better understanding;

What I was doing and seemed to work:

Date.parse("23-7-2016") // Never got an error, expected 23 Jul 2016

What I found after tracking a validation error:

var startDate = Date.parse("23-7-2016");
console.log(startDate.toISOString()); //Got Invalid Date

What I think may have happened

var startDate = Date.parse("12-7-2016"); 
// expected 12 Jul 2016, got 7 Dec 2016, silently fails, everyone is happy

Why I think the prev. case is not the case: I use an interactive scheduler and performed thousands of tests on it, hardly such an error would go unnoticed.

Worst scenario: chrome updated and changed the way it parses dates.

Not sure... hoped someone could enlighten me.

3
  • can you give some input examples for values you provide this function with? Also a general question - why do you convert dates to strings and vice-versa? Is it because you get dates as string from some external source, or do you do it for client-server communication? Commented Jul 22, 2016 at 20:01
  • I think you should be using pattern.test based on your example instead of pattern.exec Commented Jul 22, 2016 at 20:04
  • Sorry, but the example would be too extensive. The main use I do for it is an event scheduler that may be viewed as a month calendar, a week schedule, or a daily schedule. In the weekly view, for example, I have to iterate over weekDays and then over hours to hook events and later draw them. Part of the functionality is to add events, so, when it iterates over dates, I have to convert them to readable localized strings (I din´t post the whole bunch of text parsers), and viceversa. When clicking on the a day, it has to store the date value... and so on. Commented Jul 22, 2016 at 20:11

1 Answer 1

1

I've determined your method should work for any valid input. You problem is most likely that your regex is valid for hours above 23, and minutes above 59.

See my jsfiddle, which enumerates all valid inputs. https://jsfiddle.net/kLngLL72/4/

I didn't overwrite the Date.parse function in my example to prevent infinite nesting of the function.

Date.__parse = Date.parse;

var dparse = function(string){
    var pattern = /^\d{1,2}:\d{1,2}/ig;

    var today = new Date();

    if ( pattern.exec(string) ){
        var year = today.getFullYear();
        var month = today.getMonth()+1;
        var day = today.getDate();

        var t = year+"-"+month+"-"+day+" "+string;
        var timestamp = Date.__parse(t);

        return new Date(timestamp);
    }
    else{
        return new Date(Date.__parse(string));
    }
}

$("#data").append("<tr><td>" + dparse("01-01-2016 1:31") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("1-1-2016 0:0") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("1-1-2016 12:59") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("1-1-2016 23:59") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016 1:1") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016 24:0") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016 99:99") + "</td></tr>");

for (var i = 0; i < 24; i++)
{
    for (var j = 0; j < 60; j++)
  {
    $("#data").append("<tr><td>" + dparse("12-31-2016 " + i + ":" + j) + "</td></tr>");
  }
}

UPDATED - NEW JS FIDDLE https://jsfiddle.net/mfe55xun/2/ This new example, only passes the hour and minute string in.

Date.__parse = Date.parse;

var dparse = function(string){
    var pattern = /^\d{1,2}:\d{1,2}/ig;

    var today = new Date();

    if ( pattern.exec(string) ){
        var year = today.getFullYear();
        var month = today.getMonth()+1;
        var day = today.getDate();

        var t = year+"-"+month+"-"+day+" "+string;
        var timestamp = Date.__parse(t);

        return new Date(timestamp);
    }
    else{
        return new Date(Date.__parse(string));
    }
}

$("#data").append("<tr><td>" + dparse("99:99") + "</td></tr>");

for (var i = 0; i < 24; i++)
{
    for (var j = 0; j < 60; j++)
  {
    $("#data").append("<tr><td>" + dparse(i + ":" + j) + "</td></tr>");
  }
}

UPDATE

It should be noted that if your input string included the date, the regular Date.parse would work on a string with your H:m formatting:

Date.parse("1/2/2016 4:3")

You would just need to append your "4:3" to a current date string, and you could remove your custom Date.parse function.

Another Update For Updated Question

I don't think that format ever worked correctly for you. It has cases where it will work, but it's always going to interpret the day "23rd" to be a month, and give you an invalid date. Here is another jsfiddle example that loops through all conceivable dates in that format, notice only days 1-12 work. https://jsfiddle.net/mfe55xun/6/

Date.__parse = Date.parse;

var dparse = function(string){
    var pattern = /^\d{1,2}:\d{1,2}/ig;

    var today = new Date();

    if ( pattern.exec(string) ){
        var year = today.getFullYear();
        var month = today.getMonth()+1;
        var day = today.getDate();

        var t = year+"-"+month+"-"+day+" "+string;
        var timestamp = Date.__parse(t);

        return new Date(timestamp);
    }
    else{
        return new Date(Date.__parse(string));
    }
}

for (var i = 0; i <= 31; i++)
{
    for (var j = 0; j <= 12; j++)
  {
    $("#data").append("<tr><td>" + i + "-" + j + "-2016 = " + dparse(i + "-" + j + "-2016" ) + "</td></tr>");
  }
}

Look at the results loop:

test results

0-0-2016 = Invalid Date
0-1-2016 = Invalid Date
0-2-2016 = Invalid Date
0-3-2016 = Invalid Date
0-4-2016 = Invalid Date
0-5-2016 = Invalid Date
0-6-2016 = Invalid Date
0-7-2016 = Invalid Date
0-8-2016 = Invalid Date
0-9-2016 = Invalid Date
0-10-2016 = Invalid Date
0-11-2016 = Invalid Date
0-12-2016 = Invalid Date
1-0-2016 = Invalid Date
1-1-2016 = Fri Jan 01 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-2-2016 = Sat Jan 02 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-3-2016 = Sun Jan 03 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-4-2016 = Mon Jan 04 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-5-2016 = Tue Jan 05 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-6-2016 = Wed Jan 06 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-7-2016 = Thu Jan 07 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-8-2016 = Fri Jan 08 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-9-2016 = Sat Jan 09 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-10-2016 = Sun Jan 10 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-11-2016 = Mon Jan 11 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-12-2016 = Tue Jan 12 2016 00:00:00 GMT-0500 (Eastern Standard Time)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognised or, in some cases, contains illegal date values (e.g. 2015-02-31).

It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated).

Sign up to request clarification or add additional context in comments.

1 Comment

Great example, but I´m pretty sure that hours/minutes are not causing a problem. The input values for those come from a dropdown and cannot send incorrect values, and the shown values come from an iterator like the one you wrote. Anyway I have planned to change all the date parsing stuff as you suggested, altering the Date object is a really bad idea.

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.