7
\$\begingroup\$

I'm looking for the best way to return a date on a YYYYMMDD format, such as 20180106.

Here is how I do it:

var x = new Date();
var y = x.getFullYear().toString();
var m = (x.getMonth() + 1).toString();
var d = x.getDate().toString();
(d.length == 1) && (d = '0' + d);
(m.length == 1) && (m = '0' + m);
var yyyymmdd = y + m + d;
alert(yyyymmdd);

Is it correct enough or can I achieve the same in a better way?

\$\endgroup\$
  • \$\begingroup\$ To avoid those magic constants, you could also do const components = [d.getFullYear(), d.getMonth() + 1, d.getDay()]; const paddings = [4, 2, 2]; components.map((component, i) => component.toString().padStart(paddings[i], '0')).join(''); \$\endgroup\$ – le_m Jan 6 '18 at 21:31
  • \$\begingroup\$ See also stackoverflow.com/questions/3552461/… \$\endgroup\$ – mkrieger1 Jan 6 '18 at 21:38
  • \$\begingroup\$ What do the fifth and sixth lines do? I'm learning JavaScript and I get the left part is a Boolean check but you're using "and" with code that sets a variable? \$\endgroup\$ – BruceWayne Jan 7 '18 at 0:16
  • 1
    \$\begingroup\$ @BruceWayne if the boolean check is true, the right side statement will get executed (which here sets the variable), otherwise; if the left condition fails, it'll not execute. \$\endgroup\$ – hjpotter92 Jan 7 '18 at 6:27
  • \$\begingroup\$ @hjpotter92 - Oh, woah that's pretty neat! Thanks for the explanation! \$\endgroup\$ – BruceWayne Jan 7 '18 at 7:28
6
\$\begingroup\$

The code looks good and works well. Since it provides a useful bit of work, you should convert it into a function. Then you can copy that function to another program if you need so.

function yyyymmdd() {
    var x = new Date();
    var y = x.getFullYear().toString();
    var m = (x.getMonth() + 1).toString();
    var d = x.getDate().toString();
    (d.length == 1) && (d = '0' + d);
    (m.length == 1) && (m = '0' + m);
    var yyyymmdd = y + m + d;
    return yyyymmdd;
}

To make this code a little easier to read, you should rename x to now.

You could also omit the calls to toString(), which makes the code a little shorter. Plus, you should introduce the variables mm and dd, so that you don't reassign to the d and m variables. This is a generally useful pattern, because when stepping through the code you can always look at the variable definition to see how it was computed. This is not possible for variables that change their value during execution.

The modified code looks like this:

function yyyymmdd() {
    var now = new Date();
    var y = now.getFullYear();
    var m = now.getMonth() + 1;
    var d = now.getDate();
    var mm = m < 10 ? '0' + m : m;
    var dd = d < 10 ? '0' + d : d;
    return '' + y + mm + dd;
}

Or, you could inline the last few lines:

function yyyymmdd() {
    var now = new Date();
    var y = now.getFullYear();
    var m = now.getMonth() + 1;
    var d = now.getDate();
    return '' + y + (m < 10 ? '0' : '') + m + (d < 10 ? '0' : '') + d;
}

That last variant is harder to read though, therefore I prefer the previous one.

Another possibility is to define a helper function that produces a two-digit string:

function yyyymmdd() {
    function twoDigit(n) { return (n < 10 ? '0' : '') + n; }

    var now = new Date();
    return '' + now.getFullYear() + twoDigit(now.getMonth() + 1) + twoDigit(now.getDate());
}
\$\endgroup\$
  • \$\begingroup\$ There is also padStart. m.padStart(2, '0') \$\endgroup\$ – Kruga Jan 9 '18 at 11:41
3
\$\begingroup\$

For getting the 0 padded date and month values, I generally follow this approach:

let d = ('0' + x.getDate()).substring(-2)

However, the Date objects have a .toISOString method, which returns the string in YYYY-MM-DDTHH:MM:SSZ format, which you can split on T and then replace - (or vice-versa):

formatted_date = (new Date()).toISOString().replace(/-/g, '').split('T')[0]
  // same as     (new Date()).toISOString().split('T')[0].replace(/-/g, '')
\$\endgroup\$
  • 1
    \$\begingroup\$ Woops... This first chosen solution has just failed. A new Date() like Sun Jan 07 2018 00:26:00 GMT+0100 toISOString() gives 2018-01-06T23:26:00.445Z resulting in 20180106 instead of the expected 20180107 \$\endgroup\$ – user157436 Jan 7 '18 at 0:55
  • \$\begingroup\$ toISOString always uses UTC time, and I have no idea why the API doesn't include a function like toLocalISOString, which would be quite useful. \$\endgroup\$ – Roland Illig Jan 7 '18 at 15:54