【问题标题】:Recurring Events for Document Creation文档创建的重复事件
【发布时间】:2016-07-06 07:21:42
【问题描述】:

这几天我一直在琢磨这个问题。我需要能够在预定的时间段从我的 Mongo 数据库中提取文档以创建文档的副本(没有时间安排)。

例子:

时间安排:每 30 周的周一、周三和周六

文档:

{
  _id: 'abcxyz',
  service: 'HVAC',
  assignedTo: 'xyzabc',
  details: 'Check HVAC System for problems'
}

我将拥有大量不同时间安排的文件。有些事情,例如每三个月(每季度)的第一个星期一。

我尝试过使用诸如 later-js 之类的东西,但后来的 js 似乎无法理解诸如 30 weeks 之类的东西,我认为这是因为 30 weeks 不是您通常使用 crontab 会做的事情。

为了完成这项工作,我假设我将生成 nextRunDate 并拉取每个今天具有 nextRunDate 的文档。话虽如此,我需要每次计算nextRunDate,如果当前的运行日期是第一个Monday,我觉得这将很难做到Monday你将如何计算以使下一个运行日期改为星期三从现在起 30 周?

无论如何,我非常感谢您在此问题上提供的任何帮助。如果我上面所说的令人困惑,我相信它与谷歌日历调度程序非常相似。

【问题讨论】:

    标签: javascript node.js mongodb schedule


    【解决方案1】:

    在查看了许多库后,我发现 momentjs 和 later-js 都缺少使这成为可能的部分。然而,从功能上来说,momentjs 提供了大部分所需的工具。

    momentjs 缺乏定位一周中特定日期的能力,即星期一,尤其是在一个月的第一个星期一的情况下。

    later-js 由于没有every(30).weeks() 选项,因此无法安排 30 周。

    我的解决方案是创建一种在时刻之外查找first Monday of a month 并计算下一个重复日期的方法。

    这是执行此操作的代码

    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'),
        })
      );
    

    【讨论】:

      猜你喜欢
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      • 1970-01-01
      • 2014-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多