Luke Schlangen
Luke Schlangen

Reputation: 3882

Remove Time and Timezone from String Dates

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/

Upvotes: 1

Views: 933

Answers (2)

hastypudding
hastypudding

Reputation: 66

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.

Upvotes: 2

Luke Schlangen
Luke Schlangen

Reputation: 3882

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'
    }
}

Upvotes: 0

Related Questions