2016-07-04 70 views
1

我已经在这一天旋转了我的头几天了。我需要能够在预定时间段内从我的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,如果当前运行日期是第一次,我觉得这将是艰难的todo Monday如何计算使下一次运行日期为星期三而不是30周现在?

无论如何,我会疯狂感激这个问题的任何援助。如果我上面说的是混淆,我相信它会非常类似于谷歌日历调度程序。

Google Calendar Scheduler

回答

1

通过许多图书馆寻找后,我发现,无论momentjs后来-JS们缺少的部分,使之成为可能。然而在功能上,momentjs提供了大部分所需的工具。

当时jj缺乏针对一周特定日期(即星期一)的能力,尤其是在一个月的第一个星期一的情况下。

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