1

I would like to get the date (without timezone or time) from differently formatted strings that are passed into my function. The problem I am having is that the dates are not processing correctly due to the timezone I am in. Here is the current function I have:

function pgFormatDate(date) {
    /* Via http://stackoverflow.com/questions/3605214/javascript-add-leading-zeroes-to-date */
    function zeroPad(d) {
        return ("0" + d).slice(-2)
    }

    if (date) {
        var parsed = new Date(date)
        return [parsed.getUTCFullYear(), zeroPad(parsed.getMonth() + 1), zeroPad(parsed.getDate())].join("-");
    } else {
        return null;
    }
}

And here is the makeshift test harness I have created for it (all "tests" should log true if the function is working.

var test1Result = dateConvertsCorrectly("Fri Jul 07 2017 22:10:08 GMT-0500 (CDT)", "2017-07-07"); // Currently working and logging true, but break when I try to fix the others
var test2Result = dateConvertsCorrectly("Fri Jul 07 2017 02:10:08 GMT-0500 (CDT)", "2017-07-07"); // Currently working and logging true, but break when I try to fix the others
var test3Result = dateConvertsCorrectly("2017-07-07", "2017-07-07"); // Currently not working and logging false
var test4Result = dateConvertsCorrectly("Fri Jul 06 2017 22:10:08 GMT-0500 (CDT)", "2017-07-06"); // Currently working and logging true, but break when I try to fix the others
var test5Result = dateConvertsCorrectly("2017-07-06T02:59:12.037Z", "2017-07-06"); // Currently not working and logging false
var test6Result = dateConvertsCorrectly("2017-06-07", "2017-06-07"); // Currently not working and logging false

console.log('test 1 passed:', test1Result);
console.log('test 2 passed:', test2Result);
console.log('test 3 passed:', test3Result);
console.log('test 4 passed:', test4Result);
console.log('test 5 passed:', test5Result);
console.log('test 6 passed:', test6Result);


function pgFormatDate(date) {
    /* Via http://stackoverflow.com/questions/3605214/javascript-add-leading-zeroes-to-date */
    function zeroPad(d) {
        return ("0" + d).slice(-2)
    }

    if (date) {
        var parsed = new Date(date)
        return [parsed.getUTCFullYear(), zeroPad(parsed.getMonth() + 1), zeroPad(parsed.getDate())].join("-");
    } else {
        return null;
    }
}

function dateConvertsCorrectly (input, expectedOutput) {
    return pgFormatDate(input) === expectedOutput;
}

Tests 3, 5, and 6 are all failing in the CDT timezone. But I would like the code to work regardless of timezone (I really just want to keep the year, month, and day that are submitted). Using moment hasn't worked because the dates don't fit into the accepted date types allowed by moment and I get an error, so I would like to be able to do this with vanilla javascript.

Here is the jsFiddle: https://jsfiddle.net/lukeschlangen/bkyquu7j/

8
  • 1
    Can you give us an example of exactly which test is failing and in which time zone? Commented Jul 8, 2017 at 16:07
  • Thanks for asking! Tests 3, 5, and 6 are all failing in the CDT timezone. I'll add that to the question! Commented Jul 8, 2017 at 16:12
  • 1
    Generally speaking, using new Date is not recommended for parsing dates because its implementation differs across browsers. Have you tried manually specifying the format string for moment? stackoverflow.com/a/28002368/1242470 Commented Jul 8, 2017 at 16:18
  • 1
    You can put the supported format strings into an array, and then try the parsing with each element until one of them gives you a valid moment (check with m.isValid()). Commented Jul 8, 2017 at 16:23
  • 1
    I think you'll have to try them one by one. If I remember correctly, moment won't throw an error if it can't parse a date; instead, it returns a special "invalid" moment object, which you can test for using m.isValid. Commented Jul 8, 2017 at 16:26

2 Answers 2

2

Without using moment, I got manual regex parsing working for this dataset in vanilla JS.

It's not perfect, and will likely choke if you start throwing differently formatted date strings at it, but it works for this dataset.

Fiddle here.

The month parse is a big ugly switch that looks like this:

switch (true) { 
  case /Jan/i.test(date):
    parse.Month = "01";
    break;
  case /-01-/.test(date):
    date = date.replace(/-01/, '') + ' '; 
    parse.Month = "01";
    break;

But the year and date parses are reasonable enough regex matching.

 if (/\d{4}/.test(date)) {
      parse.Year = date.match(/\d{4}/)[0];
      } else {
      console.log("Year parse fail");
      }

 if (/\D\d{2}\D/.test(date)) { 
        parse.Day = date.match(/\D\d{2}\D/)[0].substring(1,3);
      } else {
      console.log("Day parse fail");
      }

The trick turned out to be parsing the month first and then removing the month data from the string, otherwise the date regex would find that first - which amusingly enough was giving the same set of errors as in the question.

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

Comments

0

Big thanks to Máté Solymosi for the suggestion of custom moment date formats. I did end up using moment and here is what I got working:

function pgFormatDate(date) {
    if (date) {
        if (moment(date.substring(4,15), 'MMM DD YYYY').isValid() && date.substring(4,15).length === 11) {
            return moment(date.substring(4,15), 'MMM DD YYYY').format('YYYY-MM-DD');
        } else if (moment(date.substring(0,10), "YYYY-MM-DD").isValid() && date.substring(0,10).length === 10) {
            return date.substring(0,10); 
        } else {
            throw 'Date not formatted correctly';
        }
    } else {
        throw 'Date must exist for formatting to occur'
    }
}

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.