简体   繁体   中英

Finding leap years in a moment-range

I'm trying to use moment.js and moment-range to determine whether a given date range contains a leap year and a leap date (Feb 29th).

// Really checks for leap day, not only leap year.
function dateRangeContainsLeapYear(dateRange) {
  return dateRange.toArray('years').some((year) => {
    return year.isLeapYear() && dateRange.contains(moment([year.year(), 1, 29]));
  });
}

// Scenario 1
var start = moment('2015-07-01', 'YYYY-MM-DD');
var end = moment('2016-06-30', 'YYYY-MM-DD');

var dateRange = moment().range(start, end);
var dateRangeLength = dateRange.toArray('days').length; // 366

var output = dateRangeContainsLeapYear(dateRange);
console.log(output); // false

// Scenario 2
var start = moment('2015-07-01', 'YYYY-MM-DD');
var end = moment('2016-07-01', 'YYYY-MM-DD');

var dateRange = moment().range(start, end);
var dateRangeLength = dateRange.toArray('days').length; // 367

var output = dateRangeContainsLeapYear(dateRange);
console.log(output); // true

// Scenario 3
var start = moment('2016-01-01', 'YYYY-MM-DD');
var end = moment('2016-06-30', 'YYYY-MM-DD');

var dateRange = moment().range(start, end);
var dateRangeLength = dateRange.toArray('days').length; // 182

var output = dateRangeContainsLeapYear(dateRange);
console.log(output); // true

// Scenario 4
var start = moment('2015-07-01', 'YYYY-MM-DD');
var end = moment('2017-06-30', 'YYYY-MM-DD');

var dateRange = moment().range(start, end);
var dateRangeLength = dateRange.toArray('days').length; // 731

var output = dateRangeContainsLeapYear(dateRange);
console.log(output); // true

Scenario 1 returns false as dateRange.toArray('years') contains only one element, ie only 2015.

What is the best way to solve this?

JSFiddle: https://jsfiddle.net/wwwescape/es931aa5/

You're right in that there is no easy way to do this in moment-range. The maintainers would be happy to accept a PR to solve a problem like this where a flag can be added to the range.by() method to allow inclusivity of non-entire years/months/days.

I've found a fairly elegant solution which solves your problem using a simple loop:

function dateRangeContainsLeapYear(dateRange) {
  for (var year = dateRange.start.year(); year <= dateRange.end.year(); year++) {
    var date = moment(year + '-02-29');
    if (date.isLeapYear() && dateRange.contains(date)) return true;
  }
  return false;
}

PS. Make sure you update your version of moment-range! Conversion to arrays is different to your examples in the API.

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