Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Last active Jul 10, 2017
Embed
What would you like to do?
convert yyyy-mm-dd to mm-dd-yyyy (with optional formatter param)
// 16 June 2017
// 8 July 2017 - see why-format-matters thing below...
// convert yyyy/mm/dd to mm/dd/yyyy
var formatDate = function(date, formatter) {
// could take a pattern parameter, a delimiter parameter,...
if (!/^[\d]{4,4}[\/][\d]{1,2}[\/][\d]{1,2}$/.test(date)) {
return date;
}
var a = date.split('/');
a.push(a.shift());
return (formatter ? a.map(formatter) : a).join('/');
};
// optional formatter function to prove the case
// pre-pend leading 0 for values < 10 (absolute values, that is).
var leftZero = function(v) {
v = Math.abs(+v);
return v < 10 ? '0' + v : v;
};
// test it out
console.log(
[
formatDate("2017/07/22"),
formatDate('2017/2/4')
formatDate('2017/07/15', leftZero),
formatDate('-2017/-07/-08', leftZero),
formatDate('2017/2/4', leftZero)
].join(',')
);
// 07/22/2017, 2/4/2017, 07/15/2017, 07/08/2017, 02/04/2017

Why input string format matters for JavaScript dates

Given this format, '2017-05-01', I want the date of May 1, 2017

Try it:

new Date('2017-05-01')

Turns out that Date() processes that format as UTC based, not local based. And that returns Sun Apr 30 2017 17:00:00 GMT-0700 - 7 hours behind - which is not what we want.

Try it without the leading zero on the month,

new Date('2017-5-01')

and that returns Mon May 01 2017 00:00:00 GMT-0700 which is what we want.

Try it with stroke/slash characters in place of the hyphens:

new Date('2017/05/01')

That works, too: Mon May 01 2017 00:00:00 GMT-0700

Recommended format: YYYY/MM/DD

    Recommended format for parsing is: YYYY/MM/DD – user local settings independent. It always assumes
    local timezone offset for date string given as a parameter.

More on this at "JavaScript Date: a Bad Part", https://jj09.net/javascript-date-a-bad-part/, by Jakub Jedryszek.

JavaScript Date vs. Moment.js

This came up today as I was debugging some Moment.js date/time library warnings. The recommended 'YYYY/MM/DD' format of the date string param, which gives us what we want from the JavaScript Date() constructor, produces something unexpected in Moment.

Moment('2017/05/01')

Result is a long console warning.

Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js 
Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be 
removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.

Turn that off by using Forgiving Mode, i.e., by adding a second parameter, indicating the format, possibly "non-standard", to be expected by Moment.

Moment('2017/05/01', 'YYYY/MM/DD')

Midnight-minus-one-hour Conclusions

  • Specifications (RFC2822/ISO) and implementations (Date(), Moment.js) are two different things.
  • Time formatting is really hard to codify once and be done with.
  • It can take a lot of time to read up and understand the issues completely.
  • (Author's message) Use test-driven development to catch this stuff. I first detected these issues today using TDD (FTR, I'm transforming a JSON response into a proper structure to be consumed by d3.js for some line/series charts. TDD, which had seemed a bit costly here, actually cut short the guesswork today).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment