fugit 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +63 -3
- data/lib/fugit/core.rb +70 -0
- data/lib/fugit/cron.rb +26 -4
- data/lib/fugit/duration.rb +331 -0
- data/lib/fugit.rb +4 -1
- metadata +16 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2828bf125d6707c54707f45157f4b84972370fe
|
4
|
+
data.tar.gz: 620ab55025dcebea9b332b4e2610631527659313
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3012a5dccfb5a63d860a1b83dff62a331f903d470e34084a7f35fca2d47e3facf5a8615f5d0fd818e6fba7650e3015208b6754336fa41b20b0e623f3bf48bb31
|
7
|
+
data.tar.gz: 320140191d5baffc8765ae2776e534a0b5f041f6e8bc315548d03969ebe011e6f79cd152366859e7486659e4eb2679159ac2905b646e7444919ed25ba2d25474
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
# fugit CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
+
## fugit 0.9.1 released 2017-01-03
|
6
|
+
|
7
|
+
* Implement Fugit::Duration #inflate and #deflate
|
8
|
+
* Bring in Fugit::Duration
|
9
|
+
* Implement Fugit .parse, .parse_at and .parse_cron
|
10
|
+
|
11
|
+
|
5
12
|
## fugit 0.9.0 released 2017-01-03
|
6
13
|
|
7
14
|
* Initial release
|
data/README.md
CHANGED
@@ -4,18 +4,52 @@
|
|
4
4
|
[![Build Status](https://secure.travis-ci.org/floraison/fugit.svg)](http://travis-ci.org/floraison/fugit)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/fugit.svg)](http://badge.fury.io/rb/fugit)
|
6
6
|
|
7
|
-
Time tools for [flor](https://github.com/floraison/flor) and the floraison
|
7
|
+
Time tools for [flor](https://github.com/floraison/flor) and the floraison group.
|
8
|
+
|
9
|
+
Fugit will probably become the foundation for [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) 4.x
|
10
|
+
|
11
|
+
|
12
|
+
## Related projects
|
13
|
+
|
14
|
+
### Sister projects
|
15
|
+
|
16
|
+
* [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) - a cron/at/in/every/interval in-process scheduler, in fact, it's the father project to this fugit project
|
17
|
+
* [flor](https://github.com/floraison/flor) - a Ruby workflow engine, fugit provides the foundation for its time scheduling capabilities
|
18
|
+
|
19
|
+
### Similar, somehow overlapping projects
|
20
|
+
|
21
|
+
* [chronic](https://github.com/mojombo/chronic) - a pure Ruby natural language date parser
|
22
|
+
* [parse-cron](https://github.com/siebertm/parse-cron) - parses cron expressions and calculates the next occurence after a given date
|
23
|
+
* [ice_cube](https://github.com/seejohnrun/ice_cube) - Ruby date recurrence library
|
24
|
+
* [ISO8601](https://github.com/arnau/ISO8601) - Ruby parser to work with ISO8601 dateTimes and durations
|
25
|
+
* ...
|
26
|
+
|
8
27
|
|
9
28
|
## `Fugit::Cron`
|
10
29
|
|
30
|
+
A class `Fugit::Cron` to parse cron strings and then `#next_time` and `#previous_time` to compute the next or the previous occurrence respectively.
|
31
|
+
|
32
|
+
There is also a `#brute_frequency` method which returns an array `[ shortest delta, longest delta, occurrence count ]` where delta is the time between two occurences.
|
33
|
+
|
11
34
|
```ruby
|
12
35
|
require 'fugit'
|
13
36
|
|
14
37
|
c = Fugit::Cron.parse('0 0 * * sun')
|
38
|
+
# or
|
39
|
+
c = Fugit::Cron.new('0 0 * * sun')
|
15
40
|
|
16
|
-
p Time.now
|
41
|
+
p Time.now # => 2017-01-03 09:53:27 +0900
|
17
42
|
|
18
|
-
p c.next_time
|
43
|
+
p c.next_time # => 2017-01-08 00:00:00 +0900
|
44
|
+
p c.previous_time # => 2017-01-01 00:00:00 +0900
|
45
|
+
|
46
|
+
p c.brute_frequency # => [ 604800, 604800, 53 ]
|
47
|
+
# [ delta min, delta max, occurrence count ]
|
48
|
+
|
49
|
+
p c.match?(Time.parse('2017-08-06')) # => true
|
50
|
+
p c.match?(Time.parse('2017-08-07')) # => false
|
51
|
+
p c.match?('2017-08-06') # => true
|
52
|
+
p c.match?('2017-08-06 12:00') # => false
|
19
53
|
```
|
20
54
|
|
21
55
|
Example of cron strings understood by fugit:
|
@@ -40,6 +74,32 @@ Example of cron strings understood by fugit:
|
|
40
74
|
# and more...
|
41
75
|
```
|
42
76
|
|
77
|
+
## `Fugit::Duration`
|
78
|
+
|
79
|
+
A class `Fugit::Duration` to parse duration strings (vanilla [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) ones and [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) ones.
|
80
|
+
|
81
|
+
Provides duration arithmetic tools.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
require 'fugit'
|
85
|
+
|
86
|
+
d = Fugit::Duration.parse('1y2M1d4h')
|
87
|
+
|
88
|
+
p d.to_plain_s # => "1Y2M1D4h"
|
89
|
+
p d.to_iso_s # => "P1Y2M1DT4H" ISO 8601 duration
|
90
|
+
p d.to_long_s # => "1 year, 2 months, 1 day, and 4 hours"
|
91
|
+
|
92
|
+
d += Fugit::Duration.parse('1y1h')
|
93
|
+
|
94
|
+
p d.to_long_s # => "2 years, 2 months, 1 day, and 5 hours"
|
95
|
+
|
96
|
+
d += 3600
|
97
|
+
|
98
|
+
p d.to_plain_s # => "2Y2M1D5h3600s"
|
99
|
+
```
|
100
|
+
TODO: continue me
|
101
|
+
|
102
|
+
|
43
103
|
## LICENSE
|
44
104
|
|
45
105
|
MIT, see [LICENSE.txt](LICENSE.txt)
|
data/lib/fugit/core.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2017-2017, John Mettraux, jmettraux+flor@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
module Fugit
|
27
|
+
|
28
|
+
def self.parse_at(s)
|
29
|
+
|
30
|
+
Time.parse(s) rescue nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.do_parse_at(s)
|
34
|
+
|
35
|
+
return s if s.is_a?(Time)
|
36
|
+
Time.parse(s)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse_cron(s)
|
40
|
+
|
41
|
+
::Fugit::Cron.parse(s)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.do_parse_cron(s)
|
45
|
+
|
46
|
+
::Fugit::Cron.do_parse(s)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.parse_duration(s)
|
50
|
+
|
51
|
+
::Fugit::Duration.parse(s)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.do_parse_duration(s)
|
55
|
+
|
56
|
+
::Fugit::Duration.do_parse(s)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parse(s)
|
60
|
+
|
61
|
+
parse_duration(s) || parse_at(s) || parse_cron(s)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.do_parse(s)
|
65
|
+
|
66
|
+
parse(s) ||
|
67
|
+
fail(ArgumentError.new("fugit found no time information in #{s}.inspect"))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
data/lib/fugit/cron.rb
CHANGED
@@ -61,19 +61,24 @@ module Fugit
|
|
61
61
|
|
62
62
|
def self.parse(s)
|
63
63
|
|
64
|
+
return s if s.is_a?(self)
|
65
|
+
|
64
66
|
original = s
|
65
67
|
s = SPECIALS[s] || s
|
66
68
|
|
67
69
|
#p s; Raabro.pp(Parser.parse(s, debug: 3))
|
68
70
|
h = Parser.parse(s)
|
69
71
|
|
70
|
-
|
71
|
-
"couldn't parse #{original.inspect}"
|
72
|
-
) unless h
|
72
|
+
return nil unless h
|
73
73
|
|
74
74
|
self.allocate.send(:init, s, h)
|
75
75
|
end
|
76
76
|
|
77
|
+
def self.do_parse(s)
|
78
|
+
|
79
|
+
parse(s) || fail(ArgumentError.new("not a cron string #{s.inspect}"))
|
80
|
+
end
|
81
|
+
|
77
82
|
class NextTime # TODO at some point, use ZoTime
|
78
83
|
|
79
84
|
def initialize(t)
|
@@ -175,6 +180,7 @@ module Fugit
|
|
175
180
|
|
176
181
|
def match?(t)
|
177
182
|
|
183
|
+
t = Fugit.do_parse_at(t)
|
178
184
|
t = NextTime.new(t)
|
179
185
|
|
180
186
|
month_match?(t) && day_match?(t) && hour_match?(t) && min_match?(t)
|
@@ -216,7 +222,7 @@ module Fugit
|
|
216
222
|
# Returns [ min delta, max delta, occurence count ]
|
217
223
|
# Computes for a non leap year (2017).
|
218
224
|
#
|
219
|
-
def
|
225
|
+
def brute_frequency(year=2017)
|
220
226
|
|
221
227
|
FREQUENCY_CACHE["#{to_cron_s}|#{year}"] ||=
|
222
228
|
begin
|
@@ -234,6 +240,22 @@ module Fugit
|
|
234
240
|
end
|
235
241
|
end
|
236
242
|
|
243
|
+
def to_a
|
244
|
+
|
245
|
+
[ @minutes, @hours, @monthdays, @months, @weekdays ]
|
246
|
+
end
|
247
|
+
|
248
|
+
def ==(o)
|
249
|
+
|
250
|
+
o.is_a?(::Fugit::Cron) && o.to_a == to_a
|
251
|
+
end
|
252
|
+
alias eql? ==
|
253
|
+
|
254
|
+
def hash
|
255
|
+
|
256
|
+
to_a.hash
|
257
|
+
end
|
258
|
+
|
237
259
|
protected
|
238
260
|
|
239
261
|
FREQUENCY_CACHE = {}
|
@@ -0,0 +1,331 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2017-2017, John Mettraux, jmettraux+flor@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
module Fugit
|
27
|
+
|
28
|
+
class Duration
|
29
|
+
|
30
|
+
attr_reader :original, :h
|
31
|
+
|
32
|
+
def self.new(s)
|
33
|
+
|
34
|
+
parse(s)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.parse(s, opts={})
|
38
|
+
|
39
|
+
return s if s.is_a?(self)
|
40
|
+
|
41
|
+
original = s
|
42
|
+
|
43
|
+
s = s
|
44
|
+
s = s.to_i if s.is_a?(Numeric)
|
45
|
+
s = s.to_s.strip
|
46
|
+
s = s + 's' if s.match(/\A-?\d+\z/)
|
47
|
+
#p [ original, s ]; Raabro.pp(Parser.parse(s, debug: 3))
|
48
|
+
|
49
|
+
h =
|
50
|
+
if opts[:iso]
|
51
|
+
IsoParser.parse(opts[:stricter] ? s : s.upcase)
|
52
|
+
elsif opts[:plain]
|
53
|
+
Parser.parse(s)
|
54
|
+
else
|
55
|
+
Parser.parse(s) || IsoParser.parse(opts[:stricter] ? s : s.upcase)
|
56
|
+
end
|
57
|
+
|
58
|
+
h ? self.allocate.send(:init, original, h) : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.do_parse(s, opts={})
|
62
|
+
|
63
|
+
parse(s, opts) || fail(ArgumentError.new("not a duration #{s.inspect}"))
|
64
|
+
end
|
65
|
+
|
66
|
+
KEYS = {
|
67
|
+
yea: { a: 'Y', i: 'Y', s: 365 * 24 * 3600, x: 0, l: 'year' },
|
68
|
+
mon: { a: 'M', i: 'M', s: 30 * 24 * 3600, x: 1, l: 'month' },
|
69
|
+
wee: { a: 'W', i: 'W', s: 7 * 24 * 3600, I: true, l: 'week' },
|
70
|
+
day: { a: 'D', i: 'D', s: 24 * 3600, I: true, l: 'day' },
|
71
|
+
hou: { a: 'h', i: 'H', s: 3600, I: true, l: 'hour' },
|
72
|
+
min: { a: 'm', i: 'M', s: 60, I: true, l: 'minute' },
|
73
|
+
sec: { a: 's', i: 'S', s: 1, I: true, l: 'second' },
|
74
|
+
}
|
75
|
+
INFLA_KEYS, NON_INFLA_KEYS =
|
76
|
+
KEYS.partition { |k, v| v[:I] }
|
77
|
+
|
78
|
+
def to_plain_s
|
79
|
+
|
80
|
+
KEYS.inject(StringIO.new) { |s, (k, a)|
|
81
|
+
v = @h[k]; next s unless v; s << v.to_s; s << a[:a]
|
82
|
+
}.string
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_iso_s
|
86
|
+
|
87
|
+
t = false
|
88
|
+
|
89
|
+
s = StringIO.new
|
90
|
+
s << 'P'
|
91
|
+
|
92
|
+
KEYS.each_with_index do |(k, a), i|
|
93
|
+
v = @h[k]; next unless v
|
94
|
+
if i > 3 && t == false
|
95
|
+
t = true
|
96
|
+
s << 'T'
|
97
|
+
end
|
98
|
+
s << v.to_s; s << a[:i]
|
99
|
+
end
|
100
|
+
|
101
|
+
s.string
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_long_s(opts={})
|
105
|
+
|
106
|
+
s = StringIO.new
|
107
|
+
adn = [ false, 'no' ].include?(opts[:oxford]) ? ' and ' : ', and '
|
108
|
+
|
109
|
+
a = @h.to_a
|
110
|
+
while kv = a.shift
|
111
|
+
k, v = kv
|
112
|
+
aa = KEYS[k]
|
113
|
+
s << v.to_i
|
114
|
+
s << ' '; s << aa[:l]; s << 's' if v > 1
|
115
|
+
s << (a.size == 1 ? adn : ', ') if a.size > 0
|
116
|
+
end
|
117
|
+
|
118
|
+
s.string
|
119
|
+
end
|
120
|
+
|
121
|
+
# Warning: this is an "approximation", months are 30 days and years are
|
122
|
+
# 365 days, ...
|
123
|
+
#
|
124
|
+
def to_sec
|
125
|
+
|
126
|
+
KEYS.inject(0) { |s, (k, a)| v = @h[k]; next s unless v; s += v * a[:s] }
|
127
|
+
end
|
128
|
+
|
129
|
+
def inflate
|
130
|
+
|
131
|
+
h =
|
132
|
+
@h.inject({ sec: 0 }) { |h, (k, v)|
|
133
|
+
a = KEYS[k]
|
134
|
+
if a[:I]
|
135
|
+
h[:sec] += (v * a[:s])
|
136
|
+
else
|
137
|
+
h[k] = v
|
138
|
+
end
|
139
|
+
h
|
140
|
+
}
|
141
|
+
|
142
|
+
self.class.allocate.init(@original, h)
|
143
|
+
end
|
144
|
+
|
145
|
+
def deflate
|
146
|
+
|
147
|
+
id = inflate
|
148
|
+
h = id.h.dup
|
149
|
+
s = h.delete(:sec)
|
150
|
+
|
151
|
+
INFLA_KEYS.each do |k, v|
|
152
|
+
|
153
|
+
n = s / v[:s]; next if n == 0
|
154
|
+
m = s % v[:s]
|
155
|
+
|
156
|
+
h[k] = (h[k] || 0) + n
|
157
|
+
s = m
|
158
|
+
end
|
159
|
+
|
160
|
+
self.class.allocate.init(@original, h)
|
161
|
+
end
|
162
|
+
|
163
|
+
def opposite
|
164
|
+
|
165
|
+
h = @h.inject({}) { |h, (k, v)| h[k] = -v; h }
|
166
|
+
|
167
|
+
self.class.allocate.init(nil, h)
|
168
|
+
end
|
169
|
+
|
170
|
+
alias -@ opposite
|
171
|
+
|
172
|
+
def add_numeric(n)
|
173
|
+
|
174
|
+
h = @h.dup
|
175
|
+
h[:sec] = (h[:sec] || 0) + n.to_i
|
176
|
+
|
177
|
+
self.class.allocate.init(nil, h)
|
178
|
+
end
|
179
|
+
|
180
|
+
def add_duration(d)
|
181
|
+
|
182
|
+
h = d.h.inject(@h.dup) { |h, (k, v)| h[k] = (h[k] || 0) + v; h }
|
183
|
+
|
184
|
+
self.class.allocate.init(nil, h)
|
185
|
+
end
|
186
|
+
|
187
|
+
def add_to_time(t)
|
188
|
+
|
189
|
+
INFLA_KEYS.each do |k, a|
|
190
|
+
|
191
|
+
v = @h[k]; next unless v
|
192
|
+
|
193
|
+
t = t + v * a[:s]
|
194
|
+
end
|
195
|
+
|
196
|
+
NON_INFLA_KEYS.each do |k, a|
|
197
|
+
|
198
|
+
v = @h[k]; next unless v
|
199
|
+
at = [ t.year, t.month, t.day, t.hour, t.min, t.sec ]
|
200
|
+
|
201
|
+
at[a[:x]] += v
|
202
|
+
|
203
|
+
if at[1] > 12
|
204
|
+
n, m = at[1] / 12, at[1] % 12
|
205
|
+
at[0], at[1] = at[0] + n, m
|
206
|
+
elsif at[1] < 1
|
207
|
+
n, m = -at[1] / 12, -at[1] % 12
|
208
|
+
at[0], at[1] = at[0] - n, m
|
209
|
+
end
|
210
|
+
|
211
|
+
t = Time.send(t.utc? ? :utc : :local, *at)
|
212
|
+
end
|
213
|
+
|
214
|
+
t
|
215
|
+
end
|
216
|
+
|
217
|
+
def add(a)
|
218
|
+
|
219
|
+
case a
|
220
|
+
when Numeric then add_numeric(a)
|
221
|
+
when Fugit::Duration then add_duration(a)
|
222
|
+
when String then add_duration(self.class.parse(a))
|
223
|
+
when Time then add_to_time(a)
|
224
|
+
else fail ArgumentError.new(
|
225
|
+
"cannot add #{a.class} instance to a Fugit::Duration")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
alias + add
|
229
|
+
|
230
|
+
def substract(a)
|
231
|
+
|
232
|
+
case a
|
233
|
+
when Numeric then add_numeric(-a)
|
234
|
+
when Fugit::Duration then add_duration(-a)
|
235
|
+
when String then add_duration(-self.class.parse(a))
|
236
|
+
when Time then opposite.add_to_time(a)
|
237
|
+
else fail ArgumentError.new(
|
238
|
+
"cannot substract #{a.class} instance to a Fugit::Duration")
|
239
|
+
end
|
240
|
+
end
|
241
|
+
alias - substract
|
242
|
+
|
243
|
+
def ==(o)
|
244
|
+
|
245
|
+
o.is_a?(Fugit::Duration) && o.h == @h
|
246
|
+
end
|
247
|
+
alias eql? ==
|
248
|
+
|
249
|
+
def hash
|
250
|
+
|
251
|
+
@h.hash
|
252
|
+
end
|
253
|
+
|
254
|
+
protected
|
255
|
+
|
256
|
+
def init(original, h)
|
257
|
+
|
258
|
+
@original = original
|
259
|
+
|
260
|
+
@h = h.reject { |k, v| v == 0 }
|
261
|
+
# which copies h btw
|
262
|
+
|
263
|
+
self
|
264
|
+
end
|
265
|
+
|
266
|
+
module Parser include Raabro
|
267
|
+
|
268
|
+
def sep(i); rex(nil, i, /([ \t,]+|and)*/i); end
|
269
|
+
|
270
|
+
def yea(i); rex(:yea, i, /-?\d+ *y(ears?)?/i); end
|
271
|
+
def mon(i); rex(:mon, i, /-?\d+ *(M|months?)/); end
|
272
|
+
def wee(i); rex(:wee, i, /-?\d+ *(weeks?|w)/i); end
|
273
|
+
def day(i); rex(:day, i, /-?\d+ *(days?|d)/i); end
|
274
|
+
def hou(i); rex(:hou, i, /-?\d+ *(hours?|h)/i); end
|
275
|
+
def min(i); rex(:min, i, /-?\d+ *(mins?|minutes?|m)/); end
|
276
|
+
|
277
|
+
def sec(i); rex(:sec, i, /-?\d+ *(secs?|seconds?|s)/i); end
|
278
|
+
# always last!
|
279
|
+
|
280
|
+
def elt(i); alt(nil, i, :yea, :mon, :wee, :day, :hou, :min, :sec); end
|
281
|
+
|
282
|
+
def dur(i); jseq(:dur, i, :elt, :sep); end
|
283
|
+
|
284
|
+
def rewrite_dur(t)
|
285
|
+
|
286
|
+
t
|
287
|
+
.subgather(nil)
|
288
|
+
.inject({}) { |h, t|
|
289
|
+
h[t.name] = (h[t.name] || 0) + t.string.to_i
|
290
|
+
# drops ending ("y", "m", ...) by itself
|
291
|
+
h
|
292
|
+
}
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
module IsoParser include Raabro
|
297
|
+
|
298
|
+
def p(i); rex(nil, i, /P/); end
|
299
|
+
def t(i); rex(nil, i, /T/); end
|
300
|
+
|
301
|
+
def yea(i); rex(:yea, i, /-?\d+Y/); end
|
302
|
+
def mon(i); rex(:mon, i, /-?\d+M/); end
|
303
|
+
def wee(i); rex(:wee, i, /-?\d+W/); end
|
304
|
+
def day(i); rex(:day, i, /-?\d+D/); end
|
305
|
+
def hou(i); rex(:hou, i, /-?\d+H/); end
|
306
|
+
def min(i); rex(:min, i, /-?\d+M/); end
|
307
|
+
def sec(i); rex(:sec, i, /-?\d+S/); end
|
308
|
+
|
309
|
+
def delt(i); alt(nil, i, :yea, :mon, :wee, :day); end
|
310
|
+
def telt(i); alt(nil, i, :hou, :min, :sec); end
|
311
|
+
|
312
|
+
def date(i); rep(nil, i, :delt, 1); end
|
313
|
+
def time(i); rep(nil, i, :telt, 1); end
|
314
|
+
def t_time(i); seq(nil, i, :t, :time); end
|
315
|
+
|
316
|
+
def dur(i); seq(:dur, i, :p, :date, '?', :t_time, '?'); end
|
317
|
+
|
318
|
+
def rewrite_dur(t)
|
319
|
+
|
320
|
+
t
|
321
|
+
.subgather(nil)
|
322
|
+
.inject({}) { |h, t|
|
323
|
+
h[t.name] = (h[t.name] || 0) + t.string.to_i
|
324
|
+
# drops ending ("y", "m", ...) by itself
|
325
|
+
h
|
326
|
+
}
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
data/lib/fugit.rb
CHANGED
@@ -25,13 +25,16 @@
|
|
25
25
|
|
26
26
|
module Fugit
|
27
27
|
|
28
|
-
VERSION = '0.9.
|
28
|
+
VERSION = '0.9.1'
|
29
29
|
end
|
30
30
|
|
31
31
|
require 'time'
|
32
|
+
require 'stringio'
|
32
33
|
|
33
34
|
require 'raabro'
|
34
35
|
|
36
|
+
require 'fugit/core'
|
35
37
|
require 'fugit/misc'
|
36
38
|
require 'fugit/cron'
|
39
|
+
require 'fugit/duration'
|
37
40
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fugit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
@@ -14,28 +14,28 @@ dependencies:
|
|
14
14
|
name: raabro
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.1.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.1.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '3.4'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.4'
|
41
41
|
description: Time tools for flor and the floraison project. Cron parsing and occurence
|
@@ -46,15 +46,17 @@ executables: []
|
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
|
-
- Makefile
|
50
|
-
- lib/fugit/cron.rb
|
51
|
-
- lib/fugit/misc.rb
|
52
|
-
- lib/fugit.rb
|
53
|
-
- fugit.gemspec
|
54
|
-
- LICENSE.txt
|
55
49
|
- CHANGELOG.md
|
56
50
|
- CREDITS.md
|
51
|
+
- LICENSE.txt
|
52
|
+
- Makefile
|
57
53
|
- README.md
|
54
|
+
- fugit.gemspec
|
55
|
+
- lib/fugit.rb
|
56
|
+
- lib/fugit/core.rb
|
57
|
+
- lib/fugit/cron.rb
|
58
|
+
- lib/fugit/duration.rb
|
59
|
+
- lib/fugit/misc.rb
|
58
60
|
homepage: http://github.com/floraison/fugit
|
59
61
|
licenses:
|
60
62
|
- MIT
|
@@ -65,17 +67,17 @@ require_paths:
|
|
65
67
|
- lib
|
66
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
67
69
|
requirements:
|
68
|
-
- -
|
70
|
+
- - ">="
|
69
71
|
- !ruby/object:Gem::Version
|
70
72
|
version: '0'
|
71
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
74
|
requirements:
|
73
|
-
- -
|
75
|
+
- - ">="
|
74
76
|
- !ruby/object:Gem::Version
|
75
77
|
version: '0'
|
76
78
|
requirements: []
|
77
79
|
rubyforge_project:
|
78
|
-
rubygems_version: 2.
|
80
|
+
rubygems_version: 2.4.5.1
|
79
81
|
signing_key:
|
80
82
|
specification_version: 4
|
81
83
|
summary: time tools for flor
|