简体   繁体   中英

Refactoring code of first and last day of previous month in JavaScript (node.js)

I need to get first day and last day of previous month (eg. startDate = "2016-04-01" and endDate = "2016-04-30" ). I made solution but it's kinda unclear. Does anyone know how can I refactoring code below? Because I have to use this in several places, and I do not want to break the rules - DRY. (At the moment var startDate and var endDate is in each router.get and as you can see is really complicated. Code will be using only in this file so my target is global vars in a simple form.

Code:

var date = new Date();
var firstDay = new Date(date.getFullYear(), date.getMonth() - 1, 1);
var lastDay = new Date(date.getFullYear(), date.getMonth(), 0);
var missingHours = ' 23:59:59'; // Because default date has format YYYY-MM-DD 00:00:00

router.get('/shop', function (req, res) {
    var startDate = req.query.startDate || firstDay.getFullYear() + '-' + ('0' + (firstDay.getMonth() + 1)).slice(-2) + '-' + ('0' + (firstDay.getDate())).slice(-2);
    var endDate = req.query.endDate || lastDay.getFullYear() + '-' + ('0' + (lastDay.getMonth() + 1)).slice(-2) + '-' + (lastDay.getDate());

    shop.prepareData(startDate, endDate + missingHours, function(err, data) {
    ...
    })
    }

In this case it is less about Don't Repeat Yourself, and more about, label what your code is doing :-)

For example, this line:

var startDate = req.query.startDate || firstDay.getFullYear() + '-' + ('0' + (firstDay.getMonth() + 1)).slice(-2) + '-' + ('0' + (firstDay.getDate())).slice(-2);

Is really difficult to read. So we can pull out some helper functions to give names to each stage of the process.

First, we are adding 0 padding here.

(firstDay.getMonth() + 1)).slice(-2)

So we can pull out a general function for adding a zero to a short number, eg:

function padNumber(number) {
  return ('0' + number).slice(-2);
}

That line now looks like this:

var startDate = req.query.startDate || (
  firstDay.getFullYear() + '-' +
  padNumber(firstDay.getMonth() + 1) + '-' +
  padNumber(firstDay.getDate())
);

We can reduce the noise in the line by turning this concatenated set of numbers into an array, and then use Array.prototype.join to join the items of the array together.

var startDate = req.query.startDate || (
  [ firstDay.getFullYear(),
  padNumber(firstDay.getMonth() + 1),
  padNumber(firstDay.getDate()) ].join('-')
);

Looking at the next line, it is doing a very similar thing, so let's use a general function again.

function formatDate(date) {
  return [ date.getFullYear(), 
    padNumber(date.getMonth() + 1), 
    padNumber(date.getDate()) ].join('-')
}

And this neatens up those two long lines:

var startDate = req.query.startDate || formatDate(firstDay);
var endDate = req.query.endDate || formatDate(lastDay);

Full code here:

var date = new Date();
var firstDay = new Date(date.getFullYear(), date.getMonth() - 1, 1);
var lastDay = new Date(date.getFullYear(), date.getMonth(), 0);
var missingHours = ' 23:59:59'; // Because default date has format YYYY-MM-DD 00:00:00

function padNumber(number) {
  return ('0' + number).slice(-2);
}

function formatDate(date) {
  return [ date.getFullYear(),
           padNumber(date.getMonth() + 1), 
           padNumber(date.getDate()) ].join('-')
}

router.get('/shop', function (req, res) {
  var startDate = req.query.startDate || formatDate(firstDay);
  var endDate = req.query.endDate || formatDate(lastDay);

  shop.prepareData(startDate, endDate + missingHours, function(err, data) {
    ...
  })
}

By the way, this would change the functionality of the code, so I won't include it in the answer, but I'd guess you want the date to be recalculated per request? Otherwise, you will always get the date that the server was started at. Instead, consider putting all this stuff:

var date = new Date();
var firstDay = new Date(date.getFullYear(), date.getMonth() - 1, 1);
var lastDay = new Date(date.getFullYear(), date.getMonth(), 0);

inside the request response. This will mean you start with the current date each time.

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM