fugit 0.1.0 → 0.9.0
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 +8 -0
- data/CREDITS.md +7 -0
- data/README.md +40 -0
- data/fugit.gemspec +3 -3
- data/lib/fugit.rb +8 -1
- data/lib/fugit/cron.rb +440 -0
- data/lib/fugit/misc.rb +56 -0
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23a78b668f05dc4bbe20ff46e0596a1211767f8a
|
4
|
+
data.tar.gz: a93498a901fa05952adf0afa0362ca5621a24b3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a059da28856f3695800f15449b2245c844a3927170a2df6f9b09081570dfaa7239c4e240dca42d518828a615bc9ad73331d34e83948e352bd7eda18aa8edbb77
|
7
|
+
data.tar.gz: 7588ef1425a8c11e3663ea2ec5de69d1f9ff76ff947a2871f9cc33b4479f7595c340a1058fb3b5f287a29b589d4ec30404167f4926b02efc41508642d9106130
|
data/CHANGELOG.md
ADDED
data/CREDITS.md
ADDED
data/README.md
CHANGED
@@ -1,6 +1,46 @@
|
|
1
1
|
|
2
2
|
# fugit
|
3
3
|
|
4
|
+
[![Build Status](https://secure.travis-ci.org/floraison/fugit.svg)](http://travis-ci.org/floraison/fugit)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/fugit.svg)](http://badge.fury.io/rb/fugit)
|
6
|
+
|
7
|
+
Time tools for [flor](https://github.com/floraison/flor) and the floraison project.
|
8
|
+
|
9
|
+
## `Fugit::Cron`
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'fugit'
|
13
|
+
|
14
|
+
c = Fugit::Cron.parse('0 0 * * sun')
|
15
|
+
|
16
|
+
p Time.now # => 2017-01-03 09:53:27 +0900
|
17
|
+
|
18
|
+
p c.next_time # => 2017-01-08 00:00:00 +0900
|
19
|
+
```
|
20
|
+
|
21
|
+
Example of cron strings understood by fugit:
|
22
|
+
```ruby
|
23
|
+
'5 0 * * *' # 5 minutes after midnight, every day
|
24
|
+
'15 14 1 * *' # at 1415 on the 1st of every month
|
25
|
+
'0 22 * * 1-5' # at 2200 on weekdays
|
26
|
+
'0 22 * * mon-fri' # idem
|
27
|
+
'23 0-23/2 * * *' # 23 minutes after 00:00, 02:00, 04:00, ...
|
28
|
+
|
29
|
+
'@yearly' # turns into '0 0 1 1 *'
|
30
|
+
'@monthly' # turns into '0 0 1 * *'
|
31
|
+
'@weekly' # turns into '0 0 * * 0'
|
32
|
+
'@daily' # turns into '0 0 * * *'
|
33
|
+
'@midnight' # turns into '0 0 * * *'
|
34
|
+
'@hourly' # turns into '0 * * * *'
|
35
|
+
|
36
|
+
'0 0 L * *' # last day of month at 00:00
|
37
|
+
'0 0 last * *' # idem
|
38
|
+
'0 0 -7-L * *' # from the seventh to last to the last day of month at 00:00
|
39
|
+
|
40
|
+
# and more...
|
41
|
+
```
|
42
|
+
|
4
43
|
## LICENSE
|
5
44
|
|
6
45
|
MIT, see [LICENSE.txt](LICENSE.txt)
|
46
|
+
|
data/fugit.gemspec
CHANGED
@@ -12,10 +12,10 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.email = [ 'jmettraux+flor@gmail.com' ]
|
13
13
|
s.homepage = 'http://github.com/floraison/fugit'
|
14
14
|
s.license = 'MIT'
|
15
|
-
s.summary = 'time
|
15
|
+
s.summary = 'time tools for flor'
|
16
16
|
|
17
17
|
s.description = %{
|
18
|
-
|
18
|
+
Time tools for flor and the floraison project. Cron parsing and occurence computing. Timestamps and more.
|
19
19
|
}.strip
|
20
20
|
|
21
21
|
#s.files = `git ls-files`.split("\n")
|
@@ -26,7 +26,7 @@ time oriented utilities for flor and the floraison project
|
|
26
26
|
]
|
27
27
|
|
28
28
|
#s.add_runtime_dependency 'tzinfo'
|
29
|
-
s.add_runtime_dependency 'raabro', '>= 1.1.
|
29
|
+
s.add_runtime_dependency 'raabro', '>= 1.1.3'
|
30
30
|
|
31
31
|
s.add_development_dependency 'rspec', '~> 3.4'
|
32
32
|
|
data/lib/fugit.rb
CHANGED
data/lib/fugit/cron.rb
ADDED
@@ -0,0 +1,440 @@
|
|
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 Cron
|
29
|
+
|
30
|
+
SPECIALS = {
|
31
|
+
'@reboot' => :reboot,
|
32
|
+
'@yearly' => '0 0 1 1 *',
|
33
|
+
'@annually' => '0 0 1 1 *',
|
34
|
+
'@monthly' => '0 0 1 * *',
|
35
|
+
'@weekly' => '0 0 * * 0',
|
36
|
+
'@daily' => '0 0 * * *',
|
37
|
+
'@midnight' => '0 0 * * *',
|
38
|
+
'@hourly' => '0 * * * *',
|
39
|
+
}
|
40
|
+
|
41
|
+
attr_reader :original
|
42
|
+
|
43
|
+
attr_reader :minutes, :hours, :monthdays, :months, :weekdays
|
44
|
+
|
45
|
+
def self.new(original)
|
46
|
+
|
47
|
+
parse(original)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_cron_s
|
51
|
+
|
52
|
+
@cron_s ||=
|
53
|
+
[
|
54
|
+
(@minutes || [ '*' ]).join(','),
|
55
|
+
(@hours || [ '*' ]).join(','),
|
56
|
+
(@monthdays || [ '*' ]).join(','),
|
57
|
+
(@months || [ '*' ]).join(','),
|
58
|
+
(@weekdays || [ [ '*' ] ]).map { |d| d.compact.join('#') }.join(',')
|
59
|
+
].join(' ')
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.parse(s)
|
63
|
+
|
64
|
+
original = s
|
65
|
+
s = SPECIALS[s] || s
|
66
|
+
|
67
|
+
#p s; Raabro.pp(Parser.parse(s, debug: 3))
|
68
|
+
h = Parser.parse(s)
|
69
|
+
|
70
|
+
fail ArgumentError.new(
|
71
|
+
"couldn't parse #{original.inspect}"
|
72
|
+
) unless h
|
73
|
+
|
74
|
+
self.allocate.send(:init, s, h)
|
75
|
+
end
|
76
|
+
|
77
|
+
class NextTime # TODO at some point, use ZoTime
|
78
|
+
|
79
|
+
def initialize(t)
|
80
|
+
@t = t.is_a?(NextTime) ? t.time : t
|
81
|
+
end
|
82
|
+
|
83
|
+
def time; @t; end
|
84
|
+
|
85
|
+
%w[ year month day wday hour min sec ]
|
86
|
+
.collect(&:to_sym).each { |k| define_method(k) { @t.send(k) } }
|
87
|
+
|
88
|
+
def inc(i)
|
89
|
+
u = @t.utc?
|
90
|
+
@t = ::Time.at(@t.to_i + i)
|
91
|
+
@t = @t.utc if u
|
92
|
+
self
|
93
|
+
end
|
94
|
+
def dec(i); inc(-i); end
|
95
|
+
|
96
|
+
def inc_month
|
97
|
+
y = @t.year
|
98
|
+
m = @t.month + 1
|
99
|
+
if m == 13; m = 1; y += 1; end
|
100
|
+
@t = Time.send((@t.utc? ? :utc : :local), y, m)
|
101
|
+
self
|
102
|
+
end
|
103
|
+
def inc_day; inc((24 - @t.hour) * 3600 - @t.min * 60 - @t.sec); end
|
104
|
+
def inc_hour; inc((60 - @t.min) * 60 - @t.sec); end
|
105
|
+
def inc_min; inc(60 - @t.sec); end
|
106
|
+
|
107
|
+
def dec_month
|
108
|
+
dec(@t.day * 24 * 3600 + @t.hour * 3600 + @t.min * 60 + @t.sec + 1)
|
109
|
+
end
|
110
|
+
def dec_day; dec(@t.hour * 3600 + @t.min * 60 + @t.sec + 1); end
|
111
|
+
def dec_hour; dec(@t.min * 60 + @t.sec + 1); end
|
112
|
+
def dec_min; dec(@t.sec + 1); end
|
113
|
+
def dec_sec; dec(@t.sec); end
|
114
|
+
|
115
|
+
def count_weeks(inc)
|
116
|
+
c = 0
|
117
|
+
t = @t
|
118
|
+
until t.month != @t.month
|
119
|
+
c += 1
|
120
|
+
t += inc * (7 * 24 * 3600)
|
121
|
+
end
|
122
|
+
c
|
123
|
+
end
|
124
|
+
|
125
|
+
def wday_in_month
|
126
|
+
[ count_weeks(-1), - count_weeks(1) ]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def month_match?(nt); ( ! @months) || @months.include?(nt.month); end
|
131
|
+
def hour_match?(nt); ( ! @hours) || @hours.include?(nt.hour); end
|
132
|
+
def min_match?(nt); ( ! @minutes) || @minutes.include?(nt.min); end
|
133
|
+
|
134
|
+
def weekday_match?(nt)
|
135
|
+
|
136
|
+
#p @weekdays
|
137
|
+
#p [ nt.day, nt.wday ]
|
138
|
+
return true if @weekdays.nil?
|
139
|
+
|
140
|
+
wd, hsh = @weekdays.find { |wd, hsh| wd == nt.wday }
|
141
|
+
|
142
|
+
return false unless wd
|
143
|
+
return true if hsh.nil?
|
144
|
+
|
145
|
+
phsh, nhsh = nt.wday_in_month
|
146
|
+
|
147
|
+
if hsh > 0
|
148
|
+
hsh == phsh # positive wday, from the beginning of the month
|
149
|
+
else
|
150
|
+
hsh == nhsh # negative wday, from the end of the month, -1 == last
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def monthday_match?(nt)
|
155
|
+
|
156
|
+
return true if @monthdays.nil?
|
157
|
+
|
158
|
+
last = (NextTime.new(nt).inc_month.time - 24 * 3600).day + 1
|
159
|
+
|
160
|
+
@monthdays
|
161
|
+
.collect { |d| d < 1 ? last + d : d }
|
162
|
+
.include?(nt.day)
|
163
|
+
end
|
164
|
+
|
165
|
+
def day_match?(nt)
|
166
|
+
|
167
|
+
return weekday_match?(nt) || monthday_match?(nt) \
|
168
|
+
if @weekdays && @monthdays
|
169
|
+
|
170
|
+
return false unless weekday_match?(nt)
|
171
|
+
return false unless monthday_match?(nt)
|
172
|
+
|
173
|
+
true
|
174
|
+
end
|
175
|
+
|
176
|
+
def match?(t)
|
177
|
+
|
178
|
+
t = NextTime.new(t)
|
179
|
+
|
180
|
+
month_match?(t) && day_match?(t) && hour_match?(t) && min_match?(t)
|
181
|
+
end
|
182
|
+
|
183
|
+
def next_time(from=Time.now)
|
184
|
+
|
185
|
+
nt = NextTime.new(from)
|
186
|
+
|
187
|
+
loop do
|
188
|
+
#p Fugit.time_to_s(nt.time)
|
189
|
+
month_match?(nt) || (nt.inc_month; next)
|
190
|
+
day_match?(nt) || (nt.inc_day; next)
|
191
|
+
hour_match?(nt) || (nt.inc_hour; next)
|
192
|
+
min_match?(nt) || (nt.inc_min; next)
|
193
|
+
break
|
194
|
+
end
|
195
|
+
|
196
|
+
nt.time
|
197
|
+
end
|
198
|
+
|
199
|
+
def previous_time(from=Time.now)
|
200
|
+
|
201
|
+
nt = NextTime.new(from)
|
202
|
+
|
203
|
+
loop do
|
204
|
+
#p Fugit.time_to_s(nt.time)
|
205
|
+
month_match?(nt) || (nt.dec_month; next)
|
206
|
+
day_match?(nt) || (nt.dec_day; next)
|
207
|
+
hour_match?(nt) || (nt.dec_hour; next)
|
208
|
+
min_match?(nt) || (nt.dec_min; next)
|
209
|
+
nt.dec_sec
|
210
|
+
break
|
211
|
+
end
|
212
|
+
|
213
|
+
nt.time
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns [ min delta, max delta, occurence count ]
|
217
|
+
# Computes for a non leap year (2017).
|
218
|
+
#
|
219
|
+
def frequency(year=2017)
|
220
|
+
|
221
|
+
FREQUENCY_CACHE["#{to_cron_s}|#{year}"] ||=
|
222
|
+
begin
|
223
|
+
deltas = []
|
224
|
+
|
225
|
+
t0 = nil
|
226
|
+
loop do
|
227
|
+
t1 = next_time(t0 || Time.parse("#{year}-01-01"))
|
228
|
+
deltas << (t1 - t0).to_i + 60 if t0
|
229
|
+
break if t1.year > year
|
230
|
+
t0 = t1 + 60
|
231
|
+
end
|
232
|
+
|
233
|
+
[ deltas.min, deltas.max, deltas.size ]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
protected
|
238
|
+
|
239
|
+
FREQUENCY_CACHE = {}
|
240
|
+
|
241
|
+
def init(original, h)
|
242
|
+
|
243
|
+
@original = original
|
244
|
+
|
245
|
+
determine_minutes(h[:min])
|
246
|
+
determine_hours(h[:hou])
|
247
|
+
determine_monthdays(h[:dom])
|
248
|
+
determine_months(h[:mon])
|
249
|
+
determine_weekdays(h[:dow])
|
250
|
+
|
251
|
+
self
|
252
|
+
end
|
253
|
+
|
254
|
+
def expand(min, max, r)
|
255
|
+
|
256
|
+
sta, edn, sla = r
|
257
|
+
|
258
|
+
sla = nil if sla == 1 # don't get fooled by /1
|
259
|
+
|
260
|
+
return [ nil ] if sta.nil? && edn.nil? && sla.nil?
|
261
|
+
return [ sta ] if sta && edn.nil?
|
262
|
+
|
263
|
+
sla = 1 if sla == nil
|
264
|
+
sta = min if sta == nil
|
265
|
+
edn = max if edn == nil
|
266
|
+
sta, edn = edn, sta if sta > edn
|
267
|
+
|
268
|
+
(sta..edn).step(sla).to_a
|
269
|
+
end
|
270
|
+
|
271
|
+
def compact(key)
|
272
|
+
|
273
|
+
arr = instance_variable_get(key)
|
274
|
+
|
275
|
+
return instance_variable_set(key, nil) if arr.include?(nil)
|
276
|
+
# reductio ad astrum
|
277
|
+
|
278
|
+
arr.uniq!
|
279
|
+
arr.sort!
|
280
|
+
end
|
281
|
+
|
282
|
+
def determine_minutes(mins)
|
283
|
+
@minutes = mins.inject([]) { |a, r| a.concat(expand(0, 59, r)) }
|
284
|
+
compact(:@minutes)
|
285
|
+
end
|
286
|
+
|
287
|
+
def determine_hours(hous)
|
288
|
+
@hours = hous.inject([]) { |a, r| a.concat(expand(0, 23, r)) }
|
289
|
+
@hours = @hours.collect { |h| h == 24 ? 0 : h }
|
290
|
+
compact(:@hours)
|
291
|
+
end
|
292
|
+
|
293
|
+
def determine_monthdays(doms)
|
294
|
+
@monthdays = doms.inject([]) { |a, r| a.concat(expand(1, 31, r)) }
|
295
|
+
compact(:@monthdays)
|
296
|
+
end
|
297
|
+
|
298
|
+
def determine_months(mons)
|
299
|
+
@months = mons.inject([]) { |a, r| a.concat(expand(1, 12, r)) }
|
300
|
+
compact(:@months)
|
301
|
+
end
|
302
|
+
|
303
|
+
def determine_weekdays(dows)
|
304
|
+
|
305
|
+
@weekdays = dows.inject([]) { |a, r|
|
306
|
+
aa = expand(0, 7, r)
|
307
|
+
if hsh = r[3]
|
308
|
+
a.concat([ [ aa.first, hsh ] ])
|
309
|
+
else
|
310
|
+
a.concat(aa.collect { |i| [ i, nil ] })
|
311
|
+
end
|
312
|
+
}
|
313
|
+
|
314
|
+
@weekdays =
|
315
|
+
if @weekdays.include?([ nil, nil ])
|
316
|
+
nil
|
317
|
+
else
|
318
|
+
@weekdays
|
319
|
+
.collect { |d, h| [ d == 7 ? 0 : d, h ] }
|
320
|
+
.uniq { |d| d.join('#') }
|
321
|
+
.sort_by { |d| d.join('#') }
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
module Parser include Raabro
|
326
|
+
|
327
|
+
WEEKDAYS = %w[ sun mon tue wed thu fri sat ]
|
328
|
+
MONTHS = %w[ - jan feb mar apr may jun jul aug sep oct nov dec ]
|
329
|
+
|
330
|
+
def s(i); rex(:s, i, /[ \t]+/); end
|
331
|
+
def star(i); str(:star, i, '*'); end
|
332
|
+
def hyphen(i); str(nil, i, '-'); end
|
333
|
+
def comma(i); str(nil, i, ','); end
|
334
|
+
|
335
|
+
def slash(i); rex(:slash, i, /\/\d\d?/); end
|
336
|
+
|
337
|
+
def core_min(i); rex(:min, i, /[0-5]?\d/); end
|
338
|
+
def core_hou(i); rex(:hou, i, /(2[0-4]|[01]?[0-9])/); end
|
339
|
+
def core_dom(i); rex(:dom, i, /(-?(3[01]|[012]?[0-9])|last|l)/i); end
|
340
|
+
def core_mon(i); rex(:mon, i, /(1[0-2]|0?[0-9]|#{MONTHS[1..-1].join('|')})/i); end
|
341
|
+
def core_dow(i); rex(:dow, i, /([0-7]|#{WEEKDAYS.join('|')})/i); end
|
342
|
+
|
343
|
+
def dow_hash(i); rex(:hash, i, /#(-?[1-5]|last|l)/i); end
|
344
|
+
|
345
|
+
def min(i); core_min(i); end
|
346
|
+
def hou(i); core_hou(i); end
|
347
|
+
def dom(i); core_dom(i); end
|
348
|
+
def mon(i); core_mon(i); end
|
349
|
+
def dow(i); core_dow(i); end
|
350
|
+
|
351
|
+
def _min(i); seq(nil, i, :hyphen, :min); end
|
352
|
+
def _hou(i); seq(nil, i, :hyphen, :hou); end
|
353
|
+
def _dom(i); seq(nil, i, :hyphen, :dom); end
|
354
|
+
def _mon(i); seq(nil, i, :hyphen, :mon); end
|
355
|
+
def _dow(i); seq(nil, i, :hyphen, :dow); end
|
356
|
+
|
357
|
+
# r: range
|
358
|
+
def r_min(i); seq(nil, i, :min, :_min, '?'); end
|
359
|
+
def r_hou(i); seq(nil, i, :hou, :_hou, '?'); end
|
360
|
+
def r_dom(i); seq(nil, i, :dom, :_dom, '?'); end
|
361
|
+
def r_mon(i); seq(nil, i, :mon, :_mon, '?'); end
|
362
|
+
def r_dow(i); seq(nil, i, :dow, :_dow, '?'); end
|
363
|
+
|
364
|
+
# sor: star or range
|
365
|
+
def sor_min(i); alt(nil, i, :star, :r_min); end
|
366
|
+
def sor_hou(i); alt(nil, i, :star, :r_hou); end
|
367
|
+
def sor_dom(i); alt(nil, i, :star, :r_dom); end
|
368
|
+
def sor_mon(i); alt(nil, i, :star, :r_mon); end
|
369
|
+
def sor_dow(i); alt(nil, i, :star, :r_dow); end
|
370
|
+
|
371
|
+
# sorws: star or range with[out] slash
|
372
|
+
def sorws_min(i); seq(nil, i, :sor_min, :slash, '?'); end
|
373
|
+
def sorws_hou(i); seq(nil, i, :sor_hou, :slash, '?'); end
|
374
|
+
def sorws_dom(i); seq(nil, i, :sor_dom, :slash, '?'); end
|
375
|
+
def sorws_mon(i); seq(nil, i, :sor_mon, :slash, '?'); end
|
376
|
+
def sorws_dow(i); seq(nil, i, :sor_dow, :slash, '?'); end
|
377
|
+
|
378
|
+
def h_dow(i); seq(nil, i, :core_dow, :dow_hash); end
|
379
|
+
|
380
|
+
def _sorws_dow(i); alt(nil, i, :h_dow, :sorws_dow); end
|
381
|
+
|
382
|
+
def list_min(i); jseq(:min, i, :sorws_min, :comma); end
|
383
|
+
def list_hou(i); jseq(:hou, i, :sorws_hou, :comma); end
|
384
|
+
def list_dom(i); jseq(:dom, i, :sorws_dom, :comma); end
|
385
|
+
def list_mon(i); jseq(:mon, i, :sorws_mon, :comma); end
|
386
|
+
def list_dow(i); jseq(:dow, i, :_sorws_dow, :comma); end
|
387
|
+
|
388
|
+
def lmin_(i); seq(nil, i, :list_min, :s); end
|
389
|
+
def lhou_(i); seq(nil, i, :list_hou, :s); end
|
390
|
+
def ldom_(i); seq(nil, i, :list_dom, :s); end
|
391
|
+
def lmon_(i); seq(nil, i, :list_mon, :s); end
|
392
|
+
alias ldow list_dow
|
393
|
+
|
394
|
+
def cron(i); seq(:cron, i, :lmin_, :lhou_, :ldom_, :lmon_, :ldow); end
|
395
|
+
|
396
|
+
def to_i(k, t)
|
397
|
+
|
398
|
+
s = t.string.downcase
|
399
|
+
|
400
|
+
(k == :mon && MONTHS.index(s)) ||
|
401
|
+
(k == :dow && WEEKDAYS.index(s)) ||
|
402
|
+
(k == :dom && s[0, 1] == 'l' && -1) || # L, l, last
|
403
|
+
s.to_i
|
404
|
+
end
|
405
|
+
|
406
|
+
def rewrite_entry(t)
|
407
|
+
|
408
|
+
k = t.name
|
409
|
+
|
410
|
+
t.children.select { |ct| ct.children.any? }.inject([]) { |a, ct|
|
411
|
+
|
412
|
+
xts = ct.gather(k)
|
413
|
+
#xts.each { |xt| Raabro.pp(xt) }
|
414
|
+
range = xts.any? ? xts.collect { |xt| to_i(k, xt) } : []
|
415
|
+
while range.size < 2; range << nil; end
|
416
|
+
|
417
|
+
st = ct.lookup(:slash)
|
418
|
+
range << (st ? st.string[1..-1].to_i : nil)
|
419
|
+
|
420
|
+
if k == :dow && ht = ct.lookup(:hash)
|
421
|
+
hs = ht.string.downcase
|
422
|
+
range << ((hs[1, 1] == 'l') ? -1 : hs[1..-1].to_i)
|
423
|
+
end
|
424
|
+
|
425
|
+
a << range
|
426
|
+
|
427
|
+
a
|
428
|
+
}
|
429
|
+
end
|
430
|
+
|
431
|
+
SYMS = %w[ min hou dom mon dow ].collect(&:to_sym)
|
432
|
+
|
433
|
+
def rewrite_cron(t)
|
434
|
+
|
435
|
+
SYMS.inject({}) { |h, k| h[k] = rewrite_entry(t.lookup(k)); h }
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
data/lib/fugit/misc.rb
ADDED
@@ -0,0 +1,56 @@
|
|
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.isostamp(show_date, show_time, show_usec, time)
|
29
|
+
|
30
|
+
t = time || Time.now
|
31
|
+
s = StringIO.new
|
32
|
+
|
33
|
+
s << t.strftime('%Y-%m-%d') if show_date
|
34
|
+
s << t.strftime('T%H:%M:%S') if show_time
|
35
|
+
s << sprintf('.%06d', t.usec) if show_time && show_usec
|
36
|
+
s << 'Z' if show_time && time.utc?
|
37
|
+
|
38
|
+
s.string
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.time_to_s(t)
|
42
|
+
|
43
|
+
isostamp(true, true, false, t)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.time_to_plain_s(t=Time.now)
|
47
|
+
|
48
|
+
s = StringIO.new
|
49
|
+
|
50
|
+
s << t.strftime('%Y-%m-%d %H:%M:%S')
|
51
|
+
s << ' Z' if t.utc?
|
52
|
+
|
53
|
+
s.string
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fugit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: raabro
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.1.
|
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
|
-
version: 1.1.
|
26
|
+
version: 1.1.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +38,8 @@ dependencies:
|
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.4'
|
41
|
-
description:
|
41
|
+
description: Time tools for flor and the floraison project. Cron parsing and occurence
|
42
|
+
computing. Timestamps and more.
|
42
43
|
email:
|
43
44
|
- jmettraux+flor@gmail.com
|
44
45
|
executables: []
|
@@ -46,9 +47,13 @@ extensions: []
|
|
46
47
|
extra_rdoc_files: []
|
47
48
|
files:
|
48
49
|
- Makefile
|
50
|
+
- lib/fugit/cron.rb
|
51
|
+
- lib/fugit/misc.rb
|
49
52
|
- lib/fugit.rb
|
50
53
|
- fugit.gemspec
|
51
54
|
- LICENSE.txt
|
55
|
+
- CHANGELOG.md
|
56
|
+
- CREDITS.md
|
52
57
|
- README.md
|
53
58
|
homepage: http://github.com/floraison/fugit
|
54
59
|
licenses:
|
@@ -73,5 +78,5 @@ rubyforge_project:
|
|
73
78
|
rubygems_version: 2.0.14
|
74
79
|
signing_key:
|
75
80
|
specification_version: 4
|
76
|
-
summary: time
|
81
|
+
summary: time tools for flor
|
77
82
|
test_files: []
|