fugit 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fugit might be problematic. Click here for more details.
- 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
|