diff --git a/.gitignore b/.gitignore index 68b9e277..d974f3d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ bower_components/ +.idea \ No newline at end of file diff --git a/lib/nlp.js b/lib/nlp.js index 857ba9f8..04b3743b 100644 --- a/lib/nlp.js +++ b/lib/nlp.js @@ -134,7 +134,8 @@ var common = [ 'count', 'until', 'interval', 'byweekday', 'bymonthday', 'bymonth' ]; -ToText.IMPLEMENTED[RRule.DAILY] = common; +ToText.IMPLEMENTED[RRule.HOURLY] = common; +ToText.IMPLEMENTED[RRule.DAILY] = ['byhour'].concat(common); ToText.IMPLEMENTED[RRule.WEEKLY] = common; ToText.IMPLEMENTED[RRule.MONTHLY] = common; ToText.IMPLEMENTED[RRule.YEARLY] = ['byweekno', 'byyearday'].concat(common); @@ -214,6 +215,17 @@ ToText.prototype = { return this.text.join(''); }, + HOURLY: function() { + var gettext = this.gettext; + if (this.options.interval != 1) { + this.add(this.options.interval); + } + + this.add(this.plural(this.options.interval) + ? gettext('hours') : gettext('hour')); + + }, + DAILY: function() { var gettext = this.gettext; if (this.options.interval != 1) { @@ -238,6 +250,8 @@ ToText.prototype = { this._bymonthday(); } else if (this.byweekday) { this._byweekday(); + } else if (this.origOptions.byhour) { + this._byhour(); } }, @@ -387,6 +401,12 @@ ToText.prototype = { } }, + _byhour: function() { + var gettext = this.gettext; + this.add(gettext('at')) + .add(this.list(this.origOptions.byhour, null, gettext('and'))); + }, + _bymonth: function() { this.add(this.list(this.options.bymonth, this.monthtext, @@ -584,7 +604,7 @@ var parseText = function(text, language) { case 'day(s)': options.freq = RRule.DAILY; if (ttr.nextSymbol()) { - ON(); + AT(); F(); } break; @@ -612,6 +632,14 @@ var parseText = function(text, language) { } break; + case 'hour(s)': + options.freq = RRule.HOURLY; + if (ttr.nextSymbol()) { + ON(); + F(); + } + break; + case 'month(s)': options.freq = RRule.MONTHLY; if (ttr.nextSymbol()) { @@ -775,6 +803,32 @@ var parseText = function(text, language) { } while (ttr.accept('comma') || ttr.accept('the') || ttr.accept('on')); } + function AT() { + + var at = ttr.accept('at'); + if(!at) { + return; + } + + do { + var n; + if(!(n = ttr.accept('number'))) { + throw new Error('Unexpected symbol ' + ttr.symbol + + ', expected hour'); + } + options.byhour = [n[0]]; + while(ttr.accept('comma')) { + if(!(n = ttr.accept('number'))) { + throw new Error('Unexpected symbol ' + ttr.symbol + + '; expected hour'); + } + options.byhour.push(n[0]); + } + + } while (ttr.accept('comma') || ttr.accept('at')); + } + + function decodeM() { switch(ttr.symbol) { case 'january': @@ -1006,9 +1060,11 @@ var ENGLISH = { 'day(s)': /^days?/i, 'weekday(s)': /^weekdays?/i, 'week(s)': /^weeks?/i, + 'hour(s)': /^hours?/i, 'month(s)': /^months?/i, 'year(s)': /^years?/i, 'on': /^(on|in)/i, + 'at': /^(at)/i, 'the': /^the/i, 'first': /^first/i, 'second': /^second/i, diff --git a/tests/tests.js b/tests/tests.js index e6dc7fe6..cd13b765 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -25,11 +25,14 @@ module("RRule", { var texts = [ + ['Every day', 'FREQ=DAILY'], + ['Every day at 10, 12 and 17', 'FREQ=DAILY;BYHOUR=10,12,17'], + ['Every week', 'FREQ=WEEKLY'], + ['Every hour', 'FREQ=HOURLY'], + ['Every 4 hours', 'INTERVAL=4;FREQ=HOURLY'], ['Every week on Tuesday', 'FREQ=WEEKLY;BYDAY=TU'], ['Every week on Monday, Wednesday', 'FREQ=WEEKLY;BYDAY=MO,WE'], ['Every weekday', 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR'], - ['Every day', 'FREQ=DAILY'], - ['Every week', 'FREQ=WEEKLY'], ['Every 2 weeks', 'INTERVAL=2;FREQ=WEEKLY'], ['Every month', 'FREQ=MONTHLY'], ['Every 6 months', 'INTERVAL=6;FREQ=MONTHLY'], @@ -57,6 +60,17 @@ test('fromText()', function() { }); +test('toText()', function() { + $.each(texts, function(){ + var text = this[0], + string = this[1]; + console.log(text, string) + equal(RRule.fromString(string).toText().toLowerCase(), text.toLowerCase(), + string + ' => ' + text); + }); + +}); + strings = [ ['FREQ=WEEKLY;UNTIL=20100101T000000Z', 'FREQ=WEEKLY;UNTIL=20100101T000000Z'],