2017-04-11 230 views
0

间隔,我需要帮助编写基于一个initialDueDate不同的时间间隔(quarterlyyearlymonthly)得到nextDueDate的功能。该方法看起来像计算nextDueDate基于使用Moment.js

伪码 -

如果initialDueDate是在未来,返回initialDueDate 否则,如果时间间隔为quarterly,不断增加3个月initialDueDate,直到你发现在该日期未来。

这是本次测试我试图通过:

describe('time helper',() => { 
    describe('when initialDueDate is in the future',() => { 
    it('returns the initialDueDate when in the future',() => { 

     const fakeNow = moment({ y: 2016, M: 0, d: 0 }); 
     Date.now = jest.fn(() => fakeNow.valueOf()); 

     const initialDueDate = moment({ y: 2016, M: 0, d: 14 }); 

     const value = time.calculateNextDueDate(initialDueDate, 'quarterly'); 

     expect(value).toEqual(initialDueDate); 

     }); 
    }); 

    describe('when initialDueDate is in the past',() => { 
    it('returns the correct date when interval is quarterly'); 
    it('returns the correct date when interval is monthly'); 
    it('returns the correct date when interval is yearly'); 
    it('throws an error when initialDueDate parameter is invalid'); 
    it('throws an error when interval parameter is invalid'); 
}); 
+0

看起来你已经开始了......你有什么问题? –

回答

1

我想一些东西添加到Yohanes Gultom的回答。处理未来的情况并使函数递归。希望能帮助到你。

// test.js 
 
const INTERVAL = { 
 
    monthly: moment.duration(1, 'months'), 
 
    quarterly: moment.duration(3, 'months'), 
 
    yearly: moment.duration(1, 'years') 
 
} 
 

 
function calculateNextDueDate(initialDueDate, intervalCode) { 
 
    if(moment().diff(initialDueDate) < 0) 
 
    return initialDueDate; 
 
    else 
 
    return calculateNextDueDate(initialDueDate.add(INTERVAL[intervalCode]), intervalCode); 
 
} 
 

 
// usage 
 
console.log(calculateNextDueDate(moment('2017-01-01', 'YYYY-MM-DD'), 'monthly').format('YYYY-MM-DD')) 
 
console.log(calculateNextDueDate(moment('2017-01-01', 'YYYY-MM-DD'), 'quarterly').format('YYYY-MM-DD')) 
 
console.log(calculateNextDueDate(moment('2017-01-01', 'YYYY-MM-DD'), 'yearly').format('YYYY-MM-DD'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

+0

作品完美!如何检查'initialDueDate'和'intervalCode'的有效参数。对不起,我是新手,感谢您的耐心等待! –

+0

检查时刻[isValid](http://momentjs.com/docs/#/parsing/is-valid/)功能。如果它存在于允许值数组中,您可以检查intervalCode。 – anshulk

+0

现在不是这样吗? – anshulk

0

我喜欢@ anshulk的递归算法,但它并没有考虑到这几个月在天方面不同长度的帐户。从我的评论:

例如,尝试下面的代码,这与1月31日开始,增加了一个月,然后又与3月28日,结束了的时候,你可能希望3月31日:

moment.utc('2017-01-31 12:00:00') 
    .add(moment.duration(1, 'month')) 
    .add(moment.duration(1, 'month')) 

基本上相同的算法应该使用.month(X)直接设置月份。关于momentjs'month()的有趣之处在于它可以超过11,所以12代表明年1月(与现在12个月不一样),29代表未来2个日历年,第5个月(即6月份)。

所以这应该工作:

function calculateNextDueDate(initialDueDate, momentMonth, intervalInMonths) { 
    const modifiedDate = moment.utc(initialDueDate).month(momentMonth) 
    if (moment.utc().diff(modifiedDate) < 0) { 
    return modifiedDate 
    } 
    return calculateNextDueDate(initialDueDate, momentMonth + intervalInMonths, intervalInMonths) 
} 

这是一个测试:

// Usage: 
var startDate = moment.utc('2017-01-31') 
console.log(calculateNextDueDate(startDate, startDate.months(), 1)) 
console.log(calculateNextDueDate(startDate, startDate.months(), 3)) 
console.log(calculateNextDueDate(startDate, startDate.months(), 12)) 

注意,moment's objects are mutable!这个算法不会改变传入的原始值,这对你来说可能很重要,也可能不重要。

另外,我到处使用了moment.utc()