cyclical-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +69 -0
- data/LICENSE +20 -0
- data/README.md +63 -0
- data/Rakefile +10 -0
- data/cyclical-rails.gemspec +19 -0
- data/lib/cyclical-rails.rb +2 -0
- data/lib/cyclical/rails.rb +7 -0
- data/lib/cyclical/rails/engine.rb +6 -0
- data/lib/cyclical/rails/version.rb +5 -0
- data/lib/tasks/cyclical-rails_tasks.rake +4 -0
- data/vendor/assets/javascripts/cyclical.0.1.0.js +1813 -0
- data/vendor/assets/javascripts/cyclical.js +2 -0
- data/vendor/assets/javascripts/date.js +145 -0
- metadata +94 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in cyclical-rails.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
# jquery-rails is used by the dummy application
|
9
|
+
gem "jquery-rails"
|
10
|
+
|
11
|
+
# Declare any dependencies that are still in development here instead of in
|
12
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
13
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
14
|
+
# your gem to rubygems.org.
|
15
|
+
|
16
|
+
# To use debugger
|
17
|
+
# gem 'debugger'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cyclical-rails (0.0.1)
|
5
|
+
cyclical (~> 0.1.0)
|
6
|
+
railties (>= 3.1)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionpack (3.2.14)
|
12
|
+
activemodel (= 3.2.14)
|
13
|
+
activesupport (= 3.2.14)
|
14
|
+
builder (~> 3.0.0)
|
15
|
+
erubis (~> 2.7.0)
|
16
|
+
journey (~> 1.0.4)
|
17
|
+
rack (~> 1.4.5)
|
18
|
+
rack-cache (~> 1.2)
|
19
|
+
rack-test (~> 0.6.1)
|
20
|
+
sprockets (~> 2.2.1)
|
21
|
+
activemodel (3.2.14)
|
22
|
+
activesupport (= 3.2.14)
|
23
|
+
builder (~> 3.0.0)
|
24
|
+
activesupport (3.2.14)
|
25
|
+
i18n (~> 0.6, >= 0.6.4)
|
26
|
+
multi_json (~> 1.0)
|
27
|
+
builder (3.0.4)
|
28
|
+
cyclical (0.1.1)
|
29
|
+
activesupport (>= 3.0.0)
|
30
|
+
erubis (2.7.0)
|
31
|
+
hike (1.2.3)
|
32
|
+
i18n (0.6.5)
|
33
|
+
journey (1.0.4)
|
34
|
+
jquery-rails (3.0.4)
|
35
|
+
railties (>= 3.0, < 5.0)
|
36
|
+
thor (>= 0.14, < 2.0)
|
37
|
+
json (1.8.0)
|
38
|
+
multi_json (1.8.1)
|
39
|
+
rack (1.4.5)
|
40
|
+
rack-cache (1.2)
|
41
|
+
rack (>= 0.4)
|
42
|
+
rack-ssl (1.3.3)
|
43
|
+
rack
|
44
|
+
rack-test (0.6.2)
|
45
|
+
rack (>= 1.0)
|
46
|
+
railties (3.2.14)
|
47
|
+
actionpack (= 3.2.14)
|
48
|
+
activesupport (= 3.2.14)
|
49
|
+
rack-ssl (~> 1.3.2)
|
50
|
+
rake (>= 0.8.7)
|
51
|
+
rdoc (~> 3.4)
|
52
|
+
thor (>= 0.14.6, < 2.0)
|
53
|
+
rake (10.1.0)
|
54
|
+
rdoc (3.12.2)
|
55
|
+
json (~> 1.4)
|
56
|
+
sprockets (2.2.2)
|
57
|
+
hike (~> 1.2)
|
58
|
+
multi_json (~> 1.0)
|
59
|
+
rack (~> 1.0)
|
60
|
+
tilt (~> 1.1, != 1.3.0)
|
61
|
+
thor (0.18.1)
|
62
|
+
tilt (1.4.1)
|
63
|
+
|
64
|
+
PLATFORMS
|
65
|
+
ruby
|
66
|
+
|
67
|
+
DEPENDENCIES
|
68
|
+
cyclical-rails!
|
69
|
+
jquery-rails
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2011 Viktor Charypar
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Cyclical for Rails
|
2
|
+
|
3
|
+
Integration with [ruby](https://github.com/charypar/cyclcical) and [JavaScript](https://github.com/charypar/cyclical-js) versions of Cyclical recurring events library for yourrails application.
|
4
|
+
|
5
|
+
## About
|
6
|
+
|
7
|
+
Cyclical lets you list recurring events with complex recurrence rules like "every 4 years, the first Tuesday after a Monday in November" in a simple way both in the front-end and the back-end of your application.
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
Add the ```cyclical-rails``` gem in your Gemfile
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "cyclical-rails"
|
15
|
+
```
|
16
|
+
|
17
|
+
The ```cyclical``` JavaScript library will be added to the asset pipeline. To use them add the following to ```app/assets/javascript/application.js```:
|
18
|
+
|
19
|
+
```javascript
|
20
|
+
//= require cyclical
|
21
|
+
```
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Ruby & JavaScript
|
26
|
+
|
27
|
+
In your controller you do:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
schedule = Cyclical::Schedule.new Time.now, Cyclical::Rule.daily(2).count(3)
|
31
|
+
schedule.occurrences
|
32
|
+
```
|
33
|
+
|
34
|
+
in your javascript you do:
|
35
|
+
|
36
|
+
```javascript
|
37
|
+
var schedule = new Schedule(new Date, Schedule.Rule.daily(2).count(3));
|
38
|
+
var occ = schedule.occurrences();
|
39
|
+
```
|
40
|
+
|
41
|
+
and you get the same results.
|
42
|
+
|
43
|
+
You can send schedules over the wire as JSON. Serialize in ERB
|
44
|
+
|
45
|
+
```
|
46
|
+
schedule_json = '<%= @schedule.to_json.html_safe %>';
|
47
|
+
```
|
48
|
+
|
49
|
+
and load in javascript
|
50
|
+
|
51
|
+
```javascript
|
52
|
+
var schedule = Schedule.fromJSON(schedule_json);
|
53
|
+
```
|
54
|
+
|
55
|
+
The same also works the other way round.
|
56
|
+
|
57
|
+
For more information about [Cyclical](https://github.com/charypar/cyclcical) and [Cyclical.js](https://github.com/charypar/cyclcical-js) see the respective repos.
|
58
|
+
|
59
|
+
## License
|
60
|
+
|
61
|
+
Released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
62
|
+
|
63
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path('../lib/cyclical/rails/version', __FILE__)
|
2
|
+
|
3
|
+
# Describe your gem and declare its dependencies:
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "cyclical-rails"
|
6
|
+
s.version = Cyclical::Rails::VERSION
|
7
|
+
s.authors = ["Viktor Charypar"]
|
8
|
+
s.email = ["charypar@gmail.com"]
|
9
|
+
s.homepage = "https://github.com/charypar/cyclical-rails"
|
10
|
+
s.summary = "Cyclical support for Rails 3"
|
11
|
+
s.description = "Provides integration with ruby and JavaScript versions of Cyclical recurring events library for your rails application."
|
12
|
+
s.license = "MIT"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.require_path = 'lib'
|
16
|
+
|
17
|
+
s.add_runtime_dependency "railties", ">= 3.1"
|
18
|
+
s.add_runtime_dependency "cyclical", "~> 0.1.0"
|
19
|
+
end
|
@@ -0,0 +1,1813 @@
|
|
1
|
+
(function() {
|
2
|
+
Date.parseISO8601 = function(string) {
|
3
|
+
var i, minutes, parts, regex, _i, _len, _ref;
|
4
|
+
regex = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/;
|
5
|
+
if (!(parts = regex.exec(string))) {
|
6
|
+
return null;
|
7
|
+
}
|
8
|
+
_ref = [1, 4, 5, 6, 7, 10, 11];
|
9
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
10
|
+
i = _ref[_i];
|
11
|
+
parts[i] = +parts[i] || 0;
|
12
|
+
}
|
13
|
+
parts[2] = (+parts[2] || 1) - 1;
|
14
|
+
parts[3] = +parts[3] || 1;
|
15
|
+
if (parts[8] !== 'Z' && (parts[9] != null)) {
|
16
|
+
minutes = parts[10] * 60 + parts[11];
|
17
|
+
if (parts[9] === '+') {
|
18
|
+
minutes = -minutes;
|
19
|
+
}
|
20
|
+
parts[5] += minutes;
|
21
|
+
}
|
22
|
+
return new Date(Date.UTC.apply(Date, parts.slice(1, 8)));
|
23
|
+
};
|
24
|
+
|
25
|
+
}).call(this);
|
26
|
+
|
27
|
+
(function() {
|
28
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
29
|
+
_this = this;
|
30
|
+
|
31
|
+
window.Schedule = (function() {
|
32
|
+
function Schedule(startTime, rule) {
|
33
|
+
this.toString = __bind(this.toString, this);
|
34
|
+
this.toJSON = __bind(this.toJSON, this);
|
35
|
+
this.toObject = __bind(this.toObject, this);
|
36
|
+
this.suboccurrencesBetween = __bind(this.suboccurrencesBetween, this);
|
37
|
+
this.occurrencesBetween = __bind(this.occurrencesBetween, this);
|
38
|
+
this.occurrences = __bind(this.occurrences, this);
|
39
|
+
this.previousOccurrence = __bind(this.previousOccurrence, this);
|
40
|
+
this.nextOccurrence = __bind(this.nextOccurrence, this);
|
41
|
+
this.first = __bind(this.first, this);
|
42
|
+
this.setEndTime = __bind(this.setEndTime, this);
|
43
|
+
this.rule = __bind(this.rule, this);
|
44
|
+
this.setRule = __bind(this.setRule, this);
|
45
|
+
if (rule != null) {
|
46
|
+
this.occurrence = new Schedule.Occurrence(rule, startTime);
|
47
|
+
}
|
48
|
+
this.startTime = this.occurrence ? this.occurrence.startTime : startTime;
|
49
|
+
}
|
50
|
+
|
51
|
+
Schedule.prototype.setRule = function(rule) {
|
52
|
+
this.occurrence = rule != null ? null : new Schedule.Occurrence(rule, this.startTime);
|
53
|
+
return this.occurrence.duration = this.endTime ? this.endTime - this.startTime : 0;
|
54
|
+
};
|
55
|
+
|
56
|
+
Schedule.prototype.rule = function() {
|
57
|
+
if (this.occurrence != null) {
|
58
|
+
return this.occurrence.rule;
|
59
|
+
} else {
|
60
|
+
return null;
|
61
|
+
}
|
62
|
+
};
|
63
|
+
|
64
|
+
Schedule.prototype.setEndTime = function(time) {
|
65
|
+
if (time < this.startTime) {
|
66
|
+
throw "End time is before start time";
|
67
|
+
}
|
68
|
+
this.endTime = time;
|
69
|
+
if (this.occurrence != null) {
|
70
|
+
this.occurrence.duration = time - this.startTime;
|
71
|
+
}
|
72
|
+
return time;
|
73
|
+
};
|
74
|
+
|
75
|
+
Schedule.prototype.first = function(n) {
|
76
|
+
if (this.occurrence == null) {
|
77
|
+
return [this.startTime];
|
78
|
+
}
|
79
|
+
return this.occurrence.nextOccurrences(n, this.startTime);
|
80
|
+
};
|
81
|
+
|
82
|
+
Schedule.prototype.nextOccurrence = function(time) {
|
83
|
+
if (this.occurrence == null) {
|
84
|
+
return (this.startTime < time ? null : this.startTime);
|
85
|
+
}
|
86
|
+
return this.occurrence.nextOccurrence(time);
|
87
|
+
};
|
88
|
+
|
89
|
+
Schedule.prototype.previousOccurrence = function(time) {
|
90
|
+
if (this.occurrence == null) {
|
91
|
+
return (this.startTime >= time ? null : this.startTime);
|
92
|
+
}
|
93
|
+
return this.occurrence.previousOccurrence(time);
|
94
|
+
};
|
95
|
+
|
96
|
+
Schedule.prototype.occurrences = function(endTime) {
|
97
|
+
if ((endTime == null) && this.occurrence && this.occurrence.rule.isInfinite()) {
|
98
|
+
throw "You have to specify end time for an infinite schedule occurrence listing";
|
99
|
+
}
|
100
|
+
if (endTime != null) {
|
101
|
+
return this.occurrencesBetween(this.startTime, endTime);
|
102
|
+
} else {
|
103
|
+
if (this.occurrence == null) {
|
104
|
+
return [this.startTime];
|
105
|
+
}
|
106
|
+
return this.occurrence.all();
|
107
|
+
}
|
108
|
+
};
|
109
|
+
|
110
|
+
Schedule.prototype.occurrencesBetween = function(t1, t2) {
|
111
|
+
if (this.occurrence == null) {
|
112
|
+
return (this.startTime < t1 || this.startTime >= t2 ? [] : [this.startTime]);
|
113
|
+
}
|
114
|
+
return this.occurrence.occurrencesBetween(t1, t2);
|
115
|
+
};
|
116
|
+
|
117
|
+
Schedule.prototype.suboccurrencesBetween = function(t1, t2) {
|
118
|
+
if (this.endTime == null) {
|
119
|
+
throw "Schedule must have an end time to compute suboccurrences";
|
120
|
+
}
|
121
|
+
if (this.occurrence == null) {
|
122
|
+
return [
|
123
|
+
Schedule.Suboccurrence.find({
|
124
|
+
occurrence: [this.startTime, this.endTime],
|
125
|
+
interval: [t1, t2]
|
126
|
+
})
|
127
|
+
];
|
128
|
+
}
|
129
|
+
return this.occurrence.suboccurrencesBetween(t1, t2);
|
130
|
+
};
|
131
|
+
|
132
|
+
Schedule.prototype.toObject = function() {
|
133
|
+
var o;
|
134
|
+
o = this.occurrence != null ? this.occurrence.toObject() : {};
|
135
|
+
o.start = this.startTime;
|
136
|
+
if (this.endTime != null) {
|
137
|
+
o.end = this.endTime;
|
138
|
+
}
|
139
|
+
return o;
|
140
|
+
};
|
141
|
+
|
142
|
+
Schedule.prototype.toJSON = function() {
|
143
|
+
return JSON.stringify(this.toObject());
|
144
|
+
};
|
145
|
+
|
146
|
+
Schedule.prototype.toString = function() {
|
147
|
+
return this.rule().toString();
|
148
|
+
};
|
149
|
+
|
150
|
+
return Schedule;
|
151
|
+
|
152
|
+
})();
|
153
|
+
|
154
|
+
Schedule.fromObject = function(object) {
|
155
|
+
var endTime, rule, s, startTime;
|
156
|
+
startTime = object.start;
|
157
|
+
endTime = object.end;
|
158
|
+
rule = object.freq && object.interval ? Schedule.Rule.fromObject(object) : null;
|
159
|
+
s = new Schedule(startTime, rule);
|
160
|
+
s.setEndTime(endTime);
|
161
|
+
return s;
|
162
|
+
};
|
163
|
+
|
164
|
+
Schedule.fromJSON = function(json) {
|
165
|
+
var o;
|
166
|
+
o = JSON.parse(json);
|
167
|
+
if (o.start != null) {
|
168
|
+
o.start = Date.parseISO8601(o.start);
|
169
|
+
}
|
170
|
+
if (o.end != null) {
|
171
|
+
o.end = Date.parseISO8601(o.end);
|
172
|
+
}
|
173
|
+
if (o.stop != null) {
|
174
|
+
o.stop = Date.parseISO8601(o.stop);
|
175
|
+
}
|
176
|
+
return Schedule.fromObject(o);
|
177
|
+
};
|
178
|
+
|
179
|
+
Schedule.Rules = {};
|
180
|
+
|
181
|
+
Schedule.Filters = {};
|
182
|
+
|
183
|
+
}).call(this);
|
184
|
+
|
185
|
+
(function() {
|
186
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
187
|
+
__slice = [].slice;
|
188
|
+
|
189
|
+
Schedule.Rule = (function() {
|
190
|
+
function Rule(interval) {
|
191
|
+
if (interval == null) {
|
192
|
+
interval = 1;
|
193
|
+
}
|
194
|
+
this._minStep = __bind(this._minStep, this);
|
195
|
+
this._potentialPrevious = __bind(this._potentialPrevious, this);
|
196
|
+
this._potentialNext = __bind(this._potentialNext, this);
|
197
|
+
this.toString = __bind(this.toString, this);
|
198
|
+
this.toJSON = __bind(this.toJSON, this);
|
199
|
+
this.toObject = __bind(this.toObject, this);
|
200
|
+
this.step = __bind(this.step, this);
|
201
|
+
this.freq = __bind(this.freq, this);
|
202
|
+
this.aligned = __bind(this.aligned, this);
|
203
|
+
this.previous = __bind(this.previous, this);
|
204
|
+
this.next = __bind(this.next, this);
|
205
|
+
this.match = __bind(this.match, this);
|
206
|
+
this.isInfinite = __bind(this.isInfinite, this);
|
207
|
+
this.isFinite = __bind(this.isFinite, this);
|
208
|
+
this.filters = __bind(this.filters, this);
|
209
|
+
this.yearday = __bind(this.yearday, this);
|
210
|
+
this.yeardays = __bind(this.yeardays, this);
|
211
|
+
this.monthday = __bind(this.monthday, this);
|
212
|
+
this.monthdays = __bind(this.monthdays, this);
|
213
|
+
this.weekday = __bind(this.weekday, this);
|
214
|
+
this.weekdays = __bind(this.weekdays, this);
|
215
|
+
this.month = __bind(this.month, this);
|
216
|
+
this.months = __bind(this.months, this);
|
217
|
+
this.stop = __bind(this.stop, this);
|
218
|
+
this.count = __bind(this.count, this);
|
219
|
+
this.interval = interval;
|
220
|
+
this._filters = [];
|
221
|
+
this._filterMap = {};
|
222
|
+
}
|
223
|
+
|
224
|
+
Rule.prototype.count = function(n) {
|
225
|
+
if (!n) {
|
226
|
+
return this._count;
|
227
|
+
}
|
228
|
+
this._count = n;
|
229
|
+
return this;
|
230
|
+
};
|
231
|
+
|
232
|
+
Rule.prototype.stop = function(t) {
|
233
|
+
if (!t) {
|
234
|
+
return this._stop;
|
235
|
+
}
|
236
|
+
this._stop = t;
|
237
|
+
return this;
|
238
|
+
};
|
239
|
+
|
240
|
+
Rule.prototype.months = function() {
|
241
|
+
var f, months;
|
242
|
+
months = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
243
|
+
if (this._filterMap.month != null) {
|
244
|
+
throw "Months filter already set";
|
245
|
+
}
|
246
|
+
f = (function(func, args, ctor) {
|
247
|
+
ctor.prototype = func.prototype;
|
248
|
+
var child = new ctor, result = func.apply(child, args);
|
249
|
+
return Object(result) === result ? result : child;
|
250
|
+
})(Schedule.Filters.MonthsFilter, months, function(){});
|
251
|
+
this._filters.push(f);
|
252
|
+
this._filterMap.months = f;
|
253
|
+
return this;
|
254
|
+
};
|
255
|
+
|
256
|
+
Rule.prototype.month = function() {
|
257
|
+
var months;
|
258
|
+
months = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
259
|
+
return this.months.apply(this, months);
|
260
|
+
};
|
261
|
+
|
262
|
+
Rule.prototype.weekdays = function() {
|
263
|
+
var f, weekdays;
|
264
|
+
weekdays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
265
|
+
if (this._filterMap.weekdays != null) {
|
266
|
+
throw "weekdays filter already set";
|
267
|
+
}
|
268
|
+
weekdays = [this].concat(weekdays);
|
269
|
+
f = (function(func, args, ctor) {
|
270
|
+
ctor.prototype = func.prototype;
|
271
|
+
var child = new ctor, result = func.apply(child, args);
|
272
|
+
return Object(result) === result ? result : child;
|
273
|
+
})(Schedule.Filters.WeekdaysFilter, weekdays, function(){});
|
274
|
+
this._filters.push(f);
|
275
|
+
this._filterMap.weekdays = f;
|
276
|
+
return this;
|
277
|
+
};
|
278
|
+
|
279
|
+
Rule.prototype.weekday = function() {
|
280
|
+
var weekdays;
|
281
|
+
weekdays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
282
|
+
return this.weekdays.apply(this, weekdays);
|
283
|
+
};
|
284
|
+
|
285
|
+
Rule.prototype.monthdays = function() {
|
286
|
+
var f, monthdays;
|
287
|
+
monthdays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
288
|
+
if (this._filterMap.monthdays != null) {
|
289
|
+
throw "monthdays filter already set";
|
290
|
+
}
|
291
|
+
f = (function(func, args, ctor) {
|
292
|
+
ctor.prototype = func.prototype;
|
293
|
+
var child = new ctor, result = func.apply(child, args);
|
294
|
+
return Object(result) === result ? result : child;
|
295
|
+
})(Schedule.Filters.MonthdaysFilter, monthdays, function(){});
|
296
|
+
this._filters.push(f);
|
297
|
+
this._filterMap.monthdays = f;
|
298
|
+
return this;
|
299
|
+
};
|
300
|
+
|
301
|
+
Rule.prototype.monthday = function() {
|
302
|
+
var monthdays;
|
303
|
+
monthdays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
304
|
+
return this.monthdays.apply(this, monthdays);
|
305
|
+
};
|
306
|
+
|
307
|
+
Rule.prototype.yeardays = function() {
|
308
|
+
var f, yeardays;
|
309
|
+
yeardays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
310
|
+
if (this._filterMap.yeardays != null) {
|
311
|
+
throw "yeardays filter already set";
|
312
|
+
}
|
313
|
+
f = (function(func, args, ctor) {
|
314
|
+
ctor.prototype = func.prototype;
|
315
|
+
var child = new ctor, result = func.apply(child, args);
|
316
|
+
return Object(result) === result ? result : child;
|
317
|
+
})(Schedule.Filters.YeardaysFilter, yeardays, function(){});
|
318
|
+
this._filters.push(f);
|
319
|
+
this._filterMap.yeardays = f;
|
320
|
+
return this;
|
321
|
+
};
|
322
|
+
|
323
|
+
Rule.prototype.yearday = function() {
|
324
|
+
var yeardays;
|
325
|
+
yeardays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
326
|
+
return yeardays.apply(null, yeardays);
|
327
|
+
};
|
328
|
+
|
329
|
+
Rule.prototype.filters = function(kind) {
|
330
|
+
if (kind == null) {
|
331
|
+
return this._filters;
|
332
|
+
}
|
333
|
+
return this._filterMap[kind];
|
334
|
+
};
|
335
|
+
|
336
|
+
Rule.prototype.isFinite = function() {
|
337
|
+
return (this.count() != null) || (this.stop() != null);
|
338
|
+
};
|
339
|
+
|
340
|
+
Rule.prototype.isInfinite = function() {
|
341
|
+
return !this.isFinite();
|
342
|
+
};
|
343
|
+
|
344
|
+
Rule.prototype.match = function(time, base) {
|
345
|
+
var filter, _i, _len, _ref;
|
346
|
+
_ref = this._filters;
|
347
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
348
|
+
filter = _ref[_i];
|
349
|
+
if (!filter.match(time)) {
|
350
|
+
return false;
|
351
|
+
}
|
352
|
+
}
|
353
|
+
return this.aligned(time, base);
|
354
|
+
};
|
355
|
+
|
356
|
+
Rule.prototype.next = function(time, base) {
|
357
|
+
var MAX_ITERATIONS, current, minStep, potNext;
|
358
|
+
current = new Date(time);
|
359
|
+
minStep = this._minStep();
|
360
|
+
MAX_ITERATIONS = 1000;
|
361
|
+
while (!(this.match(current, base) && current > time)) {
|
362
|
+
if (!(MAX_ITERATIONS-- > 0)) {
|
363
|
+
throw "Maximum iterations reached when getting next rule occurrence...";
|
364
|
+
}
|
365
|
+
potNext = this._align(this._potentialNext(current, base), base);
|
366
|
+
if (Date.equals(potNext, current)) {
|
367
|
+
potNext.add(minStep.length)[minStep.unit]();
|
368
|
+
}
|
369
|
+
current = potNext;
|
370
|
+
}
|
371
|
+
return current;
|
372
|
+
};
|
373
|
+
|
374
|
+
Rule.prototype.previous = function(time, base) {
|
375
|
+
var MAX_ITERATIONS, current, minStep, potNext;
|
376
|
+
current = new Date(time);
|
377
|
+
minStep = this._minStep();
|
378
|
+
MAX_ITERATIONS = 1000;
|
379
|
+
while (!(this.match(current, base) && current < time)) {
|
380
|
+
if (!(MAX_ITERATIONS-- > 0)) {
|
381
|
+
throw "Maximum iterations reached when getting previous occurrence...";
|
382
|
+
}
|
383
|
+
potNext = this._align(this._potentialPrevious(current, base), base);
|
384
|
+
if (Date.equals(potNext, current)) {
|
385
|
+
potNext.add(-minStep.length)[minStep.unit]();
|
386
|
+
}
|
387
|
+
current = potNext;
|
388
|
+
}
|
389
|
+
return current;
|
390
|
+
};
|
391
|
+
|
392
|
+
Rule.prototype.aligned = function(time, base) {};
|
393
|
+
|
394
|
+
Rule.prototype.freq = function() {};
|
395
|
+
|
396
|
+
Rule.prototype.step = function() {};
|
397
|
+
|
398
|
+
Rule.prototype.toObject = function() {
|
399
|
+
var object;
|
400
|
+
object = {
|
401
|
+
freq: this.freq(),
|
402
|
+
interval: this.interval
|
403
|
+
};
|
404
|
+
if (this.count() != null) {
|
405
|
+
object.count = this.count();
|
406
|
+
}
|
407
|
+
if (this.stop() != null) {
|
408
|
+
object.stop = this.stop();
|
409
|
+
}
|
410
|
+
if (this.filters('weekdays') != null) {
|
411
|
+
object.weekdays = this.filters('weekdays').weekdays.concat(this.filters('weekdays').orderedWeekdays);
|
412
|
+
}
|
413
|
+
if (this.filters('monthdays') != null) {
|
414
|
+
object.monthdays = this.filters('monthdays').monthdays;
|
415
|
+
}
|
416
|
+
if (this.filters('yeardays') != null) {
|
417
|
+
object.yeardays = this.filters('yeardays').yeardays;
|
418
|
+
}
|
419
|
+
if (this.filters('months') != null) {
|
420
|
+
object.months = this.filters('months').months;
|
421
|
+
}
|
422
|
+
return object;
|
423
|
+
};
|
424
|
+
|
425
|
+
Rule.prototype.toJSON = function() {
|
426
|
+
return JSON.stringify(this.toObject());
|
427
|
+
};
|
428
|
+
|
429
|
+
Rule.prototype.toString = function() {
|
430
|
+
var dayNames, monthNames, strings;
|
431
|
+
dayNames = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
|
432
|
+
monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
433
|
+
strings = [];
|
434
|
+
if (this.filters('months')) {
|
435
|
+
strings.push(this.filters('months').toString());
|
436
|
+
}
|
437
|
+
if (this.filters('weekdays')) {
|
438
|
+
strings.push(this.filters('weekdays').toString());
|
439
|
+
}
|
440
|
+
if (this.filters('monthdays')) {
|
441
|
+
strings.push(this.filters('monthdays').toString());
|
442
|
+
}
|
443
|
+
if (this.filters('yeardays')) {
|
444
|
+
strings.push(this.filters('yeardays').toString());
|
445
|
+
}
|
446
|
+
if (this.count()) {
|
447
|
+
strings.push("end after " + (this.count()) + " times");
|
448
|
+
}
|
449
|
+
if (this.stop()) {
|
450
|
+
strings.push("until " + monthNames[this.stop().getMonth()] + " " + (this.stop().getDate()) + ", " + (this.stop().getFullYear()));
|
451
|
+
}
|
452
|
+
return strings.join(", ");
|
453
|
+
};
|
454
|
+
|
455
|
+
Rule.prototype._potentialNext = function(current, base) {
|
456
|
+
var fNext, filter;
|
457
|
+
fNext = (function() {
|
458
|
+
var _i, _len, _ref, _results;
|
459
|
+
_ref = this.filters();
|
460
|
+
_results = [];
|
461
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
462
|
+
filter = _ref[_i];
|
463
|
+
_results.push(filter.next(current));
|
464
|
+
}
|
465
|
+
return _results;
|
466
|
+
}).call(this);
|
467
|
+
if (fNext.length > 0) {
|
468
|
+
return new Date(Math.max.apply(Math, fNext));
|
469
|
+
} else {
|
470
|
+
return current;
|
471
|
+
}
|
472
|
+
};
|
473
|
+
|
474
|
+
Rule.prototype._potentialPrevious = function(current, base) {
|
475
|
+
var fNext, filter;
|
476
|
+
fNext = (function() {
|
477
|
+
var _i, _len, _ref, _results;
|
478
|
+
_ref = this.filters();
|
479
|
+
_results = [];
|
480
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
481
|
+
filter = _ref[_i];
|
482
|
+
_results.push(filter.previous(current));
|
483
|
+
}
|
484
|
+
return _results;
|
485
|
+
}).call(this);
|
486
|
+
if (fNext.length > 0) {
|
487
|
+
return new Date(Math.max.apply(Math, fNext));
|
488
|
+
} else {
|
489
|
+
return current;
|
490
|
+
}
|
491
|
+
};
|
492
|
+
|
493
|
+
Rule.prototype._align = function(time, base) {
|
494
|
+
throw "" + (typeof this) + ".align should be overriden and return a time in the period of time parameter, aligned to base";
|
495
|
+
};
|
496
|
+
|
497
|
+
Rule.prototype._minStep = function() {
|
498
|
+
var filter, i, steps, _i, _ref;
|
499
|
+
if (this.__minStep != null) {
|
500
|
+
return this.__minStep;
|
501
|
+
}
|
502
|
+
steps = (function() {
|
503
|
+
var _i, _len, _ref, _results;
|
504
|
+
_ref = this.filters();
|
505
|
+
_results = [];
|
506
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
507
|
+
filter = _ref[_i];
|
508
|
+
_results.push(filter.step());
|
509
|
+
}
|
510
|
+
return _results;
|
511
|
+
}).call(this);
|
512
|
+
steps.push(this.step());
|
513
|
+
this.__minStep = steps[0];
|
514
|
+
for (i = _i = 1, _ref = steps.length; 1 <= _ref ? _i < _ref : _i > _ref; i = 1 <= _ref ? ++_i : --_i) {
|
515
|
+
if (steps[i].seconds < this.__minStep.seconds) {
|
516
|
+
this.__minStep = steps[i];
|
517
|
+
}
|
518
|
+
}
|
519
|
+
return this.__minStep;
|
520
|
+
};
|
521
|
+
|
522
|
+
return Rule;
|
523
|
+
|
524
|
+
})();
|
525
|
+
|
526
|
+
Schedule.Rule.daily = function(interval) {
|
527
|
+
if (interval == null) {
|
528
|
+
interval = 1;
|
529
|
+
}
|
530
|
+
return new Schedule.Rules.DailyRule(interval);
|
531
|
+
};
|
532
|
+
|
533
|
+
Schedule.Rule.yearly = function(interval) {
|
534
|
+
if (interval == null) {
|
535
|
+
interval = 1;
|
536
|
+
}
|
537
|
+
return new Schedule.Rules.YearlyRule(interval);
|
538
|
+
};
|
539
|
+
|
540
|
+
Schedule.Rule.weekly = function(interval) {
|
541
|
+
if (interval == null) {
|
542
|
+
interval = 1;
|
543
|
+
}
|
544
|
+
return new Schedule.Rules.WeeklyRule(interval);
|
545
|
+
};
|
546
|
+
|
547
|
+
Schedule.Rule.monthly = function(interval) {
|
548
|
+
if (interval == null) {
|
549
|
+
interval = 1;
|
550
|
+
}
|
551
|
+
return new Schedule.Rules.MonthlyRule(interval);
|
552
|
+
};
|
553
|
+
|
554
|
+
Schedule.Rule.fromObject = function(object) {
|
555
|
+
var rule;
|
556
|
+
if (!(object.freq && object.interval)) {
|
557
|
+
throw "Bad object format";
|
558
|
+
}
|
559
|
+
rule = Schedule.Rule[object.freq](+object.interval);
|
560
|
+
if (object.count != null) {
|
561
|
+
rule.count(object.count);
|
562
|
+
}
|
563
|
+
if (object.stop != null) {
|
564
|
+
rule.stop(object.stop);
|
565
|
+
}
|
566
|
+
if (object.weekdays != null) {
|
567
|
+
rule.weekdays.apply(rule, object.weekdays);
|
568
|
+
}
|
569
|
+
if (object.monthdays != null) {
|
570
|
+
rule.monthdays.apply(rule, object.monthdays);
|
571
|
+
}
|
572
|
+
if (object.yeardays != null) {
|
573
|
+
rule.yeardays.apply(rule, object.yeardays);
|
574
|
+
}
|
575
|
+
if (object.months != null) {
|
576
|
+
rule.months.apply(rule, object.months);
|
577
|
+
}
|
578
|
+
return rule;
|
579
|
+
};
|
580
|
+
|
581
|
+
Schedule.Rule.fromJSON = function(json) {
|
582
|
+
var o;
|
583
|
+
o = JSON.parse(json);
|
584
|
+
if (o.stop) {
|
585
|
+
o.stop = Date.parseISO8601(o.stop);
|
586
|
+
}
|
587
|
+
return Schedule.Rule.fromObject(o);
|
588
|
+
};
|
589
|
+
|
590
|
+
}).call(this);
|
591
|
+
|
592
|
+
(function() {
|
593
|
+
var _ref,
|
594
|
+
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
595
|
+
__hasProp = {}.hasOwnProperty,
|
596
|
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
597
|
+
|
598
|
+
Schedule.Rules.DailyRule = (function(_super) {
|
599
|
+
__extends(DailyRule, _super);
|
600
|
+
|
601
|
+
function DailyRule() {
|
602
|
+
this._align = __bind(this._align, this);
|
603
|
+
this._potential_previous = __bind(this._potential_previous, this);
|
604
|
+
this._potentialNext = __bind(this._potentialNext, this);
|
605
|
+
this.toString = __bind(this.toString, this);
|
606
|
+
this.step = __bind(this.step, this);
|
607
|
+
this.freq = __bind(this.freq, this);
|
608
|
+
this.aligned = __bind(this.aligned, this);
|
609
|
+
_ref = DailyRule.__super__.constructor.apply(this, arguments);
|
610
|
+
return _ref;
|
611
|
+
}
|
612
|
+
|
613
|
+
DailyRule.prototype.aligned = function(time, base) {
|
614
|
+
var _ref1;
|
615
|
+
_ref1 = [new Date(time), new Date(base)], time = _ref1[0], base = _ref1[1];
|
616
|
+
if (((new Date(base)).at({
|
617
|
+
hour: 0,
|
618
|
+
minute: 0,
|
619
|
+
second: 0
|
620
|
+
}) - (new Date(time)).at({
|
621
|
+
hour: 0,
|
622
|
+
minute: 0,
|
623
|
+
second: 0
|
624
|
+
})) % this.interval !== 0) {
|
625
|
+
return false;
|
626
|
+
}
|
627
|
+
if (!(time.getHours() === base.getHours() && time.getMinutes() === base.getMinutes() && time.getSeconds() === base.getSeconds())) {
|
628
|
+
return false;
|
629
|
+
}
|
630
|
+
return true;
|
631
|
+
};
|
632
|
+
|
633
|
+
DailyRule.prototype.freq = function() {
|
634
|
+
return 'daily';
|
635
|
+
};
|
636
|
+
|
637
|
+
DailyRule.prototype.step = function() {
|
638
|
+
return {
|
639
|
+
length: this.interval,
|
640
|
+
unit: 'days',
|
641
|
+
seconds: this.interval * 86400
|
642
|
+
};
|
643
|
+
};
|
644
|
+
|
645
|
+
DailyRule.prototype.toString = function() {
|
646
|
+
var string, sup;
|
647
|
+
sup = DailyRule.__super__.toString.call(this);
|
648
|
+
string = this.interval > 1 ? "Every " + this.interval + " days" : "Daily";
|
649
|
+
if (sup) {
|
650
|
+
string += ", " + sup;
|
651
|
+
}
|
652
|
+
return string;
|
653
|
+
};
|
654
|
+
|
655
|
+
DailyRule.prototype._potentialNext = function(current, base) {
|
656
|
+
var candidate, rem;
|
657
|
+
candidate = DailyRule.__super__._potentialNext.call(this, current, base);
|
658
|
+
rem = ((new Date(base)).at({
|
659
|
+
hour: 0,
|
660
|
+
minute: 0,
|
661
|
+
second: 0
|
662
|
+
}) - (new Date(candidate)).at({
|
663
|
+
hour: 0,
|
664
|
+
minute: 0,
|
665
|
+
second: 0
|
666
|
+
})) % this.interval;
|
667
|
+
if (rem === 0) {
|
668
|
+
return candidate;
|
669
|
+
}
|
670
|
+
return (new Date(candidate)).add(rem).days().at({
|
671
|
+
hour: 0,
|
672
|
+
minute: 0,
|
673
|
+
second: 0
|
674
|
+
});
|
675
|
+
};
|
676
|
+
|
677
|
+
DailyRule.prototype._potential_previous = function(current, base) {
|
678
|
+
var candidate, rem;
|
679
|
+
candidate = DailyRule.__super__._potential_previous.call(this, current, base);
|
680
|
+
rem = ((new Date(base)).at({
|
681
|
+
hour: 0,
|
682
|
+
minute: 0,
|
683
|
+
second: 0
|
684
|
+
}) - (new Date(candidate)).at({
|
685
|
+
hour: 0,
|
686
|
+
minute: 0,
|
687
|
+
second: 0
|
688
|
+
})) % this.interval;
|
689
|
+
if (rem === 0) {
|
690
|
+
return candidate;
|
691
|
+
}
|
692
|
+
return (new Date(candidate)).add(rem - this.interval).days().at({
|
693
|
+
hour: 0,
|
694
|
+
minute: 0
|
695
|
+
});
|
696
|
+
};
|
697
|
+
|
698
|
+
DailyRule.prototype._align = function(time, base) {
|
699
|
+
return time = (new Date(time)).at({
|
700
|
+
hour: 0,
|
701
|
+
minute: 0,
|
702
|
+
second: 0
|
703
|
+
}).add({
|
704
|
+
hours: base.getHours(),
|
705
|
+
minutes: base.getMinutes(),
|
706
|
+
seconds: base.getSeconds()
|
707
|
+
});
|
708
|
+
};
|
709
|
+
|
710
|
+
return DailyRule;
|
711
|
+
|
712
|
+
})(Schedule.Rule);
|
713
|
+
|
714
|
+
}).call(this);
|
715
|
+
|
716
|
+
(function() {
|
717
|
+
var _ref,
|
718
|
+
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
719
|
+
__hasProp = {}.hasOwnProperty,
|
720
|
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
721
|
+
|
722
|
+
Schedule.Rules.MonthlyRule = (function(_super) {
|
723
|
+
__extends(MonthlyRule, _super);
|
724
|
+
|
725
|
+
function MonthlyRule() {
|
726
|
+
this._monthdayFilters = __bind(this._monthdayFilters, this);
|
727
|
+
this._align = __bind(this._align, this);
|
728
|
+
this._potentialPrevious = __bind(this._potentialPrevious, this);
|
729
|
+
this._potentialNext = __bind(this._potentialNext, this);
|
730
|
+
this.toString = __bind(this.toString, this);
|
731
|
+
this.step = __bind(this.step, this);
|
732
|
+
this.freq = __bind(this.freq, this);
|
733
|
+
this.aligned = __bind(this.aligned, this);
|
734
|
+
_ref = MonthlyRule.__super__.constructor.apply(this, arguments);
|
735
|
+
return _ref;
|
736
|
+
}
|
737
|
+
|
738
|
+
MonthlyRule.prototype.aligned = function(time, base) {
|
739
|
+
if (((12 * base.getFullYear() + base.getMonth()) - (12 * time.getFullYear() + time.getMonth())) % this.interval !== 0) {
|
740
|
+
return false;
|
741
|
+
}
|
742
|
+
if (!(time.getHours() === base.getHours() && time.getMinutes() === base.getMinutes() && time.getSeconds() === base.getSeconds())) {
|
743
|
+
return false;
|
744
|
+
}
|
745
|
+
if (!(base.getDate() === time.getDate() || this._monthdayFilters())) {
|
746
|
+
return false;
|
747
|
+
}
|
748
|
+
return true;
|
749
|
+
};
|
750
|
+
|
751
|
+
MonthlyRule.prototype.freq = function() {
|
752
|
+
return 'monthly';
|
753
|
+
};
|
754
|
+
|
755
|
+
MonthlyRule.prototype.step = function() {
|
756
|
+
return {
|
757
|
+
length: this.interval,
|
758
|
+
unit: 'months',
|
759
|
+
seconds: this.interval * 2592000
|
760
|
+
};
|
761
|
+
};
|
762
|
+
|
763
|
+
MonthlyRule.prototype.toString = function() {
|
764
|
+
var string, sup;
|
765
|
+
sup = MonthlyRule.__super__.toString.call(this);
|
766
|
+
string = this.interval > 1 ? "Every " + this.interval + " months" : "Every month";
|
767
|
+
if (sup) {
|
768
|
+
string += ", " + sup;
|
769
|
+
}
|
770
|
+
return string;
|
771
|
+
};
|
772
|
+
|
773
|
+
MonthlyRule.prototype._potentialNext = function(current, base) {
|
774
|
+
var candidate, rem;
|
775
|
+
candidate = MonthlyRule.__super__._potentialNext.call(this, current, base);
|
776
|
+
rem = ((12 * base.getFullYear() + base.getMonth()) - (12 * candidate.getFullYear() + candidate.getMonth())) % this.interval;
|
777
|
+
if (rem === 0) {
|
778
|
+
return candidate;
|
779
|
+
}
|
780
|
+
if (rem < 0) {
|
781
|
+
rem += this.interval;
|
782
|
+
}
|
783
|
+
return (new Date(candidate)).add(rem).months().set({
|
784
|
+
day: 1
|
785
|
+
}).at({
|
786
|
+
hour: 0,
|
787
|
+
minute: 0,
|
788
|
+
second: 0
|
789
|
+
});
|
790
|
+
};
|
791
|
+
|
792
|
+
MonthlyRule.prototype._potentialPrevious = function(current, base) {
|
793
|
+
var candidate, rem;
|
794
|
+
candidate = MonthlyRule.__super__._potentialPrevious.call(this, current, base);
|
795
|
+
rem = ((12 * base.getFullYear() + base.getMonth()) - (12 * candidate.getFullYear() + candidate.getMonth())) % this.interval;
|
796
|
+
if (rem === 0) {
|
797
|
+
return candidate;
|
798
|
+
}
|
799
|
+
if (rem < 0) {
|
800
|
+
rem += this.interval;
|
801
|
+
}
|
802
|
+
return (new Date(candidate)).add(rem - this.interval + 1).months().set({
|
803
|
+
day: 1
|
804
|
+
}).add(-1).day().at({
|
805
|
+
hour: 0,
|
806
|
+
minute: 0,
|
807
|
+
second: 0
|
808
|
+
});
|
809
|
+
};
|
810
|
+
|
811
|
+
MonthlyRule.prototype._align = function(time, base) {
|
812
|
+
if (!(time.getDate() === base.getDate() || this._monthdayFilters())) {
|
813
|
+
time = (new Date(time)).set({
|
814
|
+
day: 1
|
815
|
+
}).add(base.getDate() - 1).days();
|
816
|
+
}
|
817
|
+
return time = time.at({
|
818
|
+
hour: 0,
|
819
|
+
minute: 0,
|
820
|
+
second: 0
|
821
|
+
}).add({
|
822
|
+
hours: base.getHours(),
|
823
|
+
minutes: base.getMinutes(),
|
824
|
+
seconds: base.getSeconds()
|
825
|
+
});
|
826
|
+
};
|
827
|
+
|
828
|
+
MonthlyRule.prototype._monthdayFilters = function() {
|
829
|
+
return (this.filters('weekdays') != null) || (this.filters('monthdays') != null) || (this.filters('yeardays') != null) || (this.filters('weeks') != null) || (this.filters('months') != null);
|
830
|
+
};
|
831
|
+
|
832
|
+
return MonthlyRule;
|
833
|
+
|
834
|
+
})(Schedule.Rule);
|
835
|
+
|
836
|
+
}).call(this);
|
837
|
+
|
838
|
+
(function() {
|
839
|
+
var _ref,
|
840
|
+
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
841
|
+
__hasProp = {}.hasOwnProperty,
|
842
|
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
843
|
+
|
844
|
+
Schedule.Rules.WeeklyRule = (function(_super) {
|
845
|
+
__extends(WeeklyRule, _super);
|
846
|
+
|
847
|
+
function WeeklyRule() {
|
848
|
+
this._weekdayFilters = __bind(this._weekdayFilters, this);
|
849
|
+
this._align = __bind(this._align, this);
|
850
|
+
this._potentialPrevious = __bind(this._potentialPrevious, this);
|
851
|
+
this._potentialNext = __bind(this._potentialNext, this);
|
852
|
+
this.toString = __bind(this.toString, this);
|
853
|
+
this.step = __bind(this.step, this);
|
854
|
+
this.freq = __bind(this.freq, this);
|
855
|
+
this.aligned = __bind(this.aligned, this);
|
856
|
+
_ref = WeeklyRule.__super__.constructor.apply(this, arguments);
|
857
|
+
return _ref;
|
858
|
+
}
|
859
|
+
|
860
|
+
WeeklyRule.prototype.aligned = function(time, base) {
|
861
|
+
var base_mm, time_mm;
|
862
|
+
base_mm = (new Date(base)).add(-base.getDay()).days().at({
|
863
|
+
hour: 0,
|
864
|
+
minute: 0,
|
865
|
+
second: 0
|
866
|
+
});
|
867
|
+
time_mm = (new Date(time)).add(-time.getDay()).days().at({
|
868
|
+
hour: 0,
|
869
|
+
minute: 0,
|
870
|
+
second: 0
|
871
|
+
});
|
872
|
+
if ((~~((base_mm - time_mm) / 604800000) % this.interval) !== 0) {
|
873
|
+
return false;
|
874
|
+
}
|
875
|
+
if (!(time.getHours() === base.getHours() && time.getMinutes() === base.getMinutes() && time.getSeconds() === base.getSeconds())) {
|
876
|
+
return false;
|
877
|
+
}
|
878
|
+
if (!(base.getDay() === time.getDay() || this._weekdayFilters())) {
|
879
|
+
return false;
|
880
|
+
}
|
881
|
+
return true;
|
882
|
+
};
|
883
|
+
|
884
|
+
WeeklyRule.prototype.freq = function() {
|
885
|
+
return 'weekly';
|
886
|
+
};
|
887
|
+
|
888
|
+
WeeklyRule.prototype.step = function() {
|
889
|
+
return {
|
890
|
+
length: this.interval,
|
891
|
+
unit: 'weeks',
|
892
|
+
seconds: this.interval * 604800000
|
893
|
+
};
|
894
|
+
};
|
895
|
+
|
896
|
+
WeeklyRule.prototype.toString = function() {
|
897
|
+
var string, sup;
|
898
|
+
sup = WeeklyRule.__super__.toString.call(this);
|
899
|
+
string = this.interval > 1 ? "Every " + this.interval + " weeks" : "Weekly";
|
900
|
+
if (sup) {
|
901
|
+
string += ", " + sup;
|
902
|
+
}
|
903
|
+
return string;
|
904
|
+
};
|
905
|
+
|
906
|
+
WeeklyRule.prototype._potentialNext = function(current, base) {
|
907
|
+
var base_mm, candidate, candidate_mm, next, rem;
|
908
|
+
candidate = WeeklyRule.__super__._potentialNext.call(this, current, base);
|
909
|
+
base_mm = (new Date(base)).add(-base.getDay()).days().at({
|
910
|
+
hour: 0,
|
911
|
+
minute: 0,
|
912
|
+
second: 0
|
913
|
+
});
|
914
|
+
candidate_mm = (new Date(candidate)).add(-candidate.getDay()).days().at({
|
915
|
+
hour: 0,
|
916
|
+
minute: 0,
|
917
|
+
second: 0
|
918
|
+
});
|
919
|
+
rem = (~~((base_mm - candidate_mm) / 604800000)) % this.interval;
|
920
|
+
if (rem === 0) {
|
921
|
+
return candidate;
|
922
|
+
}
|
923
|
+
if (rem < 0) {
|
924
|
+
rem += this.interval;
|
925
|
+
}
|
926
|
+
next = new Date(candidate).add(rem).weeks();
|
927
|
+
return next.add(-next.getDay()).days().at({
|
928
|
+
hour: 0,
|
929
|
+
minute: 0,
|
930
|
+
second: 0
|
931
|
+
});
|
932
|
+
};
|
933
|
+
|
934
|
+
WeeklyRule.prototype._potentialPrevious = function(current, base) {
|
935
|
+
var base_mm, candidate, candidate_mm, next, rem;
|
936
|
+
candidate = WeeklyRule.__super__._potentialPrevious.call(this, current, base);
|
937
|
+
base_mm = (new Date(base)).add(-base.getDay()).days().at({
|
938
|
+
hour: 0,
|
939
|
+
minute: 0,
|
940
|
+
second: 0
|
941
|
+
});
|
942
|
+
candidate_mm = (new Date(candidate)).add(-candidate.getDay()).days().at({
|
943
|
+
hour: 0,
|
944
|
+
minute: 0,
|
945
|
+
second: 0
|
946
|
+
});
|
947
|
+
rem = (~~((base_mm - candidate_mm) / 604800000)) % this.interval;
|
948
|
+
if (rem === 0) {
|
949
|
+
return candidate;
|
950
|
+
}
|
951
|
+
if (rem < 0) {
|
952
|
+
rem += this.interval;
|
953
|
+
}
|
954
|
+
next = (new Date(candidate)).add(rem).weeks().add(-this.interval).weeks();
|
955
|
+
return next.add(-next.getDay()).days().at({
|
956
|
+
hour: 0,
|
957
|
+
minute: 0,
|
958
|
+
second: 0
|
959
|
+
}).add(1).week().add(-1).second();
|
960
|
+
};
|
961
|
+
|
962
|
+
WeeklyRule.prototype._align = function(time, base) {
|
963
|
+
if (!(time.getDay() === base.getDay() || this._weekdayFilters())) {
|
964
|
+
time = (new Date(time)).add(-time.getDay()).days().at({
|
965
|
+
hour: 0,
|
966
|
+
minute: 0,
|
967
|
+
second: 0
|
968
|
+
}).add(base.getDay()).days();
|
969
|
+
}
|
970
|
+
return time = (new Date(time)).at({
|
971
|
+
hour: 0,
|
972
|
+
minute: 0,
|
973
|
+
second: 0
|
974
|
+
}).add({
|
975
|
+
hours: base.getHours(),
|
976
|
+
minutes: base.getMinutes(),
|
977
|
+
seconds: base.getSeconds()
|
978
|
+
});
|
979
|
+
};
|
980
|
+
|
981
|
+
WeeklyRule.prototype._weekdayFilters = function() {
|
982
|
+
return (this.filters('weekdays') != null) || (this.filters('monthdays') != null) || (this.filters('yeardays') != null) || (this.filters('yeardays') != null) || (this.filters('weeks') != null) || (this.filters('months') != null);
|
983
|
+
};
|
984
|
+
|
985
|
+
return WeeklyRule;
|
986
|
+
|
987
|
+
})(Schedule.Rule);
|
988
|
+
|
989
|
+
}).call(this);
|
990
|
+
|
991
|
+
(function() {
|
992
|
+
var _ref,
|
993
|
+
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
994
|
+
__hasProp = {}.hasOwnProperty,
|
995
|
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
996
|
+
|
997
|
+
Schedule.Rules.YearlyRule = (function(_super) {
|
998
|
+
__extends(YearlyRule, _super);
|
999
|
+
|
1000
|
+
function YearlyRule() {
|
1001
|
+
this._monthFilters = __bind(this._monthFilters, this);
|
1002
|
+
this._dayFilters = __bind(this._dayFilters, this);
|
1003
|
+
this._align = __bind(this._align, this);
|
1004
|
+
this._potentialPrevious = __bind(this._potentialPrevious, this);
|
1005
|
+
this._potentialNext = __bind(this._potentialNext, this);
|
1006
|
+
this.toString = __bind(this.toString, this);
|
1007
|
+
this.freq = __bind(this.freq, this);
|
1008
|
+
this.aligned = __bind(this.aligned, this);
|
1009
|
+
_ref = YearlyRule.__super__.constructor.apply(this, arguments);
|
1010
|
+
return _ref;
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
YearlyRule.prototype.aligned = function(time, base) {
|
1014
|
+
if ((base.getFullYear() - time.getFullYear()) % this.interval !== 0) {
|
1015
|
+
return false;
|
1016
|
+
}
|
1017
|
+
if (!(time.getHours() === base.getHours() && time.getMinutes() === base.getMinutes() && time.getSeconds() === base.getSeconds())) {
|
1018
|
+
return false;
|
1019
|
+
}
|
1020
|
+
if (!(time.getDate() === base.getDate() || this._dayFilters())) {
|
1021
|
+
return false;
|
1022
|
+
}
|
1023
|
+
if (!(time.getMonth() === base.getMonth() || this._monthFilters())) {
|
1024
|
+
return false;
|
1025
|
+
}
|
1026
|
+
return true;
|
1027
|
+
};
|
1028
|
+
|
1029
|
+
YearlyRule.prototype.freq = function() {
|
1030
|
+
return 'yearly';
|
1031
|
+
};
|
1032
|
+
|
1033
|
+
YearlyRule.prototype.step = function() {
|
1034
|
+
return {
|
1035
|
+
length: this.interval,
|
1036
|
+
unit: 'years',
|
1037
|
+
seconds: this.interval * 31536000
|
1038
|
+
};
|
1039
|
+
};
|
1040
|
+
|
1041
|
+
YearlyRule.prototype.toString = function() {
|
1042
|
+
var string, sup;
|
1043
|
+
sup = YearlyRule.__super__.toString.call(this);
|
1044
|
+
string = this.interval > 1 ? "Every " + this.interval + " years" : "Every year";
|
1045
|
+
if (sup) {
|
1046
|
+
string += ", " + sup;
|
1047
|
+
}
|
1048
|
+
return string;
|
1049
|
+
};
|
1050
|
+
|
1051
|
+
YearlyRule.prototype._potentialNext = function(current, base) {
|
1052
|
+
var candidate, years;
|
1053
|
+
candidate = YearlyRule.__super__._potentialNext.call(this, current, base);
|
1054
|
+
if ((base.getFullYear() - candidate.getFullYear()) % this.interval === 0) {
|
1055
|
+
return candidate;
|
1056
|
+
}
|
1057
|
+
years = (base.getFullYear() - candidate.getFullYear()) % this.interval;
|
1058
|
+
if (years < 0) {
|
1059
|
+
years += this.interval;
|
1060
|
+
}
|
1061
|
+
return (new Date(candidate)).add(years).years().set({
|
1062
|
+
month: 0,
|
1063
|
+
day: 1
|
1064
|
+
});
|
1065
|
+
};
|
1066
|
+
|
1067
|
+
YearlyRule.prototype._potentialPrevious = function(current, base) {
|
1068
|
+
var candidate, years;
|
1069
|
+
candidate = YearlyRule.__super__._potentialPrevious.call(this, current, base);
|
1070
|
+
if ((base.getFullYear() - candidate.getFullYear()) % this.interval === 0) {
|
1071
|
+
return candidate;
|
1072
|
+
}
|
1073
|
+
years = (base.getFullYear() - candidate.getFullYear()) % this.interval;
|
1074
|
+
if (years < 0) {
|
1075
|
+
years += this.interval;
|
1076
|
+
}
|
1077
|
+
return (new Date(candidate)).add(years - this.interval).years().set({
|
1078
|
+
month: 0,
|
1079
|
+
day: 1
|
1080
|
+
});
|
1081
|
+
};
|
1082
|
+
|
1083
|
+
YearlyRule.prototype._align = function(time, base) {
|
1084
|
+
var day, mon;
|
1085
|
+
day = (this._dayFilters() ? time.getDate() : base.getDate());
|
1086
|
+
mon = (this._monthFilters() ? time.getMonth() : base.getMonth());
|
1087
|
+
time = (new Date(time)).set({
|
1088
|
+
month: 0,
|
1089
|
+
day: 1
|
1090
|
+
}).add(mon).months().add(day - 1).days();
|
1091
|
+
return time.at({
|
1092
|
+
hour: 0,
|
1093
|
+
minute: 0,
|
1094
|
+
second: 0
|
1095
|
+
}).add({
|
1096
|
+
hours: base.getHours(),
|
1097
|
+
minutes: base.getMinutes(),
|
1098
|
+
seconds: base.getSeconds()
|
1099
|
+
});
|
1100
|
+
};
|
1101
|
+
|
1102
|
+
YearlyRule.prototype._dayFilters = function() {
|
1103
|
+
return (this.filters('weekdays') != null) || (this.filters('monthdays') != null) || (this.filters('yeardays') != null);
|
1104
|
+
};
|
1105
|
+
|
1106
|
+
YearlyRule.prototype._monthFilters = function() {
|
1107
|
+
return (this.filters('weekdays') != null) || (this.filters('yeardays') != null) || (this.filters('weeks') != null) || (this.filters('months') != null);
|
1108
|
+
};
|
1109
|
+
|
1110
|
+
return YearlyRule;
|
1111
|
+
|
1112
|
+
})(Schedule.Rule);
|
1113
|
+
|
1114
|
+
}).call(this);
|
1115
|
+
|
1116
|
+
(function() {
|
1117
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
1118
|
+
__slice = [].slice;
|
1119
|
+
|
1120
|
+
Schedule.Filters.MonthdaysFilter = (function() {
|
1121
|
+
function MonthdaysFilter() {
|
1122
|
+
var monthdays;
|
1123
|
+
monthdays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
1124
|
+
this.toString = __bind(this.toString, this);
|
1125
|
+
this.previous = __bind(this.previous, this);
|
1126
|
+
this.next = __bind(this.next, this);
|
1127
|
+
this.step = __bind(this.step, this);
|
1128
|
+
this.match = __bind(this.match, this);
|
1129
|
+
if (monthdays.length < 1) {
|
1130
|
+
throw "Specify at least one day of the month";
|
1131
|
+
}
|
1132
|
+
this.monthdays = monthdays.sort(function(a, b) {
|
1133
|
+
return a - b;
|
1134
|
+
});
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
MonthdaysFilter.prototype.match = function(date) {
|
1138
|
+
var last;
|
1139
|
+
last = (new Date(date)).add(1).month().set({
|
1140
|
+
day: 1
|
1141
|
+
}).add(-1).day().getDate();
|
1142
|
+
return this.monthdays.indexOf(date.getDate()) >= 0 || this.monthdays.indexOf(date.getDate() - last - 1) >= 0;
|
1143
|
+
};
|
1144
|
+
|
1145
|
+
MonthdaysFilter.prototype.step = function() {
|
1146
|
+
return {
|
1147
|
+
length: 1,
|
1148
|
+
unit: 'day',
|
1149
|
+
seconds: 86400
|
1150
|
+
};
|
1151
|
+
};
|
1152
|
+
|
1153
|
+
MonthdaysFilter.prototype.next = function(date) {
|
1154
|
+
date = new Date(date);
|
1155
|
+
while (!this.match(date)) {
|
1156
|
+
date.add(1).day();
|
1157
|
+
}
|
1158
|
+
return date;
|
1159
|
+
};
|
1160
|
+
|
1161
|
+
MonthdaysFilter.prototype.previous = function(date) {
|
1162
|
+
date = new Date(date);
|
1163
|
+
while (!this.match(date)) {
|
1164
|
+
date.add(-1).day();
|
1165
|
+
}
|
1166
|
+
return date;
|
1167
|
+
};
|
1168
|
+
|
1169
|
+
MonthdaysFilter.prototype.toString = function() {
|
1170
|
+
var days, last;
|
1171
|
+
days = _.map(this.monthdays, function(d) {
|
1172
|
+
return "" + d + ".";
|
1173
|
+
});
|
1174
|
+
last = days.pop();
|
1175
|
+
if (days.length > 0) {
|
1176
|
+
return "on " + (days.join(", ")) + " and " + last + " day";
|
1177
|
+
} else {
|
1178
|
+
return "on " + last + " day";
|
1179
|
+
}
|
1180
|
+
};
|
1181
|
+
|
1182
|
+
return MonthdaysFilter;
|
1183
|
+
|
1184
|
+
})();
|
1185
|
+
|
1186
|
+
}).call(this);
|
1187
|
+
|
1188
|
+
(function() {
|
1189
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
1190
|
+
__slice = [].slice;
|
1191
|
+
|
1192
|
+
Schedule.Filters.MonthsFilter = (function() {
|
1193
|
+
MonthsFilter.prototype.MONTH_NAMES = {
|
1194
|
+
jan: 1,
|
1195
|
+
january: 1,
|
1196
|
+
feb: 2,
|
1197
|
+
february: 2,
|
1198
|
+
mar: 3,
|
1199
|
+
march: 3,
|
1200
|
+
apr: 4,
|
1201
|
+
april: 4,
|
1202
|
+
may: 5,
|
1203
|
+
jun: 6,
|
1204
|
+
june: 6,
|
1205
|
+
jul: 7,
|
1206
|
+
july: 7,
|
1207
|
+
aug: 8,
|
1208
|
+
august: 8,
|
1209
|
+
sep: 9,
|
1210
|
+
sept: 9,
|
1211
|
+
september: 9,
|
1212
|
+
oct: 10,
|
1213
|
+
october: 10,
|
1214
|
+
nov: 11,
|
1215
|
+
november: 11,
|
1216
|
+
dec: 12,
|
1217
|
+
december: 12
|
1218
|
+
};
|
1219
|
+
|
1220
|
+
function MonthsFilter() {
|
1221
|
+
var month, months;
|
1222
|
+
months = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
1223
|
+
this.toString = __bind(this.toString, this);
|
1224
|
+
this.previous = __bind(this.previous, this);
|
1225
|
+
this.next = __bind(this.next, this);
|
1226
|
+
this.match = __bind(this.match, this);
|
1227
|
+
if (months.length < 1) {
|
1228
|
+
throw "Specify at least one month";
|
1229
|
+
}
|
1230
|
+
this.months = (function() {
|
1231
|
+
var _i, _len, _results;
|
1232
|
+
_results = [];
|
1233
|
+
for (_i = 0, _len = months.length; _i < _len; _i++) {
|
1234
|
+
month = months[_i];
|
1235
|
+
_results.push(!isNaN(parseFloat(month)) ? month : this.MONTH_NAMES[month]);
|
1236
|
+
}
|
1237
|
+
return _results;
|
1238
|
+
}).call(this);
|
1239
|
+
this.months = this.months.sort();
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
MonthsFilter.prototype.match = function(date) {
|
1243
|
+
return this.months.indexOf(date.getMonth() + 1) >= 0;
|
1244
|
+
};
|
1245
|
+
|
1246
|
+
MonthsFilter.prototype.step = function() {
|
1247
|
+
return {
|
1248
|
+
length: 1,
|
1249
|
+
unit: 'month',
|
1250
|
+
seconds: 2592000
|
1251
|
+
};
|
1252
|
+
};
|
1253
|
+
|
1254
|
+
MonthsFilter.prototype.next = function(date) {
|
1255
|
+
var d, m, month, _i, _len, _ref;
|
1256
|
+
if (this.match(date)) {
|
1257
|
+
return date;
|
1258
|
+
}
|
1259
|
+
month = null;
|
1260
|
+
_ref = this.months;
|
1261
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
1262
|
+
m = _ref[_i];
|
1263
|
+
if (m > date.getMonth() + 1) {
|
1264
|
+
month = m;
|
1265
|
+
}
|
1266
|
+
}
|
1267
|
+
if (month != null) {
|
1268
|
+
return (new Date(date)).set({
|
1269
|
+
month: 0,
|
1270
|
+
day: 1
|
1271
|
+
}).add(month - 1).months().at({
|
1272
|
+
hour: date.getHours(),
|
1273
|
+
minute: date.getMinutes(),
|
1274
|
+
second: date.getSeconds()
|
1275
|
+
});
|
1276
|
+
} else {
|
1277
|
+
d = (new Date(date)).set({
|
1278
|
+
month: 0,
|
1279
|
+
day: 1
|
1280
|
+
}).add(1).year().add(this.months[0] - 1).months();
|
1281
|
+
return d.at({
|
1282
|
+
hour: date.getHours(),
|
1283
|
+
minute: date.getMinutes(),
|
1284
|
+
second: date.getSeconds()
|
1285
|
+
});
|
1286
|
+
}
|
1287
|
+
};
|
1288
|
+
|
1289
|
+
MonthsFilter.prototype.previous = function(date) {
|
1290
|
+
var d, m, month, _i, _len, _ref;
|
1291
|
+
if (match(date)) {
|
1292
|
+
return date;
|
1293
|
+
}
|
1294
|
+
month = null;
|
1295
|
+
_ref = this.months.reverse();
|
1296
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
1297
|
+
m = _ref[_i];
|
1298
|
+
if (m < date.getMonth() + 1) {
|
1299
|
+
month = m;
|
1300
|
+
}
|
1301
|
+
}
|
1302
|
+
if (month != null) {
|
1303
|
+
d = (new Date(date)).set({
|
1304
|
+
month: 0,
|
1305
|
+
day: 1
|
1306
|
+
}).add(month).months().add(-1).day();
|
1307
|
+
return d.at({
|
1308
|
+
hour: date.getHours(),
|
1309
|
+
minute: date.getMinutes(),
|
1310
|
+
second: date.getSeconds()
|
1311
|
+
});
|
1312
|
+
} else {
|
1313
|
+
d = (new Date(date)).set({
|
1314
|
+
month: 0,
|
1315
|
+
day: 1
|
1316
|
+
}).add(-1).year().add(this.months.last).months().add(-1).day();
|
1317
|
+
return d.at({
|
1318
|
+
hour: date.getHours(),
|
1319
|
+
minute: date.getMinutes(),
|
1320
|
+
second: date.getSeconds()
|
1321
|
+
});
|
1322
|
+
}
|
1323
|
+
};
|
1324
|
+
|
1325
|
+
MonthsFilter.prototype.toString = function() {
|
1326
|
+
var last, monthNames, months;
|
1327
|
+
monthNames = [null, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
1328
|
+
months = _.map(this.months, function(m) {
|
1329
|
+
return monthNames[m];
|
1330
|
+
});
|
1331
|
+
last = months.pop();
|
1332
|
+
if (months.length > 0) {
|
1333
|
+
return "in " + (months.join(", ")) + " and " + last;
|
1334
|
+
} else {
|
1335
|
+
return "in " + last;
|
1336
|
+
}
|
1337
|
+
};
|
1338
|
+
|
1339
|
+
return MonthsFilter;
|
1340
|
+
|
1341
|
+
})();
|
1342
|
+
|
1343
|
+
}).call(this);
|
1344
|
+
|
1345
|
+
(function() {
|
1346
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
1347
|
+
__slice = [].slice;
|
1348
|
+
|
1349
|
+
Schedule.Filters.WeekdaysFilter = (function() {
|
1350
|
+
WeekdaysFilter.prototype.WEEKDAYS = {
|
1351
|
+
su: 0,
|
1352
|
+
sun: 0,
|
1353
|
+
sunday: 0,
|
1354
|
+
mo: 1,
|
1355
|
+
mon: 1,
|
1356
|
+
monday: 1,
|
1357
|
+
tu: 2,
|
1358
|
+
tue: 2,
|
1359
|
+
tuesday: 2,
|
1360
|
+
we: 3,
|
1361
|
+
wed: 3,
|
1362
|
+
wednesday: 3,
|
1363
|
+
th: 4,
|
1364
|
+
thu: 4,
|
1365
|
+
thursday: 4,
|
1366
|
+
fr: 5,
|
1367
|
+
fri: 5,
|
1368
|
+
friday: 5,
|
1369
|
+
sa: 6,
|
1370
|
+
sat: 6,
|
1371
|
+
saturday: 6
|
1372
|
+
};
|
1373
|
+
|
1374
|
+
WeekdaysFilter.prototype.WEEKDAY_NAMES = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'];
|
1375
|
+
|
1376
|
+
function WeekdaysFilter() {
|
1377
|
+
var day, orders, w, weekdays, _ref;
|
1378
|
+
weekdays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
1379
|
+
this.toString = __bind(this.toString, this);
|
1380
|
+
this._orderInInterval = __bind(this._orderInInterval, this);
|
1381
|
+
this.previous = __bind(this.previous, this);
|
1382
|
+
this.next = __bind(this.next, this);
|
1383
|
+
this.step = __bind(this.step, this);
|
1384
|
+
this.match = __bind(this.match, this);
|
1385
|
+
if (weekdays[0] instanceof Schedule.Rule) {
|
1386
|
+
this.rule = weekdays.shift();
|
1387
|
+
}
|
1388
|
+
if (weekdays.length < 1) {
|
1389
|
+
throw "Specify at least one weekday";
|
1390
|
+
}
|
1391
|
+
this.orderedWeekdays = {};
|
1392
|
+
if (weekdays[weekdays.length - 1] instanceof Object) {
|
1393
|
+
if (this.rule == null) {
|
1394
|
+
throw "No recurrence rule given for ordered weekdays filter";
|
1395
|
+
}
|
1396
|
+
_ref = weekdays[weekdays.length - 1];
|
1397
|
+
for (day in _ref) {
|
1398
|
+
orders = _ref[day];
|
1399
|
+
day = !isNaN(parseFloat(day)) ? day : this.WEEKDAYS[day];
|
1400
|
+
if (orders.length == null) {
|
1401
|
+
orders = [orders];
|
1402
|
+
}
|
1403
|
+
this.orderedWeekdays[this.WEEKDAY_NAMES[day]] = orders.sort();
|
1404
|
+
}
|
1405
|
+
weekdays = weekdays.slice(0, -1);
|
1406
|
+
}
|
1407
|
+
this.weekdays = (function() {
|
1408
|
+
var _i, _len, _results;
|
1409
|
+
_results = [];
|
1410
|
+
for (_i = 0, _len = weekdays.length; _i < _len; _i++) {
|
1411
|
+
w = weekdays[_i];
|
1412
|
+
_results.push(!isNaN(parseFloat(w)) ? w : this.WEEKDAYS[w]);
|
1413
|
+
}
|
1414
|
+
return _results;
|
1415
|
+
}).call(this);
|
1416
|
+
this.weekdays.sort();
|
1417
|
+
}
|
1418
|
+
|
1419
|
+
WeekdaysFilter.prototype.match = function(date) {
|
1420
|
+
var day, first, max, occ, _ref;
|
1421
|
+
if (this.weekdays.indexOf(date.getDay()) >= 0) {
|
1422
|
+
return true;
|
1423
|
+
}
|
1424
|
+
day = this.WEEKDAY_NAMES[date.getDay()];
|
1425
|
+
if (this.orderedWeekdays[day] == null) {
|
1426
|
+
return false;
|
1427
|
+
}
|
1428
|
+
_ref = this._orderInInterval(date), first = _ref[0], occ = _ref[1], max = _ref[2];
|
1429
|
+
return this.orderedWeekdays[day].indexOf(occ) >= 0 || this.orderedWeekdays[day].indexOf(occ - max - 1) >= 0;
|
1430
|
+
};
|
1431
|
+
|
1432
|
+
WeekdaysFilter.prototype.step = function() {
|
1433
|
+
return {
|
1434
|
+
length: 1,
|
1435
|
+
unit: 'day',
|
1436
|
+
seconds: 846000
|
1437
|
+
};
|
1438
|
+
};
|
1439
|
+
|
1440
|
+
WeekdaysFilter.prototype.next = function(date) {
|
1441
|
+
var MAX_ITERATIONS;
|
1442
|
+
date = new Date(date);
|
1443
|
+
MAX_ITERATIONS = 10000;
|
1444
|
+
while (!this.match(date)) {
|
1445
|
+
if (!(MAX_ITERATIONS-- > 0)) {
|
1446
|
+
throw "Maximum iterations reached in WeekdaysFilter.next";
|
1447
|
+
}
|
1448
|
+
date.add(1).day();
|
1449
|
+
}
|
1450
|
+
return date;
|
1451
|
+
};
|
1452
|
+
|
1453
|
+
WeekdaysFilter.prototype.previous = function(date) {
|
1454
|
+
var MAX_ITERATIONS;
|
1455
|
+
date = new Date(date);
|
1456
|
+
MAX_ITERATIONS = 10000;
|
1457
|
+
while (!this.match(date)) {
|
1458
|
+
if (!(MAX_ITERATIONS-- > 0)) {
|
1459
|
+
throw "Maximum iterations reached in WeekdaysFilter.previous";
|
1460
|
+
}
|
1461
|
+
date.add(-1).day();
|
1462
|
+
}
|
1463
|
+
return date;
|
1464
|
+
};
|
1465
|
+
|
1466
|
+
WeekdaysFilter.prototype._orderInInterval = function(date) {
|
1467
|
+
var eoy, eyday, first, janfirst, max, occ, yday;
|
1468
|
+
janfirst = (new Date(date)).set({
|
1469
|
+
month: 0,
|
1470
|
+
day: 1
|
1471
|
+
});
|
1472
|
+
if (this.rule instanceof Schedule.Rules.YearlyRule) {
|
1473
|
+
first = (7 + date.getDay() - janfirst.getDay()) % 7 + 1;
|
1474
|
+
yday = Math.ceil((date - janfirst) / 1000 / 60 / 60 / 24) + 1;
|
1475
|
+
occ = ~~((yday - first) / 7) + 1;
|
1476
|
+
eoy = (new Date(date)).add(1).year().set({
|
1477
|
+
month: 0,
|
1478
|
+
day: 1
|
1479
|
+
}).add(-1).day();
|
1480
|
+
eyday = Math.ceil((eoy - janfirst) / 1000 / 60 / 60 / 24) + 1;
|
1481
|
+
max = ~~((eyday - first) / 7) + 1;
|
1482
|
+
} else if (this.rule instanceof Schedule.Rules.MonthlyRule) {
|
1483
|
+
first = (7 + date.getDay() - (new Date(date)).set({
|
1484
|
+
day: 1
|
1485
|
+
}).getDay()) % 7 + 1;
|
1486
|
+
occ = ~~((date.getDate() - first) / 7) + 1;
|
1487
|
+
max = ~~(((new Date(date)).add(1).month().set({
|
1488
|
+
day: 1
|
1489
|
+
}).add(-1).day().getDate() - first) / 7) + 1;
|
1490
|
+
} else {
|
1491
|
+
throw "Ordered weekdays filter only supports monthy and yearly rules. (" + this.rule["class"] + " given)";
|
1492
|
+
}
|
1493
|
+
return [first, occ, max];
|
1494
|
+
};
|
1495
|
+
|
1496
|
+
WeekdaysFilter.prototype.toString = function() {
|
1497
|
+
var dayNames, days, last, owdays, wdays,
|
1498
|
+
_this = this;
|
1499
|
+
dayNames = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
1500
|
+
wdays = _.map(this.weekdays, function(w) {
|
1501
|
+
return dayNames[w];
|
1502
|
+
});
|
1503
|
+
owdays = _.map(this.orderedWeekdays, function(ord, d) {
|
1504
|
+
return "" + (_.map(ord, function(o) {
|
1505
|
+
return "" + o + ".";
|
1506
|
+
}).join(", ")) + " " + dayNames[_this.WEEKDAYS[d]];
|
1507
|
+
});
|
1508
|
+
days = wdays.concat(owdays);
|
1509
|
+
last = days.pop();
|
1510
|
+
if (days.length > 0) {
|
1511
|
+
return "on " + (days.join(", ")) + " and " + last;
|
1512
|
+
} else {
|
1513
|
+
return "on " + last;
|
1514
|
+
}
|
1515
|
+
};
|
1516
|
+
|
1517
|
+
return WeekdaysFilter;
|
1518
|
+
|
1519
|
+
})();
|
1520
|
+
|
1521
|
+
}).call(this);
|
1522
|
+
|
1523
|
+
(function() {
|
1524
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
1525
|
+
__slice = [].slice;
|
1526
|
+
|
1527
|
+
Schedule.Filters.YeardaysFilter = (function() {
|
1528
|
+
function YeardaysFilter() {
|
1529
|
+
var yeardays;
|
1530
|
+
yeardays = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
1531
|
+
this.toString = __bind(this.toString, this);
|
1532
|
+
this.yearDay = __bind(this.yearDay, this);
|
1533
|
+
this.previous = __bind(this.previous, this);
|
1534
|
+
this.next = __bind(this.next, this);
|
1535
|
+
this.step = __bind(this.step, this);
|
1536
|
+
this.match = __bind(this.match, this);
|
1537
|
+
if (yeardays.length < 1) {
|
1538
|
+
throw "Specify at least one day of the month";
|
1539
|
+
}
|
1540
|
+
this.yeardays = yeardays.sort();
|
1541
|
+
}
|
1542
|
+
|
1543
|
+
YeardaysFilter.prototype.match = function(date) {
|
1544
|
+
var eoy, last;
|
1545
|
+
eoy = (new Date(date)).set({
|
1546
|
+
month: 0,
|
1547
|
+
day: 1
|
1548
|
+
}).add(1).year().add(-1).day();
|
1549
|
+
last = this.yearDay(eoy);
|
1550
|
+
return (this.yeardays.indexOf(this.yearDay(date)) >= 0) || (this.yeardays.indexOf(this.yearDay(date) - last - 1) >= 0);
|
1551
|
+
};
|
1552
|
+
|
1553
|
+
YeardaysFilter.prototype.step = function() {
|
1554
|
+
return {
|
1555
|
+
length: 1,
|
1556
|
+
unit: 'day',
|
1557
|
+
seconds: 86400
|
1558
|
+
};
|
1559
|
+
};
|
1560
|
+
|
1561
|
+
YeardaysFilter.prototype.next = function(date) {
|
1562
|
+
date = new Date(date);
|
1563
|
+
while (!this.match(date)) {
|
1564
|
+
date.add(1).day();
|
1565
|
+
}
|
1566
|
+
return date;
|
1567
|
+
};
|
1568
|
+
|
1569
|
+
YeardaysFilter.prototype.previous = function(date) {
|
1570
|
+
date = new Date(date);
|
1571
|
+
while (!this.match(date)) {
|
1572
|
+
date.add(-1).day();
|
1573
|
+
}
|
1574
|
+
return date;
|
1575
|
+
};
|
1576
|
+
|
1577
|
+
YeardaysFilter.prototype.yearDay = function(date) {
|
1578
|
+
var janFirst;
|
1579
|
+
date = new Date(date);
|
1580
|
+
janFirst = (new Date(date)).set({
|
1581
|
+
month: 0,
|
1582
|
+
day: 1
|
1583
|
+
});
|
1584
|
+
return Math.ceil((date - janFirst) / 86400000) + 1;
|
1585
|
+
};
|
1586
|
+
|
1587
|
+
YeardaysFilter.prototype.toString = function() {
|
1588
|
+
var days, last;
|
1589
|
+
days = _.map(this.yeardays, function(d) {
|
1590
|
+
return "" + d + ".";
|
1591
|
+
});
|
1592
|
+
last = days.pop();
|
1593
|
+
if (days.length > 0) {
|
1594
|
+
return "on " + (days.join(", ")) + " and " + last + " day";
|
1595
|
+
} else {
|
1596
|
+
return "on " + last + " day";
|
1597
|
+
}
|
1598
|
+
};
|
1599
|
+
|
1600
|
+
return YeardaysFilter;
|
1601
|
+
|
1602
|
+
})();
|
1603
|
+
|
1604
|
+
}).call(this);
|
1605
|
+
|
1606
|
+
(function() {
|
1607
|
+
Schedule.Suboccurrence = (function() {
|
1608
|
+
function Suboccurrence(attrs) {
|
1609
|
+
this.start = attrs.start;
|
1610
|
+
this.end = attrs.end;
|
1611
|
+
this.isOccurrenceStart = attrs.isOccurrenceStart;
|
1612
|
+
this.isOccurrenceEnd = attrs.isOccurrenceEnd;
|
1613
|
+
}
|
1614
|
+
|
1615
|
+
return Suboccurrence;
|
1616
|
+
|
1617
|
+
})();
|
1618
|
+
|
1619
|
+
Schedule.Suboccurrence.find = function(attrs) {
|
1620
|
+
var interval, occurrence, suboccurrence;
|
1621
|
+
if ((occurrence = attrs.occurrence).length == null) {
|
1622
|
+
throw "Missing occurrence";
|
1623
|
+
}
|
1624
|
+
if ((interval = attrs.interval).length == null) {
|
1625
|
+
throw "Missing interval";
|
1626
|
+
}
|
1627
|
+
if (occurrence[1] <= interval[0] || occurrence[0] >= interval[2]) {
|
1628
|
+
return null;
|
1629
|
+
}
|
1630
|
+
suboccurrence = {};
|
1631
|
+
if (occurrence[0] < interval[0]) {
|
1632
|
+
suboccurrence.start = interval[0];
|
1633
|
+
suboccurrence.isOccurrenceStart = false;
|
1634
|
+
} else {
|
1635
|
+
suboccurrence.start = occurrence[0];
|
1636
|
+
suboccurrence.isOccurrenceStart = true;
|
1637
|
+
}
|
1638
|
+
if (occurrence[1] > interval[1]) {
|
1639
|
+
suboccurrence.end = interval[1];
|
1640
|
+
suboccurrence.isOccurrenceEnd = false;
|
1641
|
+
} else {
|
1642
|
+
suboccurrence.end = occurrence[1];
|
1643
|
+
suboccurrence.isOccurrenceEnd = true;
|
1644
|
+
}
|
1645
|
+
return new Schedule.Suboccurrence(suboccurrence);
|
1646
|
+
};
|
1647
|
+
|
1648
|
+
}).call(this);
|
1649
|
+
|
1650
|
+
(function() {
|
1651
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
1652
|
+
|
1653
|
+
Schedule.Occurrence = (function() {
|
1654
|
+
function Occurrence(rule, startTime) {
|
1655
|
+
this._initLoop = __bind(this._initLoop, this);
|
1656
|
+
this._listOccurrences = __bind(this._listOccurrences, this);
|
1657
|
+
this.toObject = __bind(this.toObject, this);
|
1658
|
+
this.all = __bind(this.all, this);
|
1659
|
+
this.suboccurrencesBetween = __bind(this.suboccurrencesBetween, this);
|
1660
|
+
this.occurrencesBetween = __bind(this.occurrencesBetween, this);
|
1661
|
+
this.previousOccurrences = __bind(this.previousOccurrences, this);
|
1662
|
+
this.previousOccurrence = __bind(this.previousOccurrence, this);
|
1663
|
+
this.nextOccurrences = __bind(this.nextOccurrences, this);
|
1664
|
+
this.nextOccurrence = __bind(this.nextOccurrence, this);
|
1665
|
+
this.rule = rule;
|
1666
|
+
this.startTime = this.rule.match(startTime, startTime) ? startTime : this.rule.next(startTime, startTime);
|
1667
|
+
}
|
1668
|
+
|
1669
|
+
Occurrence.prototype.nextOccurrence = function(after) {
|
1670
|
+
return this.nextOccurrences(1, after)[0];
|
1671
|
+
};
|
1672
|
+
|
1673
|
+
Occurrence.prototype.nextOccurrences = function(n, after) {
|
1674
|
+
var time;
|
1675
|
+
if ((this.rule.stop() != null) && after > this.rule.stop()) {
|
1676
|
+
return [];
|
1677
|
+
}
|
1678
|
+
time = (after <= this.startTime ? this.startTime : after);
|
1679
|
+
if (!this.rule.match(time, this.startTime)) {
|
1680
|
+
time = this.rule.next(time, this.startTime);
|
1681
|
+
}
|
1682
|
+
return this._listOccurrences(time, function() {
|
1683
|
+
return (n -= 1) >= 0;
|
1684
|
+
});
|
1685
|
+
};
|
1686
|
+
|
1687
|
+
Occurrence.prototype.previousOccurrence = function(before) {
|
1688
|
+
return this.previousOccurrences(1, before)[0];
|
1689
|
+
};
|
1690
|
+
|
1691
|
+
Occurrence.prototype.previousOccurrences = function(n, before) {
|
1692
|
+
var time;
|
1693
|
+
if (before <= this.startTime) {
|
1694
|
+
return [];
|
1695
|
+
}
|
1696
|
+
time = ((this.rule.stop() == null) || before < this.rule.stop() ? before : this.rule.stop());
|
1697
|
+
time = this.rule.previous(time, this.startTime);
|
1698
|
+
return this._listOccurrences(time, 'back', function() {
|
1699
|
+
return (n -= 1) >= 0;
|
1700
|
+
}).reverse();
|
1701
|
+
};
|
1702
|
+
|
1703
|
+
Occurrence.prototype.occurrencesBetween = function(t1, t2) {
|
1704
|
+
var time;
|
1705
|
+
if (!(t2 > t1)) {
|
1706
|
+
throw "Empty time interval";
|
1707
|
+
}
|
1708
|
+
if (t2 <= this.startTime || (this.rule.stop() != null) && t1 >= this.rule.stop()) {
|
1709
|
+
return [];
|
1710
|
+
}
|
1711
|
+
time = (t1 <= this.startTime ? this.startTime : t1);
|
1712
|
+
if (!this.rule.match(time, this.startTime)) {
|
1713
|
+
time = this.rule.next(time, this.startTime);
|
1714
|
+
}
|
1715
|
+
return this._listOccurrences(time, function(t) {
|
1716
|
+
return t < t2;
|
1717
|
+
});
|
1718
|
+
};
|
1719
|
+
|
1720
|
+
Occurrence.prototype.suboccurrencesBetween = function(t1, t2) {
|
1721
|
+
var occ, occurrences, _i, _len, _results;
|
1722
|
+
occurrences = this.occurrencesBetween(new Date(t1 - this.duration), t2);
|
1723
|
+
_results = [];
|
1724
|
+
for (_i = 0, _len = occurrences.length; _i < _len; _i++) {
|
1725
|
+
occ = occurrences[_i];
|
1726
|
+
_results.push(Schedule.Suboccurrence.find({
|
1727
|
+
occurrence: [occ, new Date(+occ + this.duration)],
|
1728
|
+
interval: [t1, t2]
|
1729
|
+
}));
|
1730
|
+
}
|
1731
|
+
return _results;
|
1732
|
+
};
|
1733
|
+
|
1734
|
+
Occurrence.prototype.all = function() {
|
1735
|
+
var n, rule;
|
1736
|
+
if (this.rule.stop() != null) {
|
1737
|
+
rule = this.rule;
|
1738
|
+
return this._listOccurrences(this.startTime, function(t) {
|
1739
|
+
return t < rule.stop();
|
1740
|
+
});
|
1741
|
+
} else {
|
1742
|
+
n = this.rule.count();
|
1743
|
+
return this._listOccurrences(this.startTime, function() {
|
1744
|
+
return (n -= 1) >= 0;
|
1745
|
+
});
|
1746
|
+
}
|
1747
|
+
};
|
1748
|
+
|
1749
|
+
Occurrence.prototype.toObject = function() {
|
1750
|
+
return this.rule.toObject();
|
1751
|
+
};
|
1752
|
+
|
1753
|
+
Occurrence.prototype._listOccurrences = function(from, direction_or_func, func) {
|
1754
|
+
var MAX_ITERATIONS, current, direction, n, results, _ref;
|
1755
|
+
if (!this.rule.match(from, this.startTime)) {
|
1756
|
+
throw "From " + from + " not matching the rule " + this.rule + " and start time " + this.startTime;
|
1757
|
+
}
|
1758
|
+
if (func != null) {
|
1759
|
+
direction = direction_or_func;
|
1760
|
+
} else {
|
1761
|
+
direction = 'forward';
|
1762
|
+
func = direction_or_func;
|
1763
|
+
}
|
1764
|
+
results = [];
|
1765
|
+
_ref = this._initLoop(from, direction), n = _ref[0], current = _ref[1];
|
1766
|
+
MAX_ITERATIONS = 10000;
|
1767
|
+
while (true) {
|
1768
|
+
if (!(MAX_ITERATIONS-- > 0)) {
|
1769
|
+
throw "Maximum iterations reached when listing occurrences...";
|
1770
|
+
}
|
1771
|
+
if (!((current >= this.startTime) && ((this.rule.stop() == null) || current < this.rule.stop()) && ((this.rule.count() == null) || (n -= 1) >= 0))) {
|
1772
|
+
return results;
|
1773
|
+
}
|
1774
|
+
if (!func(current)) {
|
1775
|
+
return results;
|
1776
|
+
}
|
1777
|
+
results.push(current);
|
1778
|
+
if (direction === 'forward') {
|
1779
|
+
current = this.rule.next(current, this.startTime);
|
1780
|
+
} else {
|
1781
|
+
current = this.rule.previous(current, this.startTime);
|
1782
|
+
}
|
1783
|
+
}
|
1784
|
+
};
|
1785
|
+
|
1786
|
+
Occurrence.prototype._initLoop = function(from, direction) {
|
1787
|
+
var current, n;
|
1788
|
+
if (this.rule.count() == null) {
|
1789
|
+
return [0, from];
|
1790
|
+
}
|
1791
|
+
if (direction === 'forward') {
|
1792
|
+
n = 0;
|
1793
|
+
current = this.startTime;
|
1794
|
+
while (current < from) {
|
1795
|
+
n += 1;
|
1796
|
+
current = this.rule.next(current, this.startTime);
|
1797
|
+
}
|
1798
|
+
return [this.rule.count() - n, current];
|
1799
|
+
} else {
|
1800
|
+
n = 0;
|
1801
|
+
current = this.startTime;
|
1802
|
+
while (current < from && (n += 1) < this.rule.count()) {
|
1803
|
+
current = this.rule.next(current, this.startTime);
|
1804
|
+
}
|
1805
|
+
return [this.rule.count(), current];
|
1806
|
+
}
|
1807
|
+
};
|
1808
|
+
|
1809
|
+
return Occurrence;
|
1810
|
+
|
1811
|
+
})();
|
1812
|
+
|
1813
|
+
}).call(this);
|