Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用于文档创建的重复事件_Javascript_Node.js_Mongodb_Schedule - Fatal编程技术网

Javascript 用于文档创建的重复事件

Javascript 用于文档创建的重复事件,javascript,node.js,mongodb,schedule,Javascript,Node.js,Mongodb,Schedule,我已经在这上面转了好几天了。我需要能够在计划的时间段内从我的Mongo数据库中提取文档,以创建文档的副本(没有时间表) 例如: 时间表:每30周一次,周一、周三和周六 文件: { _id: 'abcxyz', service: 'HVAC', assignedTo: 'xyzabc', details: 'Check HVAC System for problems' } 我将有大量的文件和所有不同的时间表。有些是每三个月(每季度)的第一个星期一 我尝试过使用later js,

我已经在这上面转了好几天了。我需要能够在计划的时间段内从我的Mongo数据库中提取文档,以创建文档的副本(没有时间表)

例如:

时间表:每30周一次,周一、周三和周六

文件:

{
  _id: 'abcxyz',
  service: 'HVAC',
  assignedTo: 'xyzabc',
  details: 'Check HVAC System for problems'
}
我将有大量的文件和所有不同的时间表。有些是每三个月(每季度)的第一个星期一

我尝试过使用later js,但later js似乎不理解诸如
30周
,我认为这是因为
30周
不是你通常使用crontab做的事情

为了完成这项工作,我假设我将生成
nextRunDate
,并提取包含当前
nextRunDate
的每个文档。说到这里,我需要计算下一次的
nextRunDate
,如果当前运行日期是第一次
Monday
,那么我觉得很难做到这一点,那么您如何计算将下一次运行日期定为周三,而不是30周后

无论如何,我非常感谢在这个问题上给予的任何帮助。如果我上面说的让人困惑的话,我相信它与谷歌日历调度器非常相似


在浏览了许多库之后,我发现momentjs和更高版本的js都缺少实现这一点的功能。然而,功能上momentjs提供了所需的大部分工具

momentjs缺乏针对一周中某一天,即周一的能力,尤其是在一个月的第一个周一的情况下

later js无法安排30周,因为它没有
every(30).weeks()
选项

我的解决方案是创建一种方法,找到一个月的第一个星期一,并计算下一个重复日期

下面是这样做的代码

import moment from 'moment';

/**
 * Gets the first week day of type in a month
 * @param  {Date} date    the original date
 * @param  {Number} day   the day of the week we are looking for
 * @return {Date}         the new date object
 */
const getFirstWeekDay = (date = new Date(), day = 0) => {
  // set the date to the first of the month
  date.setDate(1);

  // Get the first weekday of the month
  while (date.getDay() !== day) {
    date.setDate(date.getDate() + 1);
  }
  // return the new date
  return date;
};

/**
 * Returns a starting point
 * @param  {Date} startDate   the date to start from
 * @return {moment}           a moment object
 */
const start = (startDate) => moment(startDate).startOf('day');

/**
 * Calculates a Schedule on a weekly basis
 * @param  {Date}    startDate   the date to start from
 * @param  {Array}   days        days of the week to create
 * @param  {Number}  weeks       number of weeks for recurrance
 * @return {Date}                the next run date
 */
const weekly = ({ startDate, days, weeks }) => {
  const today = start(startDate);
  const index = _.indexOf(days, today.day());
  if (index === (days.length - 1)) {
    return today.add(weeks, 'weeks').day(days[0]).toDate();
  }

  return today.day(days[index + 1]).toDate();
};

/**
 * Calculates a Schedule on a monthly basis
 * @param  {Date}    startDate   the date to start from
 * @param  {Number}  day         day of the week or month
 * @param  {Number}  months      number of months for recurrance
 * @param  {Boolean} weekDay     starting at weekday or date
 * @return {Date}                the next run date
 */
const monthly = ({ startDate, day, months, weekDay }) => {
  const next = start(startDate).startOf('month').add(months, 'months');
  if (weekDay) {
    return getFirstWeekDay(next.toDate(), day);
  }

  return next.date(day).toDate();
};

// register the function in a object so we can find them
const schedules = {
  weekly,
  monthly,
};

/**
 * Returns the next run date based on a config
 * @param  {Object} config      the config for recurrence
 * @return {Date}               the next run date
 */
export default (config) => schedules[config.type](config);
您可以按如下方式使用它

  // this will get the next date 2 months out on the 30th of the month
  console.log(
    getSchedule({
      type: 'monthly', 
      months: 2,
      day: 30,
    })
  );
  // this will get the next date 2 months out on the first Wednesday
  // of the month
  console.log(
    getSchedule({
      type: 'monthly',
      months: 2,
      day: 3,
      weekDay: true,
    })
  );
  // this will get the next date 30 weeks out and if it is Monday it will
  // instead of creating another date 30 weeks out it will create a new date 
  // for Wednesday. Once Wednesday comes it will then find the next Monday 
  // that is 30 weeks out
  console.log(
    getSchedule({
      type: 'weekly',
      weeks: 30,
      days: [1, 3],
      startDate: moment().add(1, 'weeks'),
    })
  );