fugit 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15c7da961f6616177b4837e7db2b8d2cbef8a73af0e39d482bbde88ca927d420
4
- data.tar.gz: bdb787682ba39f3bd873c935378d7097291ff275c9c2443a4bf42990e71dfa92
3
+ metadata.gz: 11380138d493b9ed80a43bffc6a61f74de5a2c52132ae2b9746c8097b3f8015a
4
+ data.tar.gz: 40ec86bcc48074cc6d3a5bc02b7c2ae84ba3f9fc505104373fc83c7c984ec04b
5
5
  SHA512:
6
- metadata.gz: c920de689a07b8e5b082afa2d67ff26a2ad3422e0a35afc0c02fee71d92d6a76da391d7ec6d03e55d62cbc1a46cbf1296bccb4a37ec9df9d72f35d3e4ecaf0ad
7
- data.tar.gz: 11694200215f7506f64f862d7f63e86b3fc79be5ad4a4ddfe9278143c40991bcd2c89356e9e314d5caad125b0b26623daf3da64ee2e92b49ca1480b59fc220f3
6
+ metadata.gz: dbd303863f53f7fbf39544fe914e48226952ff4e5983769e7bf932d8a92fdae67514460363f0a1921c77d9dfd7431539935ea18383e3187e103770f46eeeba78
7
+ data.tar.gz: b558ec5b070e2119d5ed0b21f840afd375f2b1eed95ef4542bd78d17dc026402d17c890163f8f9b3e08f8899d01ff08f2d4d3b1baece4d0c5af0e56d72e6d3d9
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## fugit 1.14.0 released 2026-09-14
6
+
7
+ * Reject input when length > 256
8
+
9
+
5
10
  ## fugit 1.13.0 released 2026-07-10
6
11
 
7
12
  * Random values support in cron string `"10 ~ * * *"` gh-121 Nicols Bachschmidt
data/CREDITS.md CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  # fugit credits
3
3
 
4
+ * Yaroslav Kurbatov https://github.com/viralpraxis input max length
4
5
  * Nicolas Bachschmidt https://github.com/baarde gh-120 weekday wrap fix
5
6
  * JebeenLee https://github.com/JebeenLee gh-117 divide by zero
6
7
  * Eric Claerhout https://github.com/swebra gh-114 rweek readme clarity
@@ -34,7 +35,7 @@
34
35
  * Niklas https://github.com/gr8bit gh-49, Fugit::Cron.parse('')
35
36
  * Matsuda Akira https://github.com/amatsuda gh-46, warning suppression
36
37
  * Honglooker https://github.com/honglooker gh-43, New York cron skip
37
- * Jérôme Dalbert https://github.com/jeromedalbert gh-41, gh-42
38
+ * Jérôme Dalbert https://github.com/jeromedalbert gh-41, gh-42, gh-123
38
39
  * Danny Ben Shitrit https://github.com/DannyBen nat variants, gh-38
39
40
  * Dominik Sander https://github.com/dsander #rough_frequency 0, gh-36
40
41
  * Milovan Zogovic https://github.com/assembler Cron#match? vs TZ, gh-31
data/fugit.gemspec CHANGED
@@ -43,7 +43,9 @@ Time tools for flor and the floraison project. Cron parsing and occurrence compu
43
43
  s.add_runtime_dependency 'raabro', '~> 1.4'
44
44
  s.add_runtime_dependency 'et-orbi', '~> 1.4'
45
45
 
46
- s.add_development_dependency 'rspec', '~> 3.8'
46
+ #s.add_development_dependency 'rspec', '~> 3.8'
47
+ s.add_development_dependency 'probatio', '~> 1.6'
48
+
47
49
  s.add_development_dependency 'chronic', '~> 0.10'
48
50
  s.add_development_dependency 'ostruct'
49
51
 
data/lib/fugit/cron.rb CHANGED
@@ -37,6 +37,16 @@ module Fugit
37
37
  s0 = s
38
38
  s = s.strip
39
39
 
40
+ if s.length > ::Fugit::MAX_INPUT_LENGTH
41
+
42
+ fail ArgumentError.new(
43
+ 'input too long for a cron string, ' +
44
+ "#{s.length} > #{MAX_INPUT_LENGTH}"
45
+ ) if opts[:do_parse]
46
+
47
+ return nil
48
+ end
49
+
40
50
  s =
41
51
  if s[0, 1] == '@'
42
52
  ss = s.split(/\s+/, 2)
@@ -53,7 +63,7 @@ module Fugit
53
63
 
54
64
  def do_parse(s, opts={})
55
65
 
56
- parse(s, opts) ||
66
+ parse(s, opts.merge(do_parse: true)) ||
57
67
  fail(ArgumentError.new("invalid cron string #{trunc(s)}"))
58
68
  end
59
69
 
@@ -26,6 +26,16 @@ module Fugit
26
26
  s = s.strip
27
27
  #p [ original, s ]; Raabro.pp(Parser.parse(s, debug: 3), colours: true)
28
28
 
29
+ if s.length > ::Fugit::MAX_INPUT_LENGTH
30
+
31
+ fail ArgumentError.new(
32
+ 'input too long for a duration string, ' +
33
+ "#{s.length} > #{MAX_INPUT_LENGTH}"
34
+ ) if opts[:do_parse]
35
+
36
+ return nil
37
+ end
38
+
29
39
  h =
30
40
  if opts[:iso]
31
41
  IsoParser.parse(opts[:stricter] ? s : s.upcase)
@@ -40,7 +50,7 @@ module Fugit
40
50
 
41
51
  def do_parse(s, opts={})
42
52
 
43
- parse(s, opts) ||
53
+ parse(s, opts.merge(do_parse: true)) ||
44
54
  fail(ArgumentError.new("not a duration #{s.inspect}"))
45
55
  end
46
56
 
data/lib/fugit/misc.rb CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Fugit
4
4
 
5
- DAY_S = (24 * 3600).freeze
6
- YEAR_S = (365 * DAY_S).freeze
5
+ DAY_S = 24 * 3600
6
+ YEAR_S = 365 * DAY_S
7
7
 
8
8
  class << self
9
9
 
data/lib/fugit/nat.rb CHANGED
@@ -7,8 +7,6 @@ module Fugit
7
7
  #
8
8
  module Nat
9
9
 
10
- MAX_INPUT_LENGTH = 256
11
-
12
10
  class << self
13
11
 
14
12
  def parse(s, opts={})
@@ -19,10 +17,10 @@ module Fugit
19
17
 
20
18
  s = s.strip
21
19
 
22
- if s.length > MAX_INPUT_LENGTH
20
+ if s.length > ::Fugit::MAX_INPUT_LENGTH
23
21
 
24
22
  fail ArgumentError.new(
25
- "input too long for a nat string, " +
23
+ 'input too long for a nat string, ' +
26
24
  "#{s.length} > #{MAX_INPUT_LENGTH}"
27
25
  ) if opts[:do_parse]
28
26
 
@@ -278,10 +276,27 @@ module Fugit
278
276
  rex(:interval, i, INTERVAL_REX)
279
277
  end
280
278
 
279
+ def _starting_at(i)
280
+ rex(nil, i, /[ \t]*(starting[ \t]+at|from)[ \t]+/i)
281
+ end
282
+ def _offset_unit(i)
283
+ rex(nil, i, /(second|minute|hour|day|month)s?[ \t]+/i)
284
+ end
285
+ def offset_count(i)
286
+ rex(:offset_count, i, /\d+/)
287
+ end
288
+
289
+ # starting at minute 1
290
+ # from minute 1
291
+ def offset(i)
292
+ seq(:offset, i, :_starting_at, :_offset_unit, :offset_count)
293
+ end
294
+
281
295
  # every day
282
296
  # every 1 minute
297
+ # every minute starting at minute 10
283
298
  def every_interval(i)
284
- seq(:every_interval, i, :count, '?', :interval)
299
+ seq(:every_interval, i, :count, '?', :interval, :offset, '?')
285
300
  end
286
301
 
287
302
  def every_single_interval(i)
@@ -380,6 +395,7 @@ module Fugit
380
395
  end
381
396
 
382
397
  def rewrite_on_minutes(t)
398
+
383
399
  #Raabro.pp(t, colours: true)
384
400
  mins = t.subgather(:dmin).collect(&:strinp)
385
401
  #slot(:m, mins.join(','))
@@ -387,6 +403,7 @@ module Fugit
387
403
  end
388
404
 
389
405
  def rewrite_on_thex(t)
406
+
390
407
  case s = t.string
391
408
  #when /hour/i then slot(:h, 0)
392
409
  #else slot(:m, '*')
@@ -415,10 +432,12 @@ module Fugit
415
432
  end
416
433
 
417
434
  def rewrite_at_p(t)
435
+
418
436
  pt = t.sublookup(:point).strinpd
419
437
  pt = pt.start_with?('mon') ? 'M' : pt[0, 1]
420
438
  pts = t.subgather(:count).collect { |e| e.string.to_i }
421
439
  #p [ pt, pts ]
440
+
422
441
  case pt
423
442
  #when 'm' then slot(:m, pts)
424
443
  when 'm' then slot(:hm, '*', pts, strong: 1)
@@ -428,6 +447,7 @@ module Fugit
428
447
  end
429
448
 
430
449
  def rewrite_every_single_interval(t)
450
+
431
451
  case t.string
432
452
  when /year/i then [ slot(:month, 1, :weak), slot(:monthday, 1, :weak) ]
433
453
  #when /week/i then xxx...
@@ -438,11 +458,19 @@ module Fugit
438
458
  def rewrite_every_interval(t)
439
459
 
440
460
  #Raabro.pp(t, colours: true)
441
- ci = t.subgather(nil).collect(&:string)
442
- i = ci.pop.strip[0, 3]
443
- c = (ci.pop || '1').strip
461
+ ct = t.sublookup(:count)
462
+ it = t.sublookup(:interval)
463
+ ot = t.sublookup(:offset)
464
+
465
+ c = (ct ? ct.string : '1').strip
466
+ i = it.string.strip[0, 3]
444
467
  i = (i == 'M' || i.downcase == 'mon') ? 'M' : i[0, 1].downcase
445
- cc = c == '1' ? '*' : "*/#{c}"
468
+ off = ot ? ot.sublookup(:offset_count).string.to_i : nil
469
+ cc =
470
+ if off then "#{off}/#{c}"
471
+ elsif c == '1' then '*'
472
+ else "*/#{c}"
473
+ end
446
474
 
447
475
  case i
448
476
  when 'M' then slot(:month, cc)
@@ -465,17 +493,14 @@ module Fugit
465
493
  end
466
494
 
467
495
  def rewrite_tz(t)
468
-
469
496
  slot(:tz, t.string)
470
497
  end
471
498
 
472
499
  def rewrite_weekday(t)
473
-
474
500
  Fugit::Cron::Parser::WEEKDS.index(t.string[0, 3].downcase)
475
501
  end
476
502
 
477
503
  def rewrite_weekdays(t)
478
-
479
504
  #Raabro.pp(t, colours: true)
480
505
  slot(:weekday, _rewrite_subs(t, :weekday))
481
506
  end
@@ -542,12 +567,15 @@ module Fugit
542
567
  end
543
568
 
544
569
  def rewrite_to_hour(t)
570
+
545
571
  #Raabro.pp(t, colours: true)
546
572
  ht0, ht1 = t.subgather(nil)
547
573
  h0, h1 = rewrite(ht0), rewrite(ht1)
574
+
548
575
  fail ArgumentError.new(
549
576
  "cannot deal with #{ht0.strinp} to #{ht1.strinp}, minutes diverge"
550
577
  ) if h0.data1 != h1.data1
578
+
551
579
  slot(:hm, "#{h0._data0}-#{h1._data0}", 0, strong: 0)
552
580
  end
553
581
 
data/lib/fugit/parse.rb CHANGED
@@ -65,11 +65,13 @@ module Fugit
65
65
  fail(ArgumentError.new("not cron or 'natural' cron string: #{s.inspect}"))
66
66
  end
67
67
 
68
+ # Still an exploration, but what was the goal? 2026-09-14
69
+ #
68
70
  def parse_max(s, opts={})
69
71
 
70
72
  s0 = s.lines.first
71
73
 
72
- (0..[ ::Fugit::Nat::MAX_INPUT_LENGTH, s0.length - 1 ].min).each do |i|
74
+ (0..[ ::Fugit::MAX_INPUT_LENGTH, s0.length - 1 ].min).each do |i|
73
75
 
74
76
  s1 =
75
77
  s0[0, s0.length - i].rstrip
data/lib/fugit.rb CHANGED
@@ -1,9 +1,9 @@
1
- # frozen_string_literal: true
2
-
3
1
 
4
2
  module Fugit
5
3
 
6
- VERSION = '1.13.0'
4
+ VERSION = '1.14.0'.freeze
5
+
6
+ MAX_INPUT_LENGTH = 256
7
7
  end
8
8
 
9
9
  require 'time'
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fugit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.0
4
+ version: 1.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-07-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: raabro
@@ -39,19 +38,19 @@ dependencies:
39
38
  - !ruby/object:Gem::Version
40
39
  version: '1.4'
41
40
  - !ruby/object:Gem::Dependency
42
- name: rspec
41
+ name: probatio
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - "~>"
46
45
  - !ruby/object:Gem::Version
47
- version: '3.8'
46
+ version: '1.6'
48
47
  type: :development
49
48
  prerelease: false
50
49
  version_requirements: !ruby/object:Gem::Requirement
51
50
  requirements:
52
51
  - - "~>"
53
52
  - !ruby/object:Gem::Version
54
- version: '3.8'
53
+ version: '1.6'
55
54
  - !ruby/object:Gem::Dependency
56
55
  name: chronic
57
56
  requirement: !ruby/object:Gem::Requirement
@@ -110,7 +109,6 @@ metadata:
110
109
  homepage_uri: https://github.com/floraison/fugit
111
110
  source_code_uri: https://github.com/floraison/fugit
112
111
  rubygems_mfa_required: 'true'
113
- post_install_message:
114
112
  rdoc_options: []
115
113
  require_paths:
116
114
  - lib
@@ -125,8 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
123
  - !ruby/object:Gem::Version
126
124
  version: '0'
127
125
  requirements: []
128
- rubygems_version: 3.4.19
129
- signing_key:
126
+ rubygems_version: 3.6.9
130
127
  specification_version: 4
131
128
  summary: time tools for flor
132
129
  test_files: []