fugit 1.11.1 → 1.12.1
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 +4 -4
- data/CHANGELOG.md +20 -0
- data/CREDITS.md +6 -0
- data/LICENSE.txt +1 -1
- data/README.md +278 -108
- data/fugit.gemspec +5 -5
- data/lib/fugit/cron.rb +28 -23
- data/lib/fugit/duration.rb +14 -5
- data/lib/fugit/nat.rb +10 -6
- data/lib/fugit/parse.rb +21 -1
- data/lib/fugit.rb +1 -1
- metadata +7 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 15a3ea665c020e35ce51dcbc82be9a74e6f4abcaa2441316b514c630ffdbc094
|
|
4
|
+
data.tar.gz: f99246722de255325b57ea46f7b3f24bbfc11d65f1eb98fde9a2a43a3c249df0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc55e7332f5f111ddf27d145fed7fbfeaeed30f492ba343d1f4067e776c96874b42bad9488b9683203040cc50333f74bab56fa6e61744ef92fb059f2a2c9f076
|
|
7
|
+
data.tar.gz: 5ee65240dd04fddb7777bee327f8fee0cfef5260ed55db9ec71ece64c5e5e6b53283aa7d26ba52facbca3882aee0920ff0dd3715fea5ad9153caca82ea712450
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
# CHANGELOG.md
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## fugit 1.12.1 released 2025-10-14
|
|
6
|
+
|
|
7
|
+
* Fix Fugit::Cron#to_cron_s to include & if @day_and
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## fugit 1.12.0 released 2025-09-30
|
|
11
|
+
|
|
12
|
+
* Upgrade et-orbi to ~> 1.4.0 for EtOrbi.rweek_ref=, gh-114
|
|
13
|
+
this changes the rweek reference point to 2018-12-31 (Monday)
|
|
14
|
+
* Fix `12 0 * * wed%4+1,wed%4` issue where 1 wed was ignored, gh-114
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## fugit 1.11.2 released 2025-08-22
|
|
18
|
+
|
|
19
|
+
* Fix "every day at midnight America/Los_Angeles", gh-113, Mark R. James
|
|
20
|
+
* Avoid Hash#partition https://bugs.ruby-lang.org/issues/16252
|
|
21
|
+
* Fix Fugit::Nat "zero dark forty", gh-107
|
|
22
|
+
* Ensure @yearly and other specials accept a timezone
|
|
23
|
+
|
|
24
|
+
|
|
5
25
|
## fugit 1.11.1 released 2024-08-15
|
|
6
26
|
|
|
7
27
|
* Prevent nat parsing chocking on long input (> 256 chars), gh-104
|
data/CREDITS.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
# fugit credits
|
|
3
3
|
|
|
4
|
+
* Eric Claerhout https://github.com/swebra gh-114 rweek readme clarity
|
|
5
|
+
* Hugh Kelsey https://github.com/hughkelsey gh-114 rweek/rday / wed%4+1,wed%4
|
|
6
|
+
* Mark R. James, https://github.com/mrj, AM vs America/Los_Angeles, gh-113
|
|
7
|
+
* Tejas Bubane, https://github.com/tejasbubane, r3.4 in test matrix, gh-109
|
|
8
|
+
* Luis Castillo, https://github.com/lekastillo, nice_hash gh-108
|
|
9
|
+
* Geremia Taglialatela, https://github.com/tagliala, gh-105 gh-107
|
|
4
10
|
* https://github.com/personnumber3377, gh-104 Fugit.parse choke on long input
|
|
5
11
|
* Michael Scrivo, https://github.com/mscrivo, gh-103
|
|
6
12
|
* Benjamin Darcet, https://github.com/bdarcet gh-95 gh-96 et-orbi #rweek
|
data/LICENSE.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
Copyright (c) 2017-
|
|
2
|
+
Copyright (c) 2017-2025, John Mettraux, jmettraux+flor@gmail.com
|
|
3
3
|
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
|
@@ -17,31 +17,33 @@ Fugit is a core dependency of [rufus-scheduler](https://github.com/jmettraux/ruf
|
|
|
17
17
|
|
|
18
18
|
The intersection of those two projects is where fugit is born:
|
|
19
19
|
|
|
20
|
-
* [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler)
|
|
21
|
-
* [flor](https://github.com/floraison/flor)
|
|
20
|
+
* [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
|
|
21
|
+
* [flor](https://github.com/floraison/flor) — a Ruby workflow engine, fugit provides the foundation for its time scheduling capabilities
|
|
22
22
|
|
|
23
23
|
### Similar, sometimes overlapping projects
|
|
24
24
|
|
|
25
|
-
* [chronic](https://github.com/mojombo/chronic)
|
|
26
|
-
* [parse-cron](https://github.com/siebertm/parse-cron)
|
|
27
|
-
* [ice_cube](https://github.com/seejohnrun/ice_cube)
|
|
28
|
-
* [ISO8601](https://github.com/arnau/ISO8601)
|
|
29
|
-
* [chrono](https://github.com/r7kamura/chrono)
|
|
30
|
-
* [CronCalc](https://github.com/mizinsky/cron_calc)
|
|
31
|
-
* [Recurrence](https://github.com/fnando/recurrence)
|
|
25
|
+
* [chronic](https://github.com/mojombo/chronic) — a pure Ruby natural language date parser
|
|
26
|
+
* [parse-cron](https://github.com/siebertm/parse-cron) — parses cron expressions and calculates the next occurrence after a given date
|
|
27
|
+
* [ice_cube](https://github.com/seejohnrun/ice_cube) — Ruby date recurrence library
|
|
28
|
+
* [ISO8601](https://github.com/arnau/ISO8601) — Ruby parser to work with ISO8601 dateTimes and durations
|
|
29
|
+
* [chrono](https://github.com/r7kamura/chrono) — a chain of logics about chronology
|
|
30
|
+
* [CronCalc](https://github.com/mizinsky/cron_calc) — calculates cron job occurrences
|
|
31
|
+
* [Recurrence](https://github.com/fnando/recurrence) — a simple library to handle recurring events
|
|
32
|
+
* [CronConfigParser](https://github.com/madogiwa0124/cron_config_parser) — parse the cron configuration for readability
|
|
32
33
|
* ...
|
|
33
34
|
|
|
34
35
|
### Projects using fugit
|
|
35
36
|
|
|
36
|
-
* [arask](https://github.com/Ebbe/arask)
|
|
37
|
-
* [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron)
|
|
38
|
-
* [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler)
|
|
39
|
-
* [flor](https://github.com/floraison/flor)
|
|
40
|
-
* [que-scheduler](https://github.com/hlascelles/que-scheduler)
|
|
41
|
-
* [serial_scheduler](https://github.com/grosser/serial_scheduler)
|
|
42
|
-
* [delayed_cron_job](https://github.com/codez/delayed_cron_job)
|
|
43
|
-
* [GoodJob](https://github.com/bensheldon/good_job)
|
|
44
|
-
* [Solid Queue](https://github.com/rails/solid_queue)
|
|
37
|
+
* [arask](https://github.com/Ebbe/arask) — "Automatic RAils taSKs" uses fugit to parse cron strings
|
|
38
|
+
* [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron) — uses fugit to parse cron strings since version 1.0.0, it was using rufus-scheduler previously
|
|
39
|
+
* [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) — as seen above
|
|
40
|
+
* [flor](https://github.com/floraison/flor) — used in the [cron](https://github.com/floraison/flor/blob/master/doc/procedures/cron.md) procedure
|
|
41
|
+
* [que-scheduler](https://github.com/hlascelles/que-scheduler) — a reliable job scheduler for [que](https://github.com/chanks/que)
|
|
42
|
+
* [serial_scheduler](https://github.com/grosser/serial_scheduler) — ruby task scheduler without threading
|
|
43
|
+
* [delayed_cron_job](https://github.com/codez/delayed_cron_job) — an extension to Delayed::Job that allows you to set cron expressions for your jobs
|
|
44
|
+
* [GoodJob](https://github.com/bensheldon/good_job) — a multithreaded, Postgres-based, Active Job backend for Ruby on Rails
|
|
45
|
+
* [Solid Queue](https://github.com/rails/solid_queue) — a DB-based queuing backend for Active Job, designed with simplicity and performance in mind
|
|
46
|
+
* [qron](https://github.com/floraison/qron) — stupid cron thread that wakes up from time to time to do what's in its crontab
|
|
45
47
|
* ...
|
|
46
48
|
|
|
47
49
|
## `Fugit.parse(s)`
|
|
@@ -112,6 +114,7 @@ Fugit.parse_cronish('12y12M') # ==> nil
|
|
|
112
114
|
|
|
113
115
|
Introduced in fugit 1.8.0.
|
|
114
116
|
|
|
117
|
+
|
|
115
118
|
## `Fugit::Cron`
|
|
116
119
|
|
|
117
120
|
A class `Fugit::Cron` to parse cron strings and then `#next_time` and `#previous_time` to compute the next or the previous occurrence respectively.
|
|
@@ -204,13 +207,28 @@ Example of cron strings understood by fugit:
|
|
|
204
207
|
|
|
205
208
|
Please note that `'15/30 * * * *'` is interpreted as `'15-59/30 * * * *'` since fugit 1.4.6.
|
|
206
209
|
|
|
210
|
+
### time zones
|
|
211
|
+
|
|
212
|
+
Fugit accepts a IANA timezone identifier right after a cron string:
|
|
213
|
+
```ruby
|
|
214
|
+
'5 0 * * * Europe/Rome' # 5 minutes after midnight, every day, Rome tz
|
|
215
|
+
'0 22 * * 1-5 Asia/Tbilisi' # at 2200 on weekdays in Georgia
|
|
216
|
+
|
|
217
|
+
'@yearly Asia/Kuala_Lumpur' # turns into '0 0 1 1 * Asia/Kuala_Lumpur'
|
|
218
|
+
'@monthly Asia/Jakarta' # turns into '0 0 1 * * Asia/Jakarta'
|
|
219
|
+
#
|
|
220
|
+
# those two "ats" and friends since fugit 1.11.2...
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
When no time zone is specified, fugit uses Ruby's provided timezone.
|
|
224
|
+
|
|
207
225
|
### the first Monday of the month
|
|
208
226
|
|
|
209
227
|
Fugit tries to follow the `man 5 crontab` documentation.
|
|
210
228
|
|
|
211
229
|
There is a surprising thing about this canon, all the columns are joined by ANDs, except for monthday and weekday which are joined together by OR if they are both set (they are not `*`).
|
|
212
230
|
|
|
213
|
-
Many people (me included) [are
|
|
231
|
+
Many people (me included) [are surprised](https://superuser.com/questions/428807/run-a-cron-job-on-the-first-monday-of-every-month) when they try to specify "at 05:00 on the first Monday of the month" as `0 5 1-7 * 1` or `0 5 1-7 * mon` and the results are off.
|
|
214
232
|
|
|
215
233
|
The man page says:
|
|
216
234
|
|
|
@@ -278,139 +296,201 @@ The hash extension can only be used in the day-of-week field.
|
|
|
278
296
|
|
|
279
297
|
### the modulo extension
|
|
280
298
|
|
|
281
|
-
|
|
299
|
+
Since 1.1.10, fugit also understands cron strings like `9 0 * * sun%2` which can be read as "every other Sunday at 9am" or `12 0 * * mon%4` for "every fourth monday at noon".
|
|
282
300
|
|
|
283
301
|
The modulo extension can only be used in the day-of-week field.
|
|
284
302
|
|
|
285
303
|
For odd Sundays, one can write `9 0 * * sun%2+1`.
|
|
286
304
|
|
|
287
|
-
It can be combined, as in `9 0 * * sun%2,tue%3+2
|
|
288
|
-
|
|
289
|
-
But what does it reference to? It starts at 1 on 2019-01-01.
|
|
305
|
+
It can be combined, as in `9 0 * * sun%2,tue%3+2`, which will match every other Sunday and 1 in 3 Tuesdays (with an offset of 2).
|
|
290
306
|
|
|
307
|
+
What does `sun%2` actually mean?
|
|
291
308
|
```ruby
|
|
292
|
-
|
|
309
|
+
t.wday == 0 && t.rweek % 2 == 0
|
|
310
|
+
```
|
|
293
311
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
What does `tue%3+2` mean?
|
|
313
|
+
```ruby
|
|
314
|
+
t.wday == 2 && t.rweek % 3 == 2
|
|
315
|
+
```
|
|
298
316
|
|
|
299
|
-
|
|
300
|
-
p EtOrbi.parse('2019-04-11').wday # => 4
|
|
301
|
-
p EtOrbi.parse('2019-04-11').rweek # => 15
|
|
302
|
-
p EtOrbi.parse('2019-04-11').rweek % 2 # => 1
|
|
317
|
+
#### et-orbi < 1.4.0 : reference set on Tuesday 2019-01-01
|
|
303
318
|
|
|
304
|
-
|
|
305
|
-
c.match?('2019-01-01') # => false, since rweek % 2 == 1
|
|
306
|
-
c.match?('2019-01-08') # => true, since rweek % 2 == 0
|
|
319
|
+
The original implementation of `#rweek` (and `#rday`) found in [et-orbi](https://github.com/floraison/et-orbi) was initially pointing to "Tuesday 2019-01-01" and it was set as rday 1 and rweek 1.
|
|
307
320
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
321
|
+
Consider this iteration through the days around 2019-01-01.
|
|
322
|
+
```ruby
|
|
323
|
+
require 'fugit'
|
|
311
324
|
|
|
312
|
-
|
|
313
|
-
```
|
|
325
|
+
t = EtOrbi.parse('2018-12-28 12:00')
|
|
314
326
|
|
|
315
|
-
|
|
316
|
-
`tue%3+2` matches if Tuesday and `current_date.rweek + 2 % 3 == 0`
|
|
317
|
-
`tue%x+y` matches if Tuesday and `current_date.rweek + y % x == 0`
|
|
327
|
+
15.times do |i|
|
|
318
328
|
|
|
329
|
+
puts " * %14s / rday: %5d / rweek: %5d" % [
|
|
330
|
+
t.strftime('%F %a'), t.rday, t.rweek ]
|
|
319
331
|
|
|
320
|
-
|
|
332
|
+
w = t.rweek
|
|
333
|
+
t = t.add(24 * 3600)
|
|
334
|
+
puts if t.rweek != w
|
|
321
335
|
|
|
322
|
-
|
|
336
|
+
if i == 7
|
|
337
|
+
puts "\n (...)\n\n"
|
|
338
|
+
t = EtOrbi.parse('2025-10-04 12:00')
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
```
|
|
323
342
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
343
|
+
For et-orbi 1.2.11, it yields:
|
|
344
|
+
```
|
|
345
|
+
* 2018-12-28 Fri / rday: -3 / rweek: 0
|
|
346
|
+
* 2018-12-29 Sat / rday: -2 / rweek: 0
|
|
347
|
+
* 2018-12-30 Sun / rday: -1 / rweek: 0
|
|
348
|
+
* 2018-12-31 Mon / rday: 0 / rweek: 0
|
|
349
|
+
|
|
350
|
+
* 2019-01-01 Tue / rday: 1 / rweek: 1
|
|
351
|
+
* 2019-01-02 Wed / rday: 2 / rweek: 1
|
|
352
|
+
* 2019-01-03 Thu / rday: 3 / rweek: 1
|
|
353
|
+
* 2019-01-04 Fri / rday: 4 / rweek: 1
|
|
354
|
+
* 2019-01-05 Sat / rday: 5 / rweek: 1
|
|
355
|
+
|
|
356
|
+
(...)
|
|
357
|
+
|
|
358
|
+
* 2025-10-04 Sat / rday: 2469 / rweek: 353
|
|
359
|
+
* 2025-10-05 Sun / rday: 2470 / rweek: 353
|
|
360
|
+
* 2025-10-06 Mon / rday: 2471 / rweek: 353
|
|
361
|
+
|
|
362
|
+
* 2025-10-07 Tue / rday: 2472 / rweek: 354
|
|
363
|
+
* 2025-10-08 Wed / rday: 2473 / rweek: 354
|
|
364
|
+
* 2025-10-09 Thu / rday: 2474 / rweek: 354
|
|
329
365
|
```
|
|
330
366
|
|
|
367
|
+
This [was problematic](https://github.com/floraison/fugit/issues/114), since the week started on, well, Tuesday.
|
|
331
368
|
|
|
332
|
-
## `Fugit::Duration`
|
|
333
369
|
|
|
334
|
-
|
|
370
|
+
#### et-orbi >= 1.4.0 : reference set on Monday 2018-12-31
|
|
335
371
|
|
|
336
|
-
|
|
372
|
+
Since 1.4.0, et-orbi starts by default on Monday (2018-12-31), as rday 0 with rweek 0.
|
|
337
373
|
|
|
338
|
-
|
|
339
|
-
|
|
374
|
+
Thus, the above code yields:
|
|
375
|
+
```
|
|
376
|
+
* 2018-12-28 Fri / rday: -3 / rweek: -1
|
|
377
|
+
* 2018-12-29 Sat / rday: -2 / rweek: -1
|
|
378
|
+
* 2018-12-30 Sun / rday: -1 / rweek: -1
|
|
379
|
+
|
|
380
|
+
* 2018-12-31 Mon / rday: 0 / rweek: 0
|
|
381
|
+
* 2019-01-01 Tue / rday: 1 / rweek: 0
|
|
382
|
+
* 2019-01-02 Wed / rday: 2 / rweek: 0
|
|
383
|
+
* 2019-01-03 Thu / rday: 3 / rweek: 0
|
|
384
|
+
* 2019-01-04 Fri / rday: 4 / rweek: 0
|
|
385
|
+
* 2019-01-05 Sat / rday: 5 / rweek: 0
|
|
386
|
+
|
|
387
|
+
(...)
|
|
388
|
+
|
|
389
|
+
* 2025-10-04 Sat / rday: 2469 / rweek: 352
|
|
390
|
+
* 2025-10-05 Sun / rday: 2470 / rweek: 352
|
|
391
|
+
|
|
392
|
+
* 2025-10-06 Mon / rday: 2471 / rweek: 353
|
|
393
|
+
* 2025-10-07 Tue / rday: 2472 / rweek: 353
|
|
394
|
+
* 2025-10-08 Wed / rday: 2473 / rweek: 353
|
|
395
|
+
* 2025-10-09 Thu / rday: 2474 / rweek: 353
|
|
396
|
+
```
|
|
340
397
|
|
|
341
|
-
d = Fugit::Duration.parse('1y2M1d4h')
|
|
342
398
|
|
|
343
|
-
|
|
344
|
-
p d.to_iso_s # => "P1Y2M1DT4H" ISO 8601 duration
|
|
345
|
-
p d.to_long_s # => "1 year, 2 months, 1 day, and 4 hours"
|
|
399
|
+
#### modulo and et-orbi >= 1.4.0 sanity check
|
|
346
400
|
|
|
347
|
-
|
|
401
|
+
Given the cron `"0 12 * * mon%2,wed%3+1"`, here is a piece of code that considers a range of 44 days and tells in its last column if YES or no if each of the days matches the cron.
|
|
348
402
|
|
|
349
|
-
|
|
403
|
+
```ruby
|
|
404
|
+
require 'fugit'
|
|
350
405
|
|
|
351
|
-
|
|
406
|
+
c = Fugit.parse_cron('0 12 * * mon%2,wed%3+1')
|
|
352
407
|
|
|
353
|
-
|
|
408
|
+
t = EtOrbi.parse('2025-09-20 12:00')
|
|
354
409
|
|
|
355
|
-
|
|
356
|
-
```
|
|
410
|
+
44.times do
|
|
357
411
|
|
|
358
|
-
|
|
412
|
+
wd = t.strftime('%a')
|
|
413
|
+
wd = %w[ Mon Wed ].include?(wd) ? '*' + wd.upcase : ' ' + wd.downcase
|
|
359
414
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
415
|
+
puts "%14s | rweek: %3d | %%2: %d == 0 | %%3: %d == 1 | ? %3s" % [
|
|
416
|
+
t.strftime('%F') + ' ' + wd,
|
|
417
|
+
t.rweek,
|
|
418
|
+
t.rweek % 2, t.rweek % 3,
|
|
419
|
+
c.match?(t)
|
|
420
|
+
].map { |e| e == true ? 'YES' : e == false ? 'no' : e }
|
|
365
421
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
422
|
+
w = t.rweek
|
|
423
|
+
t = t.add(24 * 3600)
|
|
424
|
+
puts if t.rweek != w
|
|
425
|
+
end
|
|
369
426
|
```
|
|
370
427
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
```ruby
|
|
374
|
-
Fugit::Duration.parse('1h30m12').inflate.to_plain_s # => "5412s"
|
|
375
|
-
Fugit.parse('1h30m12').inflate.to_plain_s # => "5412s"
|
|
376
|
-
|
|
377
|
-
Fugit.parse('1h30m12').to_sec # => 5412
|
|
378
|
-
Fugit.parse('1h30m12').to_sec.to_s + 's' # => "5412s"
|
|
428
|
+
Here's the output:
|
|
379
429
|
```
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
430
|
+
2025-09-20 sat | rweek: 350 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
431
|
+
2025-09-21 sun | rweek: 350 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
432
|
+
|
|
433
|
+
2025-09-22 *MON | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
434
|
+
2025-09-23 tue | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
435
|
+
2025-09-24 *WED | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
436
|
+
2025-09-25 thu | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
437
|
+
2025-09-26 fri | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
438
|
+
2025-09-27 sat | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
439
|
+
2025-09-28 sun | rweek: 351 | %2: 1 == 0 | %3: 0 == 1 | ? no
|
|
440
|
+
|
|
441
|
+
2025-09-29 *MON | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? YES
|
|
442
|
+
2025-09-30 tue | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? no
|
|
443
|
+
2025-10-01 *WED | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? YES
|
|
444
|
+
2025-10-02 thu | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? no
|
|
445
|
+
2025-10-03 fri | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? no
|
|
446
|
+
2025-10-04 sat | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? no
|
|
447
|
+
2025-10-05 sun | rweek: 352 | %2: 0 == 0 | %3: 1 == 1 | ? no
|
|
448
|
+
|
|
449
|
+
2025-10-06 *MON | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
450
|
+
2025-10-07 tue | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
451
|
+
2025-10-08 *WED | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
452
|
+
2025-10-09 thu | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
453
|
+
2025-10-10 fri | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
454
|
+
2025-10-11 sat | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
455
|
+
2025-10-12 sun | rweek: 353 | %2: 1 == 0 | %3: 2 == 1 | ? no
|
|
456
|
+
|
|
457
|
+
2025-10-13 *MON | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? YES
|
|
458
|
+
2025-10-14 tue | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? no
|
|
459
|
+
2025-10-15 *WED | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? no
|
|
460
|
+
2025-10-16 thu | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? no
|
|
461
|
+
2025-10-17 fri | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? no
|
|
462
|
+
2025-10-18 sat | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? no
|
|
463
|
+
2025-10-19 sun | rweek: 354 | %2: 0 == 0 | %3: 0 == 1 | ? no
|
|
464
|
+
|
|
465
|
+
2025-10-20 *MON | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? no
|
|
466
|
+
2025-10-21 tue | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? no
|
|
467
|
+
2025-10-22 *WED | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? YES
|
|
468
|
+
2025-10-23 thu | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? no
|
|
469
|
+
2025-10-24 fri | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? no
|
|
470
|
+
2025-10-25 sat | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? no
|
|
471
|
+
2025-10-26 sun | rweek: 355 | %2: 1 == 0 | %3: 1 == 1 | ? no
|
|
472
|
+
|
|
473
|
+
2025-10-27 *MON | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? YES
|
|
474
|
+
2025-10-28 tue | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
475
|
+
2025-10-29 *WED | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
476
|
+
2025-10-30 thu | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
477
|
+
2025-10-31 fri | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
478
|
+
2025-11-01 sat | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
479
|
+
2025-11-02 sun | rweek: 356 | %2: 0 == 0 | %3: 2 == 1 | ? no
|
|
389
480
|
```
|
|
390
481
|
|
|
391
|
-
## `Fugit::At`
|
|
392
|
-
|
|
393
|
-
Points in time are parsed and given back as EtOrbi::EoTime instances.
|
|
394
482
|
|
|
395
|
-
|
|
396
|
-
Fugit::At.parse('2017-12-12').to_s
|
|
397
|
-
# ==> "2017-12-12 00:00:00 +0900" (at least here in Hiroshima)
|
|
483
|
+
### the second extension
|
|
398
484
|
|
|
399
|
-
Fugit
|
|
400
|
-
# ==> "2017-12-12 12:00:00 -0500"
|
|
401
|
-
```
|
|
485
|
+
Fugit accepts cron strings with five elements, `minute hour day-of-month month day-of-week`, the standard cron format or six elements `second minute hour day-of-month month day-of-week`.
|
|
402
486
|
|
|
403
|
-
Directly with `Fugit.parse_at(s)` is OK too:
|
|
404
487
|
```ruby
|
|
405
|
-
Fugit.
|
|
406
|
-
|
|
488
|
+
c = Fugit.parse('* * * * *') # every minute
|
|
489
|
+
c = Fugit.parse('5 * * * *') # every hour at minute 5
|
|
490
|
+
c = Fugit.parse('* * * * * *') # every second
|
|
491
|
+
c = Fugit.parse('5 * * * * *') # every minute at second 5
|
|
407
492
|
```
|
|
408
493
|
|
|
409
|
-
Directly with `Fugit.parse(s)` is OK too:
|
|
410
|
-
```ruby
|
|
411
|
-
Fugit.parse('2017-12-12 12:00:00 America/New_York').to_s
|
|
412
|
-
# ==> "2017-12-12 12:00:00 -0500"
|
|
413
|
-
```
|
|
414
494
|
|
|
415
495
|
## `Fugit::Nat`
|
|
416
496
|
|
|
@@ -511,6 +591,96 @@ p Fugit.parse('every day at 12:15 midnight').original # ==> "15 24 * * *"
|
|
|
511
591
|
```
|
|
512
592
|
|
|
513
593
|
|
|
594
|
+
## `Fugit::Duration`
|
|
595
|
+
|
|
596
|
+
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).
|
|
597
|
+
|
|
598
|
+
Provides duration arithmetic tools.
|
|
599
|
+
|
|
600
|
+
```ruby
|
|
601
|
+
require 'fugit'
|
|
602
|
+
|
|
603
|
+
d = Fugit::Duration.parse('1y2M1d4h')
|
|
604
|
+
|
|
605
|
+
p d.to_plain_s # => "1Y2M1D4h"
|
|
606
|
+
p d.to_iso_s # => "P1Y2M1DT4H" ISO 8601 duration
|
|
607
|
+
p d.to_long_s # => "1 year, 2 months, 1 day, and 4 hours"
|
|
608
|
+
|
|
609
|
+
d += Fugit::Duration.parse('1y1h')
|
|
610
|
+
|
|
611
|
+
p d.to_long_s # => "2 years, 2 months, 1 day, and 5 hours"
|
|
612
|
+
|
|
613
|
+
d += 3600
|
|
614
|
+
|
|
615
|
+
p d.to_plain_s # => "2Y2M1D5h3600s"
|
|
616
|
+
|
|
617
|
+
p Fugit::Duration.parse('1y2M1d4h').to_sec # => 36820800
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
There is a `#deflate` method
|
|
621
|
+
|
|
622
|
+
```ruby
|
|
623
|
+
Fugit::Duration.parse(1000).to_plain_s # => "1000s"
|
|
624
|
+
Fugit::Duration.parse(3600).to_plain_s # => "3600s"
|
|
625
|
+
Fugit::Duration.parse(1000).deflate.to_plain_s # => "16m40s"
|
|
626
|
+
Fugit::Duration.parse(3600).deflate.to_plain_s # => "1h"
|
|
627
|
+
|
|
628
|
+
# or event shorter
|
|
629
|
+
Fugit.parse(1000).deflate.to_plain_s # => "16m40s"
|
|
630
|
+
Fugit.parse(3600).deflate.to_plain_s # => "1h"
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
There is also an `#inflate` method
|
|
634
|
+
|
|
635
|
+
```ruby
|
|
636
|
+
Fugit::Duration.parse('1h30m12').inflate.to_plain_s # => "5412s"
|
|
637
|
+
Fugit.parse('1h30m12').inflate.to_plain_s # => "5412s"
|
|
638
|
+
|
|
639
|
+
Fugit.parse('1h30m12').to_sec # => 5412
|
|
640
|
+
Fugit.parse('1h30m12').to_sec.to_s + 's' # => "5412s"
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
The `to_*_s` methods are also available as class methods:
|
|
644
|
+
```ruby
|
|
645
|
+
p Fugit::Duration.to_plain_s('1y2M1d4h')
|
|
646
|
+
# => "1Y2M1D4h"
|
|
647
|
+
p Fugit::Duration.to_iso_s('1y2M1d4h')
|
|
648
|
+
# => "P1Y2M1DT4H" ISO 8601 duration
|
|
649
|
+
p Fugit::Duration.to_long_s('1y2M1d4h')
|
|
650
|
+
# => "1 year, 2 months, 1 day, and 4 hours"
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
## `Fugit::At`
|
|
655
|
+
|
|
656
|
+
Points in time are parsed and given back as EtOrbi::EoTime instances.
|
|
657
|
+
|
|
658
|
+
```ruby
|
|
659
|
+
Fugit::At.parse('2017-12-12').to_s
|
|
660
|
+
# ==> "2017-12-12 00:00:00 +0900" (at least here in Hiroshima)
|
|
661
|
+
|
|
662
|
+
Fugit::At.parse('2017-12-12 12:00:00 America/New_York').to_s
|
|
663
|
+
# ==> "2017-12-12 12:00:00 -0500"
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
Directly with `Fugit.parse_at(s)` is OK too:
|
|
667
|
+
```ruby
|
|
668
|
+
Fugit.parse_at('2017-12-12 12:00:00 America/New_York').to_s
|
|
669
|
+
# ==> "2017-12-12 12:00:00 -0500"
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
Directly with `Fugit.parse(s)` is OK too:
|
|
673
|
+
```ruby
|
|
674
|
+
Fugit.parse('2017-12-12 12:00:00 America/New_York').to_s
|
|
675
|
+
# ==> "2017-12-12 12:00:00 -0500"
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
## KNOWN ISSUES
|
|
680
|
+
|
|
681
|
+
The gem [nice_hash](https://github.com/MarioRuiz/nice_hash) gets in the way of `fugit`, as seen in [issue 108](https://github.com/floraison/fugit/issues/108). It prevents `fugit` from correctly parsing cron strings.
|
|
682
|
+
|
|
683
|
+
|
|
514
684
|
## LICENSE
|
|
515
685
|
|
|
516
686
|
MIT, see [LICENSE.txt](LICENSE.txt)
|
data/fugit.gemspec
CHANGED
|
@@ -20,18 +20,18 @@ Time tools for flor and the floraison project. Cron parsing and occurrence compu
|
|
|
20
20
|
|
|
21
21
|
s.metadata = {
|
|
22
22
|
'changelog_uri' => s.homepage + '/blob/master/CHANGELOG.md',
|
|
23
|
-
'documentation_uri' => s.homepage,
|
|
24
23
|
'bug_tracker_uri' => s.homepage + '/issues',
|
|
25
|
-
|
|
24
|
+
'documentation_uri' => s.homepage,
|
|
26
25
|
'homepage_uri' => s.homepage,
|
|
27
26
|
'source_code_uri' => s.homepage,
|
|
27
|
+
#'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/floraison',
|
|
28
28
|
#'wiki_uri' => s.homepage + '/wiki',
|
|
29
|
+
'rubygems_mfa_required' => 'true',
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
#s.files = `git ls-files`.split("\n")
|
|
32
33
|
s.files = Dir[
|
|
33
|
-
'README.{md,txt}',
|
|
34
|
-
'CHANGELOG.{md,txt}', 'CREDITS.{md,txt}', 'LICENSE.{md,txt}',
|
|
34
|
+
'{README,CHANGELOG,CREDITS,LICENSE}.{md,txt}',
|
|
35
35
|
#'Makefile',
|
|
36
36
|
'lib/**/*.rb', #'spec/**/*.rb', 'test/**/*.rb',
|
|
37
37
|
"#{s.name}.gemspec",
|
|
@@ -41,7 +41,7 @@ Time tools for flor and the floraison project. Cron parsing and occurrence compu
|
|
|
41
41
|
# this dependency appears in 'et-orbi'
|
|
42
42
|
|
|
43
43
|
s.add_runtime_dependency 'raabro', '~> 1.4'
|
|
44
|
-
s.add_runtime_dependency 'et-orbi', '~> 1
|
|
44
|
+
s.add_runtime_dependency 'et-orbi', '~> 1.4'
|
|
45
45
|
|
|
46
46
|
s.add_development_dependency 'rspec', '~> 3.8'
|
|
47
47
|
s.add_development_dependency 'chronic', '~> 0.10'
|
data/lib/fugit/cron.rb
CHANGED
|
@@ -32,15 +32,23 @@ module Fugit
|
|
|
32
32
|
def parse(s)
|
|
33
33
|
|
|
34
34
|
return s if s.is_a?(self)
|
|
35
|
+
return nil unless s.is_a?(String)
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
s0 = s
|
|
38
|
+
s = s.strip
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
s =
|
|
41
|
+
if s[0, 1] == '@'
|
|
42
|
+
ss = s.split(/\s+/, 2)
|
|
43
|
+
[ SPECIALS[ss[0]] || ss, *ss[1..-1] ].join(' ')
|
|
44
|
+
else
|
|
45
|
+
s
|
|
46
|
+
end
|
|
39
47
|
|
|
40
48
|
#p s; Raabro.pp(Parser.parse(s, debug: 3), colors: true)
|
|
41
|
-
h = Parser.parse(s
|
|
49
|
+
h = Parser.parse(s)
|
|
42
50
|
|
|
43
|
-
self.allocate.send(:init,
|
|
51
|
+
self.allocate.send(:init, s0, h)
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
def do_parse(s)
|
|
@@ -167,34 +175,30 @@ module Fugit
|
|
|
167
175
|
|
|
168
176
|
def weekday_hash_match?(nt, hsh)
|
|
169
177
|
|
|
178
|
+
return false unless hsh.is_a?(Integer)
|
|
179
|
+
|
|
170
180
|
phsh, nhsh = nt.wday_in_month
|
|
181
|
+
#
|
|
182
|
+
# positive wday, from the beginning of the month
|
|
183
|
+
# negative wday, from the end of the month, -1 == last
|
|
171
184
|
|
|
172
|
-
|
|
173
|
-
hsh == phsh # positive wday, from the beginning of the month
|
|
174
|
-
else
|
|
175
|
-
hsh == nhsh # negative wday, from the end of the month, -1 == last
|
|
176
|
-
end
|
|
185
|
+
(hsh == phsh) || (hsh == nhsh)
|
|
177
186
|
end
|
|
178
187
|
|
|
179
188
|
def weekday_modulo_match?(nt, mod)
|
|
180
189
|
|
|
181
|
-
(
|
|
190
|
+
mod.is_a?(Array) &&
|
|
191
|
+
((nt.rweek % mod[0]) == (mod[1] % mod[0]))
|
|
182
192
|
end
|
|
183
193
|
|
|
184
194
|
def weekday_match?(nt)
|
|
185
195
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if hom.is_a?(Array)
|
|
194
|
-
weekday_modulo_match?(nt, hom)
|
|
195
|
-
else
|
|
196
|
-
weekday_hash_match?(nt, hom)
|
|
197
|
-
end
|
|
196
|
+
@weekdays.nil? ||
|
|
197
|
+
@weekdays.find { |wd, hom|
|
|
198
|
+
(nt.wday == wd) &&
|
|
199
|
+
(hom.nil? ||
|
|
200
|
+
weekday_modulo_match?(nt, hom) ||
|
|
201
|
+
weekday_hash_match?(nt, hom)) }
|
|
198
202
|
end
|
|
199
203
|
|
|
200
204
|
def monthday_match?(nt)
|
|
@@ -727,7 +731,8 @@ module Fugit
|
|
|
727
731
|
else
|
|
728
732
|
a.collect(&:to_s).join('#')
|
|
729
733
|
end }
|
|
730
|
-
.join(',')
|
|
734
|
+
.join(',') +
|
|
735
|
+
(@day_and ? '&' : '')
|
|
731
736
|
end
|
|
732
737
|
|
|
733
738
|
module Parser include Raabro
|
data/lib/fugit/duration.rb
CHANGED
|
@@ -67,11 +67,20 @@ module Fugit
|
|
|
67
67
|
day: { a: 'D', r: 'd', i: 'D', s: DAY_S, I: true, l: 'day' },
|
|
68
68
|
hou: { a: 'h', r: 'h', i: 'H', s: 3600, I: true, l: 'hour' },
|
|
69
69
|
min: { a: 'm', r: 'm', i: 'M', s: 60, I: true, l: 'minute' },
|
|
70
|
-
sec: { a: 's', r: 's', i: 'S', s: 1, I: true, l: 'second' }
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
sec: { a: 's', r: 's', i: 'S', s: 1, I: true, l: 'second' }
|
|
71
|
+
}.freeze
|
|
72
|
+
|
|
73
|
+
#INFLA_KEYS, NON_INFLA_KEYS = KEYS
|
|
74
|
+
# .partition { |k, v| v[:I] }
|
|
75
|
+
# .collect(&:freeze)
|
|
76
|
+
#
|
|
77
|
+
# https://bugs.ruby-lang.org/issues/16252
|
|
78
|
+
#
|
|
79
|
+
kes = KEYS.entries
|
|
80
|
+
INFLA_KEYS,
|
|
81
|
+
NON_INFLA_KEYS =
|
|
82
|
+
kes.select { |_, v| v[:I] }.freeze,
|
|
83
|
+
kes.select { |_, v| ! v[:I] }.freeze
|
|
75
84
|
|
|
76
85
|
def _to_s(key)
|
|
77
86
|
|
data/lib/fugit/nat.rb
CHANGED
|
@@ -54,7 +54,7 @@ module Fugit
|
|
|
54
54
|
%w[ zero ] + one_to_nine +
|
|
55
55
|
%w[ ten eleven twelve thirteen fourteen fifteen sixteen seventeen
|
|
56
56
|
eighteen nineteen ] +
|
|
57
|
-
%w[ twenty thirty
|
|
57
|
+
%w[ twenty thirty forty fifty ]
|
|
58
58
|
.collect { |a|
|
|
59
59
|
([ nil ] + one_to_nine)
|
|
60
60
|
.collect { |b| [ a, b ].compact.join('-') } }
|
|
@@ -210,7 +210,7 @@ module Fugit
|
|
|
210
210
|
end
|
|
211
211
|
|
|
212
212
|
def ampm(i)
|
|
213
|
-
rex(:ampm, i, /[ \t]*(am|pm|
|
|
213
|
+
rex(:ampm, i, /[ \t]*(am|AM|pm|PM|[Nn]oon|[Mm]idday|[Mm]idnight)/)
|
|
214
214
|
end
|
|
215
215
|
def dark(i)
|
|
216
216
|
rex(:dark, i, /[ \t]*dark/i)
|
|
@@ -719,6 +719,8 @@ module Fugit
|
|
|
719
719
|
end
|
|
720
720
|
end
|
|
721
721
|
|
|
722
|
+
SLASH_REGEX = /^(\d+|\*)\/(\d+)$/.freeze
|
|
723
|
+
|
|
722
724
|
# Return nil if the cron is "not strict"
|
|
723
725
|
#
|
|
724
726
|
# For example, "0 0/17 * * *" (gh-86) is a perfectly valid
|
|
@@ -729,16 +731,18 @@ module Fugit
|
|
|
729
731
|
#
|
|
730
732
|
def restrict(a, cron)
|
|
731
733
|
|
|
732
|
-
if m = ((a[
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
734
|
+
if m = ((a[0] && a[0] != [ 0 ] && a[0][0]) || '').match(SLASH_REGEX)
|
|
735
|
+
return nil unless (1..60).include?(m[1].to_i)
|
|
736
|
+
end
|
|
737
|
+
if m = ((a[1] && a[1][0]) || '').match(SLASH_REGEX)
|
|
738
|
+
return nil unless [ 1, 2, 3, 4, 5, 6, 8, 12 ].include?(m[1].to_i)
|
|
736
739
|
end
|
|
737
740
|
|
|
738
741
|
cron
|
|
739
742
|
end
|
|
740
743
|
|
|
741
744
|
def slot(key, default)
|
|
745
|
+
|
|
742
746
|
s = @slots[key]
|
|
743
747
|
s ? s.data0 : [ default ]
|
|
744
748
|
end
|
data/lib/fugit/parse.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Fugit
|
|
4
4
|
|
|
5
|
+
DO_PARSE_ORDER = %i[ cron duration nat at ].freeze
|
|
6
|
+
|
|
5
7
|
class << self
|
|
6
8
|
|
|
7
9
|
def parse_cron(s); ::Fugit::Cron.parse(s); end
|
|
@@ -34,7 +36,7 @@ module Fugit
|
|
|
34
36
|
result = nil
|
|
35
37
|
errors = []
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
DO_PARSE_ORDER
|
|
38
40
|
.each { |k|
|
|
39
41
|
begin
|
|
40
42
|
result ||= (opts[k] != false && self.send("do_parse_#{k}", s))
|
|
@@ -63,6 +65,24 @@ module Fugit
|
|
|
63
65
|
fail(ArgumentError.new("not cron or 'natural' cron string: #{s.inspect}"))
|
|
64
66
|
end
|
|
65
67
|
|
|
68
|
+
def parse_max(s, opts={})
|
|
69
|
+
|
|
70
|
+
s0 = s.lines.first
|
|
71
|
+
|
|
72
|
+
(0..[ ::Fugit::Nat::MAX_INPUT_LENGTH, s0.length - 1 ].min).each do |i|
|
|
73
|
+
|
|
74
|
+
s1 =
|
|
75
|
+
s0[0, s0.length - i].rstrip
|
|
76
|
+
f =
|
|
77
|
+
opts[:cronish] ? parse_cronish(s1, opts) :
|
|
78
|
+
parse(s1, opts)
|
|
79
|
+
|
|
80
|
+
return [ s1, f ] if f
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
nil
|
|
84
|
+
end
|
|
85
|
+
|
|
66
86
|
def determine_type(s)
|
|
67
87
|
|
|
68
88
|
case self.parse(s)
|
data/lib/fugit.rb
CHANGED
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: 1.
|
|
4
|
+
version: 1.12.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Mettraux
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-10-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: raabro
|
|
@@ -30,20 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1'
|
|
34
|
-
- - ">="
|
|
35
|
-
- !ruby/object:Gem::Version
|
|
36
|
-
version: 1.2.11
|
|
33
|
+
version: '1.4'
|
|
37
34
|
type: :runtime
|
|
38
35
|
prerelease: false
|
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
37
|
requirements:
|
|
41
38
|
- - "~>"
|
|
42
39
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: '1'
|
|
44
|
-
- - ">="
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: 1.2.11
|
|
40
|
+
version: '1.4'
|
|
47
41
|
- !ruby/object:Gem::Dependency
|
|
48
42
|
name: rspec
|
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -97,10 +91,11 @@ licenses:
|
|
|
97
91
|
- MIT
|
|
98
92
|
metadata:
|
|
99
93
|
changelog_uri: https://github.com/floraison/fugit/blob/master/CHANGELOG.md
|
|
100
|
-
documentation_uri: https://github.com/floraison/fugit
|
|
101
94
|
bug_tracker_uri: https://github.com/floraison/fugit/issues
|
|
95
|
+
documentation_uri: https://github.com/floraison/fugit
|
|
102
96
|
homepage_uri: https://github.com/floraison/fugit
|
|
103
97
|
source_code_uri: https://github.com/floraison/fugit
|
|
98
|
+
rubygems_mfa_required: 'true'
|
|
104
99
|
post_install_message:
|
|
105
100
|
rdoc_options: []
|
|
106
101
|
require_paths:
|
|
@@ -116,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
116
111
|
- !ruby/object:Gem::Version
|
|
117
112
|
version: '0'
|
|
118
113
|
requirements: []
|
|
119
|
-
rubygems_version: 3.4.
|
|
114
|
+
rubygems_version: 3.4.19
|
|
120
115
|
signing_key:
|
|
121
116
|
specification_version: 4
|
|
122
117
|
summary: time tools for flor
|