cyclical-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|