检查日期是否与重复日期匹配

时间:2017-10-22 23:47:33

标签: javascript node.js date datetime momentjs

我有一个包含日期的 STATUS AS "Status" , 'NO_DATA' AS NoData1 变量,以及一个包含数字数组的date变量。 interval数组上的每个数字代表一个日期,该日期是通过将所述数字添加到上一日期的日期计数而获得的。例如:

如果interval等于date2016-09-01等于interval,则生成的日期将为[15, 15, 20]2016-09-16,{ {1}},2016-10-01等等。

我想检查一个给定的日期是否与该模式匹配。要做到这一点,我尝试使用moment-recur,这正是我想要的2016-10-21函数,但重复数字的间隔似乎不起作用(2016-11-06将被解析例如.every()]。如何通过moment-recur或不同的库来实现这一目标?

这里是使用moment-recur的所需输出:

[15, 15, 20]

3 个答案:

答案 0 :(得分:2)

你想要做的事情的累积性质有点棘手。

可能有一种更好的方式,但我认为只要您的间隔列表不是太大,这种方法就能很好地运作。

主要的见解是,如果你正在寻找说[2, 10, 11]的累积间隔,那么你将寻找每2,12,23,25,35,46等。这个数量来寻找三个在你的累加器总和的固定间隔的不同日期 - 在这种情况下23.所以你可以在三个案例和一个间隔中使用时刻every()

例如,如果你有:

const now = moment();
const date = moment("2016-10-22", "YYYY-MM-DD");
const interval = [18, 18, 57]

// sum of the intervals -- i.e. the main interval (93)
const main_int = interval.reduce( (prev, curr) => prev + curr );

// an array of days for each small interval
const dates = interval.map(i  => moment(date.add(i ,'days')))

// moment mutates the original so this results in 
// [ moment("2016-11-09T00:00:00.000"),
//   moment("2016-11-27T00:00:00.000"),
//   moment("2017-01-23T00:00:00.000") ]

// Now see if any of these days matches the main interval

const match = dates.some(d => d.recur().every(main_int).days().matches(now))

答案 1 :(得分:1)

以一种非常愚蠢的方式,您尝试做的是生成根据您的顺序累积的新日期,然后查看它是否在某个时刻与测试日期匹配。

以下使用moment.js,但实际上并不需要它。在一些单独的函数中,矩函数可以用大约10行代码替换。



/* @param {Date} sequenceStart - start of sequence
** @param {Array} sequence - sequence of intervals
** @param {Date} date - date for comparison
*/
function inSequence(sequenceStart, sequence, date) {
  // Copy start date so don't affect original
  var s = moment(sequenceStart);
  // Get test date in suitable format
  var d = moment(date).format('YYYYMMDD');
  var i = 0;

  do {
    // debug
    console.log(s.format('YYYYMMDD') + ' ' + d)

    // If dates match, return true
    if (s.format('YYYYMMDD') == d) {
      return true;
    }
    // If didn't match, add the next value in the sequence
    s.add(sequence[i++ % sequence.length], 'day');

  // Stop if go past test date
  } while (s.format('YYYYMMDD') <= d)

  // If didn't return true, return false
  return false;
}

var sequence = [15,15,20];
var start = new Date(2017,8,1); // 1 Sep 2017
var test  = new Date(2017,10,5) // 5 Nov 2017

console.log(inSequence(start, sequence, test));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.min.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

如果您愿意,可以使用与@Mark_M描述的类似方法

,而无需使用moment-recur

第一步是确定给定日期和开始日期之间的天数:moment(endDate).diff(startDate, 'days');

然后,为区间数组中每个条目的开始日期后的天数创建一个累积总计数组:

function sumSoFar(nums) {
   return nums.reduce((sums, num) => {
       const prevSum = last(sums) || 0;
       return sums.concat(num + prevSum);
   }, []);
}

// ...

const sums = sumSoFar(interval);

最后,整个区间数组的总和只是该列表中的最后一个条目,因此我们可以通过采用天数模数区间和来找出它匹配的区间列表中的哪个条目。如果是0sums数组中的条目,则日期与间隔匹配。如果没有,那就没有。

以下是我提出的完整代码:

const startDate = moment('2016-09-01');
const interval = [15, 15, 20];
const last = (arr) => arr[arr.length - 1];
const sum = (nums) => nums.reduce((acc, num) => acc + num, 0);

function sumSoFar(nums) {
  return nums.reduce((sums, num) => {
    const prevSum = last(sums) || 0;
    return sums.concat(num + prevSum);
  }, []);
}

const validDates = [moment('2016-09-16'), moment('2016-10-01'), moment('2016-10-21'), moment('2016-11-05')];

function isValid(startDate, interval, date) {
  const days = moment(date).diff(startDate, 'days');
  const sums = sumSoFar(interval);
  const remainingDays = days % last(sums);
  return remainingDays === 0 || sums.indexOf(remainingDays) >= 0;
}

validDates.forEach(d => console.log(isValid(startDate, interval, d)));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.min.js"></script>