Skip to content

Commit

Permalink
updated docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Bill Scheidel committed Jun 22, 2013
1 parent 12dddbd commit c0c58f8
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
language: node_js
node_js:
- 0.8
- "0.10"
59 changes: 49 additions & 10 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
_Later_ is a library for describing recurring schedules and calculating their future occurrences. It supports a very flexible schedule definition including support for composite schedules and schedule exceptions. _Later_ also supports executing a callback on a provided schedule.
# [Later v1.0.0](http://bunkat.github.io/later/)

There are four ways that schedules can be defined: using the chainable _Recur_ api, using an English expression, using a Cron expression, or they can also be manually defined. _Later_ works in both the browser and [node](http://nodejs.org) and the core engine for calculating schedules is only 4kb minified and compressed.
_Later_ is a library for describing recurring schedules and calculating their future occurrences. It supports a very flexible schedule definition including support for composite schedules and schedule exceptions. Create new schedules manually, via Cron expression, via text expressions, or using a fully chainable API.

Types of schedules supported by _Later_:

Example _Later_ schedules:
* Run a report on the last day of every month at 12 AM except in December
* Install patches on the 2nd Tuesday of every month at 4 AM
* Gather CPU metrics every 10 mins Mon - Fri and every 30 mins Sat - Sun
* Send out a scary e-mail at 13:13:13 every Friday the 13th

## Full documentation

http://bunkat.github.io/later/

## Installation

Using npm:

$ npm install later
Expand All @@ -24,12 +20,55 @@ Using bower:

## Building

To build the minified javascript files for _later_:
To build the minified javascript files for _later_, run `npm install` to install dependencies and then:

$ make build

## Running tests

To run the tests for _later_, run `npm install` to install dependencies and then:

$ make test
$ make test

## Versioning

Releases will be numbered with the following format:

`<major>.<minor>.<patch>`

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

For more information on SemVer, please visit [http://semver.org/](http://semver.org/).

## Bug tracker

Have a bug or a feature request? [Please open a new issue](https://github.com/bunkat/later/issues).

## Change Log

### Later v1.0.0

* No more resolutions!
- _Later_ now automatically handles this internally, you no longer need to specify your desired resolution. 'Every 5 minutes' now does exactly what you would expect it to :)

* Changing between UTC and local time has changed.
- Use `later.date.UTC()` and `later.date.localTime()` to switch between the two.

* API for parsers has changed.
- Recur is now at `later.parse.recur()`
- Cron is now at `later.parse.cron(expr)`
- Text is now at `later.parse.text(expr)`

* API for calculating occurrences has changed.
- Schedules are now compiled using `later.schedule(schedule)`
- getNext is now `later.schedule(schedule).next(count, start, end)`
- getPrev is now `later.schedule(schedule).prev(count, start, end)`

* `After` meaning 'don't start until after this amount of time' has been deprecated.
- This was a hack since people had a hard time with resolutions. With resolutions gone, this is no longer needed and is deprecated since it produced non-deterministic schedules.

**Note:** Schedule definitions did not change (unless you were using `after` constraints which have been deprecated). If you stored any schedule definitions from v0.0.20, they should continue to work unchanged in v1.0.0.
23 changes: 7 additions & 16 deletions example/browser.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,16 @@
<script src="../later.js" type="text/javascript"></script>
<script type="text/javascript">

var schedComplex = later.parse.cron().parse('0 5 15W * ?'),
compiledComplex = later.schedule(schedComplex);

later.date.localTime();
compiledComplex.next(2000);

console.log('done');

// create the desired schedule
//var schedule = enParser().parse('after 14 days');


// calculate the next 5 occurrences with a minimum resolution of 60 seconds, using local time
//var results = later(0, true).get(schedule, 20);
var sched = later.parse.text('every 5 mins on the 30th sec');

// calculate the next 5 occurrences using local time
later.date.localTime();
var results = later.schedule(sched).next(5);

//for (var i = 0; i < results.length; i++) {
// document.write('<p>' + results[i].toLocaleString() + '</p>');
//}
for (var i = 0; i < results.length; i++) {
document.write('<p>' + results[i].toLocaleString() + '</p>');
}

</script>
</html>
12 changes: 12 additions & 0 deletions example/modifier.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/**
* Modifier
* (c) 2013 Bill, BunKat LLC.
*
* Example of creating a custom modifier. See
* http://bunkat.github.io/later/modifiers.html#custom for more details.
*
* Later is freely distributable under the MIT license.
* For all details and documentation:
* http://github.com/bunkat/later
*/

var later = require('../index');

// create the new modifier
Expand Down
75 changes: 6 additions & 69 deletions example/server.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,9 @@
var recur = require('../../lib/recur').recur
, cron = require('../../lib/cron.parser').cronParser
, text = require('../../lib/en.parser').enParser
, later = require('../../lib/later').later
, rSched, cSched, tSched, mSched, results;
var later = require('../index');

// every 5 minutes (make sure to set schedule resolution to 60 seconds)
rSched = recur().every(5).minute();
cSched = cron().parse('* */5 * * * *', true);
tSched = text().parse('every 5 minutes');
mSched = {schedules: [ {m: [0,5,10,15,20,25,30,35,40,45,50,55]}]};

results = later(60).getNext(rSched);
// create the desired schedule
var sched = later.parse.text('every 5 mins on the 30th sec');

// every 5 minutes starting on the 3rd minute (make sure to set schedule resolution to 60 seconds)
rSched = recur().every(5).minute().startingOn(3);
cSched = cron().parse('* 3-59/5 * * * *', true);
tSched = text().parse('every 5 minutes starting on the 3rd minute');
mSched = {schedules: [ {m: [3,8,13,18,23,28,33,38,43,48,53,58]}]};

results = later(60).getNext(rSched);

// every 5 minutes between the 3rd and 20th minute (make sure to set schedule resolution to 60 seconds)
rSched = recur().every(5).minute().between(3,20);
cSched = cron().parse('* 3-20/5 * * * *', true);
tSched = text().parse('every 5 minutes between the 3rd and 20th minute');
mSched = {schedules: [ {m: [3,8,13,18]}]};

results = later(60).getNext(rSched);

// every 5 minutes between the 3rd and 20th minute except 8th (make sure to set schedule resolution to 60 seconds)
rSched = recur().every(5).minute().between(3,20).except().on(8).minute();
cSched = cron().parse('* 3-7,9-20/5 * * * *', true);
tSched = text().parse('every 5 minutes between the 3rd and 20th minute except on the 8th minute');
mSched = {schedules: [ {m: [3,8,13,18]}]};

results = later(60).getNext(rSched);

// every 5 minutes on the 0th second (schedule resolution can be 1 seconds)
rSched = recur().every(5).minute().first().second();
cSched = cron().parse('0 */5 * * * *', true);
tSched = text().parse('every 5 minutes on the first second');
mSched = {schedules: [ {s: [0], m: [0,5,10,15,20,25,30,35,40,45,50,55]}]};

results = later().getNext(rSched);

// every Tuesday at at 11 am
rSched = recur().on(3).dayOfWeek().at('11:00');
cSched = cron().parse('* 0 11 * * 2');
tSched = text().parse('on tuesday at 11:00 am');

results = later(1, true).getNext(rSched); // 11 am local time
results = later().getNext(rSched); // 11 am UTC

// every hour on weekdays and every other hour on weekends (set resolution to 3600 seconds)
rSched = recur().every(1).hour().onWeekday().and().every(2).hour().onWeekend();
tSched = text().parse('every 1 hour every weekday also every 2 hours every weekend');
mSched = {schedules: [
{h: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
d:[2,3,4,5,6]},
{h: [0,2,4,6,8,10,12,14,16,18,20,22],
d:[1,7]}]};

// get next 10 occurrences
results = later().get(rSched, 10);

// at 6 pm every day except on Christmas (Dec 25th)
rSched = recur().at('18:00').except().on(12).month().on(25).dayOfMonth();
tSched = text().parse('at 6:00 pm except on the 12th month on the 25th day');

// get next 10 occurrences starting in october
results = later().get(rSched, 10, new Date('9/1/2012'), new Date('1/1/2013'));
// calculate the next 5 occurrences using local time
later.date.localTime();
var results = later.schedule(sched).next(5);
12 changes: 12 additions & 0 deletions example/timeperiod.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/**
* Timeperiod
* (c) 2013 Bill, BunKat LLC.
*
* Example of creating a custom time period. See
* http://bunkat.github.io/later/time-periods.html#custom for more details.
*
* Later is freely distributable under the MIT license.
* For all details and documentation:
* http://github.com/bunkat/later
*/

var later = require('../index');

// create the new time period
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
"jslint": "*",
"uglify-js": "*",
"benchmark": "*"
},
"scripts": {
"test": "./node_modules/.bin/mocha test/**/*-test.js"
}
}
3 changes: 3 additions & 0 deletions src/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ console.log(JSON.stringify({
"jslint": "*",
"uglify-js": "*",
"benchmark": "*"
},
"scripts": {
"test": "./node_modules/.bin/mocha test/**/*-test.js"
}
}, null, 2));
15 changes: 15 additions & 0 deletions src/parse/ebnf_grammar.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Composite ::= Schedule ('also' Schedule)* (('except' Schedule) ('also' Schedule)*)?

Schedule ::= (
('on the' ('first' | 'last' | Number_Range) Period) |
('every' ('weekend' | 'weekday' | ((Number Period)) (('starting on the' Number Period) | ('between the' Number 'and' Number))?)) |
('after' ((Number Period) | Time)) |
('before' ((Number Period) | Time)) |
('at' Time ('and' Time)*) |
('on' Day (Day_Range)?) |
('of' Month (Month_Range)?) |
('in' Year (Year_Range)?)

)+

Range ::= (('-' | 'through') Value) | ((',' | 'and') Value)+
12 changes: 12 additions & 0 deletions test/core/compile-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,35 @@ describe('Compile', function() {
describe('next', function() {

it('should return start date if start is valid', function() {
later.date.UTC();
later.compile({Y:[2013], M:[3], D:[21], s:[5]}).start('next', d).should.eql(d);
});

it('should return start date if after modifier is used', function() {
later.date.UTC();
later.compile({M: [3], Y_a:[2012]}).start('next', d).should.eql(new Date('2013-03-01T00:00:00Z'));
});

it('should return next valid occurrence if invalid', function() {
later.date.UTC();
later.compile({Y:[2013], M:[4,5]}).start('next', d).should.eql(new Date('2013-04-01T00:00:00Z'));
});

it('should validate all constraints on a rollover', function() {
later.date.UTC();
later.compile({Y:[2013,2015], M:[1]}).start('next', d).should.eql(new Date('2015-01-01T00:00:00Z'));
});
});

describe('prev', function() {

it('should return start date if start is valid', function() {
later.date.UTC();
later.compile({Y:[2013], s:[5]}).start('prev', d).should.eql(d);
});

it('should return previous valid occurrence if invalid', function() {
later.date.UTC();
later.compile({Y:[2012]}).start('prev', d).should.eql(new Date('2012-01-01T00:00:00Z'));
});

Expand All @@ -45,10 +51,12 @@ describe('Compile', function() {
describe('next', function() {

it('should return start date if start is invalid', function() {
later.date.UTC();
later.compile({Y:[2014]}).end(d).should.eql(d);
});

it('should return next invalid occurrence if valid', function() {
later.date.UTC();
later.compile({Y:[2013,2014]}).end(d).should.eql(new Date('2015-01-01T00:00:00Z'));
});

Expand All @@ -60,10 +68,12 @@ describe('Compile', function() {
describe('next', function() {

it('should tick the smallest constraint with only one', function() {
later.date.UTC();
later.compile({M:[3,5]}).tick('next', d).should.eql(new Date('2013-04-01T00:00:00Z'));
});

it('should tick the smallest constraint with multiple', function() {
later.date.UTC();
later.compile({Y:[2013,2014], s: [10, 20]}).tick('next', d).should.eql(new Date('2013-03-21T00:00:06Z'));
});

Expand All @@ -72,10 +82,12 @@ describe('Compile', function() {
describe('prev', function() {

it('should tick the smallest constraint with only one', function() {
later.date.UTC();
later.compile({M:[3,5]}).tick('prev', d).should.eql(new Date('2013-02-28T23:59:59Z'));
});

it('should tick the smallest constraint with multiple', function() {
later.date.UTC();
later.compile({Y:[2013,2014], s: [10, 20]}).tick('prev', d).should.eql(new Date('2013-03-21T00:00:04Z'));
});

Expand Down

0 comments on commit c0c58f8

Please sign in to comment.