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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23a78b668f05dc4bbe20ff46e0596a1211767f8a
4
- data.tar.gz: a93498a901fa05952adf0afa0362ca5621a24b3b
3
+ metadata.gz: c2828bf125d6707c54707f45157f4b84972370fe
4
+ data.tar.gz: 620ab55025dcebea9b332b4e2610631527659313
5
5
  SHA512:
6
- metadata.gz: a059da28856f3695800f15449b2245c844a3927170a2df6f9b09081570dfaa7239c4e240dca42d518828a615bc9ad73331d34e83948e352bd7eda18aa8edbb77
7
- data.tar.gz: 7588ef1425a8c11e3663ea2ec5de69d1f9ff76ff947a2871f9cc33b4479f7595c340a1058fb3b5f287a29b589d4ec30404167f4926b02efc41508642d9106130
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 project.
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 # => 2017-01-03 09:53:27 +0900
41
+ p Time.now # => 2017-01-03 09:53:27 +0900
17
42
 
18
- p c.next_time # => 2017-01-08 00:00:00 +0900
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
- fail ArgumentError.new(
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 frequency(year=2017)
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.0'
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.0
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.0.14
80
+ rubygems_version: 2.4.5.1
79
81
  signing_key:
80
82
  specification_version: 4
81
83
  summary: time tools for flor