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 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