periodoxical 0.9.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +55 -30
- data/lib/periodoxical/helpers.rb +70 -0
- data/lib/periodoxical/validation.rb +2 -2
- data/lib/periodoxical/version.rb +1 -1
- data/lib/periodoxical.rb +48 -49
- metadata +3 -3
- data/.travis.yml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b67da50d1bba17e1d25babaa937440ccad41bf152d1df8d3adb50ff8c9199b3
|
4
|
+
data.tar.gz: 954c91d5da06a9d4955fdb35576b11f1e209a8ab152825c3f09657e891787a5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab9f0eb8538ea18407171b2d9dc435935821370f3f3d229f59d718e3e11f3eba6b6f926129274f33c5100b22a70d937ba6f9693d714f52abaf0f2a7be4965d28
|
7
|
+
data.tar.gz: 64503a74a1879ae8d0cda934ad511530ff6c22e5f1aeb9fe331f0dda99ccf8d7b81c735e2d10a9c6ce468010ea64674c1d8bc86a24fa8f18aa5382cfd29facdd
|
data/CODE_OF_CONDUCT.md
CHANGED
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
|
|
55
55
|
## Enforcement
|
56
56
|
|
57
57
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
-
reported by contacting the project team at
|
58
|
+
reported by contacting the project team at stevenJLi@gmail.com. All
|
59
59
|
complaints will be reviewed and investigated and will result in a response that
|
60
60
|
is deemed necessary and appropriate to the circumstances. The project team is
|
61
61
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -29,7 +29,7 @@ Or install it yourself as:
|
|
29
29
|
|
30
30
|
## Usage
|
31
31
|
|
32
|
-
### Example
|
32
|
+
### Basic Example
|
33
33
|
As a Ruby dev, I want to generate all the datetime blocks of **9:00AM - 10:30AM** for all days from **May 23, 2024** to **May 26, 2024** inclusive.
|
34
34
|
|
35
35
|
```rb
|
@@ -41,8 +41,8 @@ Periodoxical.generate(
|
|
41
41
|
end_time: '10:30AM'
|
42
42
|
},
|
43
43
|
],
|
44
|
-
|
45
|
-
|
44
|
+
starting_from: '2024-05-23',
|
45
|
+
ending_at: '2024-05-26',
|
46
46
|
)
|
47
47
|
#=>
|
48
48
|
[
|
@@ -65,8 +65,33 @@ Periodoxical.generate(
|
|
65
65
|
]
|
66
66
|
```
|
67
67
|
|
68
|
-
|
69
|
-
|
68
|
+
The `starting_from` and `ending_at` params can also accept datetimes in ISO 8601 format. This example generate all the datetime blocks of **9:00AM - 10:30AM** but starting from **May 23, 2024 at 9:30AM**.
|
69
|
+
|
70
|
+
```rb
|
71
|
+
Periodoxical.generate(
|
72
|
+
time_zone: 'America/Los_Angeles',
|
73
|
+
time_blocks: [
|
74
|
+
{
|
75
|
+
start_time: '9:00AM',
|
76
|
+
end_time: '10:30AM'
|
77
|
+
},
|
78
|
+
],
|
79
|
+
starting_from: '2024-05-23T09:30:00-07:00', # can be string in iso8601 format
|
80
|
+
ending_at: DateTime.parse('2024-05-26T17:00:00-07:00'), # or an instance of DateTime
|
81
|
+
)
|
82
|
+
#=> [
|
83
|
+
# 2024-05-23 was skipped because the 9AM time block was before
|
84
|
+
# the `starting_from` of '2024-05-23T09:30:00-07:00'
|
85
|
+
{
|
86
|
+
start_time: #<DateTime: 2024-05-24T09:00:00-0700>,
|
87
|
+
end_time: #<DateTime: 2024-05-24T10:30:00-0700>,
|
88
|
+
},
|
89
|
+
...
|
90
|
+
]
|
91
|
+
```
|
92
|
+
|
93
|
+
### Specify days of the week
|
94
|
+
As a Ruby dev, I want to generate all the datetime blocks of **9:00AM - 10:30AM** and **2:00PM - 2:30PM**, on **Mondays**, **Wednesdays**, and **Thursdays**, between the dates of **May 23, 2024** and **June 12, 2024**, inclusive. I can do this using the `days_of_week` parameter. This can be represented visually as:
|
70
95
|
|
71
96
|
<div align="center">
|
72
97
|
<img width="558" alt="calendar_image_1" src="https://github.com/StevenJL/periodoxical/assets/2191808/e92fc6ff-03fd-44ed-a955-d3a0dd0f5d0a">
|
@@ -89,8 +114,8 @@ Periodoxical.generate(
|
|
89
114
|
end_time: '2:30PM'
|
90
115
|
}
|
91
116
|
],
|
92
|
-
|
93
|
-
|
117
|
+
starting_from: '2024-05-23',
|
118
|
+
ending_at: '2024-06-12',
|
94
119
|
)
|
95
120
|
# returns an array of hashes, each with :start and :end keys
|
96
121
|
#=>
|
@@ -115,9 +140,9 @@ Periodoxical.generate(
|
|
115
140
|
]
|
116
141
|
```
|
117
142
|
|
118
|
-
### Example
|
143
|
+
### Example using the `limit` parameter.
|
119
144
|
|
120
|
-
As a ruby dev, I want to generate the next **3** datetime blocks of **9:00AM - 10:30AM** and **2:00PM - 2:30PM** on **Sundays**, after **May 23, 2024
|
145
|
+
As a ruby dev, I want to generate the next **3** datetime blocks of **9:00AM - 10:30AM** and **2:00PM - 2:30PM** on **Sundays**, after **May 23, 2024**. I can do this using the `limit` parameter, instead of `ending_at`.
|
121
146
|
|
122
147
|
```rb
|
123
148
|
Periodoxical.generate(
|
@@ -133,7 +158,7 @@ Periodoxical.generate(
|
|
133
158
|
end_time: '2:30PM'
|
134
159
|
}
|
135
160
|
],
|
136
|
-
|
161
|
+
starting_from: Date.parse('2024-05-23'), # Can also pass in `Date` object.
|
137
162
|
limit: 3
|
138
163
|
)
|
139
164
|
# =>
|
@@ -153,9 +178,9 @@ Periodoxical.generate(
|
|
153
178
|
]
|
154
179
|
```
|
155
180
|
|
156
|
-
###
|
181
|
+
### Time blocks that vary between days-of-the-week
|
157
182
|
|
158
|
-
As a ruby dev, I want to generate all the timeblocks between **May 23, 2024** and **June 12, 2024** where the time should be **8AM-9AM** on **Mondays**, but **10:45AM-12:00PM** and **2:00PM-4:00PM** on **Wednesdays**, and **2:30PM-4:15PM** on **Thursdays**.
|
183
|
+
As a ruby dev, I want to generate all the timeblocks between **May 23, 2024** and **June 12, 2024** where the time should be **8AM-9AM** on **Mondays**, but **10:45AM-12:00PM** and **2:00PM-4:00PM** on **Wednesdays**, and **2:30PM-4:15PM** on **Thursdays**. I can do this using the `day_of_week_time_blocks` parameter.
|
159
184
|
|
160
185
|
<div align="center">
|
161
186
|
<img width="628" alt="calendar_image_2" src="https://github.com/StevenJL/periodoxical/assets/2191808/26d14824-08ff-481a-97e2-9b6b11beea29">
|
@@ -167,8 +192,8 @@ As a ruby dev, I want to generate all the timeblocks between **May 23, 2024** an
|
|
167
192
|
```rb
|
168
193
|
Periodoxical.generate(
|
169
194
|
time_zone: 'America/Los_Angeles',
|
170
|
-
|
171
|
-
|
195
|
+
starting_from: Date.parse('2024-05-23'), # can also pass in Date objects
|
196
|
+
ending_at: Date.parse('2024-06-12'), # can also pass in Date objects,
|
172
197
|
day_of_week_time_blocks: {
|
173
198
|
mon: [
|
174
199
|
{ start_time: '8:00AM', end_time: '9:00AM' },
|
@@ -184,14 +209,14 @@ Periodoxical.generate(
|
|
184
209
|
)
|
185
210
|
```
|
186
211
|
|
187
|
-
###
|
212
|
+
### Specifying time blocks using rules for day-of-month and/or week-of-month and/or month.
|
188
213
|
|
189
|
-
As a Ruby dev, I want to generate the next 3 timeblocks for **8AM - 9AM** for the **5th** and **10th** day of every month starting from **June
|
214
|
+
As a Ruby dev, I want to generate the next 3 timeblocks for **8AM - 9AM** for the **5th** and **10th** day of every month starting from **June**. I can do this using the `days_of_month` parameter.
|
190
215
|
|
191
216
|
```rb
|
192
217
|
Periodoxical.generate(
|
193
218
|
time_zone: 'America/Los_Angeles',
|
194
|
-
|
219
|
+
starting_from: '2024-06-01',
|
195
220
|
limit: 3,
|
196
221
|
days_of_month: [5, 10],
|
197
222
|
time_blocks: [
|
@@ -215,12 +240,12 @@ Periodoxical.generate(
|
|
215
240
|
]
|
216
241
|
```
|
217
242
|
|
218
|
-
As a Ruby dev, I want to generate **4** timeblocks for **8AM - 9AM** on **Mondays** but only in the **first two weeks** in the months of **April, May, and June
|
243
|
+
As a Ruby dev, I want to generate **4** timeblocks for **8AM - 9AM** on **Mondays** but only in the **first two weeks** in the months of **April, May, and June**. I can do this using the `months` parameter.
|
219
244
|
|
220
245
|
```
|
221
246
|
Periodoxical.generate(
|
222
247
|
time_zone: 'America/Los_Angeles',
|
223
|
-
|
248
|
+
starting_from: '2024-04-01',
|
224
249
|
limit: 4,
|
225
250
|
weeks_of_month: [1 2],
|
226
251
|
months: [4, 5, 6],
|
@@ -256,11 +281,11 @@ As a Ruby dev, I want to generate timeblocks for **8AM - 9AM** on the **first an
|
|
256
281
|
```rb
|
257
282
|
Periodoxical.generate(
|
258
283
|
time_zone: 'America/Los_Angeles',
|
259
|
-
|
284
|
+
starting_from: '2024-06-01',
|
260
285
|
limit: 5,
|
261
286
|
nth_day_of_week_in_month: {
|
262
287
|
mon: [1, 2], # valid values: -1,1,2,3,4,5
|
263
|
-
fri: [-1], # Use -1 to specify
|
288
|
+
fri: [-1], # Use -1 to specify the last Friday of the month.
|
264
289
|
},
|
265
290
|
time_blocks: [
|
266
291
|
{ start_time: '8:00AM', end_time: '9:00AM' },
|
@@ -292,12 +317,12 @@ Periodoxical.generate(
|
|
292
317
|
```
|
293
318
|
|
294
319
|
### Example 7 - Exclude time blocks using the `exclusion_dates` and `exclusion_times` parameters
|
295
|
-
As a Ruby dev, I want to generate timeblocks for **8AM - 9AM** on **Mondays**, except for the **Monday of June 10, 2024**.
|
320
|
+
As a Ruby dev, I want to generate timeblocks for **8AM - 9AM** on **Mondays**, except for the **Monday of June 10, 2024**. I can do this using the `exlcusion_dates` parameter.
|
296
321
|
|
297
322
|
```rb
|
298
323
|
Periodoxical.generate(
|
299
324
|
time_zone: 'America/Los_Angeles',
|
300
|
-
|
325
|
+
starting_from: '2024-06-03',
|
301
326
|
limit: 4,
|
302
327
|
exclusion_dates: %w(2024-06-10),
|
303
328
|
day_of_week_time_blocks: {
|
@@ -333,7 +358,7 @@ As a Ruby dev, I want to generate timeblocks for **8AM - 9AM**, and **10AM - 11A
|
|
333
358
|
```rb
|
334
359
|
Periodoxical.generate(
|
335
360
|
time_zone: 'America/Los_Angeles',
|
336
|
-
|
361
|
+
starting_from: '2024-06-03',
|
337
362
|
limit: 4,
|
338
363
|
days_of_week: %(mon),
|
339
364
|
time_blocks: [
|
@@ -379,7 +404,7 @@ Periodoxical.generate(
|
|
379
404
|
|
380
405
|
### Example 8 - Every-other-nth day-of-week rules (ie. every other Tuesday, every 3rd Wednesday, every 10th Friday)
|
381
406
|
|
382
|
-
As a Ruby dev, I want to generate timeblocks for **9AM- 10AM** on **every Monday**, but **every other Tuesday**, and **every other 3rd Wednesday**. I can do this using the `days_of_week` parameter
|
407
|
+
As a Ruby dev, I want to generate timeblocks for **9AM- 10AM** on **every Monday**, but **every other Tuesday**, and **every other 3rd Wednesday**. I can do this using the `days_of_week` parameter with the `every` and `every_other_nth` keys to specify the every-other-nth-rules.
|
383
408
|
|
384
409
|
This can be visualized as:
|
385
410
|
|
@@ -393,11 +418,11 @@ This can be visualized as:
|
|
393
418
|
```rb
|
394
419
|
Periodoxical.generate(
|
395
420
|
time_zone: 'America/Los_Angeles',
|
396
|
-
|
421
|
+
starting_from: '2024-12-30',
|
397
422
|
days_of_week: {
|
398
423
|
mon: { every: true }, # every Monday (no skipping)
|
399
|
-
tue: { every_other_nth: 2 }, # every other Tuesday starting at first Tuesday from
|
400
|
-
wed: { every_other_nth: 3 }, # every 3rd Wednesday starting at first Wednesday from
|
424
|
+
tue: { every_other_nth: 2 }, # every other Tuesday starting at first Tuesday from `starting_from` date
|
425
|
+
wed: { every_other_nth: 3 }, # every 3rd Wednesday starting at first Wednesday from `starting_from` date
|
401
426
|
},
|
402
427
|
limit: 10,
|
403
428
|
time_blocks: [
|
@@ -456,7 +481,7 @@ Generate all the Friday the 13ths ever since May 1980 (when the first Friday the
|
|
456
481
|
```rb
|
457
482
|
Periodoxical.generate(
|
458
483
|
time_zone: 'America/Los_Angeles',
|
459
|
-
|
484
|
+
starting_from: '1980-05-01',
|
460
485
|
days_of_week: %w(fri),
|
461
486
|
days_of_month: [13],
|
462
487
|
limit: 100,
|
@@ -491,7 +516,7 @@ Generate the next 10 Thanksgivings from now on (Thanksgivings is defined as the
|
|
491
516
|
```rb
|
492
517
|
Periodoxical.generate(
|
493
518
|
time_zone: 'America/Los_Angeles',
|
494
|
-
|
519
|
+
starting_from: '2024-05-01',
|
495
520
|
months: [11],
|
496
521
|
nth_day_of_week_in_month: {
|
497
522
|
thu: [4],
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Periodoxical
|
2
|
+
module Helpers
|
3
|
+
def deep_symbolize_keys(obj)
|
4
|
+
return unless obj
|
5
|
+
|
6
|
+
case obj
|
7
|
+
when Hash
|
8
|
+
obj.each_with_object({}) do |(key, value), result|
|
9
|
+
symbolized_key = key.to_sym rescue key
|
10
|
+
result[symbolized_key] = deep_symbolize_keys(value)
|
11
|
+
end
|
12
|
+
when Array
|
13
|
+
obj.map { |e| deep_symbolize_keys(e) }
|
14
|
+
else
|
15
|
+
obj
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Hash] time_block_1, time_block_2
|
20
|
+
# Ex: {
|
21
|
+
# start: #<DateTime>,
|
22
|
+
# end: #<DateTime>,
|
23
|
+
# }
|
24
|
+
def overlap?(time_block_1, time_block_2)
|
25
|
+
tb_1_start = time_block_1[:start]
|
26
|
+
tb_1_end = time_block_1[:end]
|
27
|
+
tb_2_start = time_block_2[:start]
|
28
|
+
tb_2_end = time_block_2[:end]
|
29
|
+
|
30
|
+
# Basicall overlap is when one starts before the other has ended
|
31
|
+
return true if tb_1_end > tb_2_start && tb_1_end < tb_2_end
|
32
|
+
# By symmetry
|
33
|
+
return true if tb_2_end > tb_1_start && tb_2_end < tb_1_end
|
34
|
+
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def date_object_from(dt)
|
39
|
+
return unless dt
|
40
|
+
return dt if dt.is_a?(Date) || dt.is_a?(DateTime)
|
41
|
+
|
42
|
+
if dt.is_a?(String)
|
43
|
+
return Date.parse(dt) if /\A\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01])\z/ =~ dt
|
44
|
+
|
45
|
+
if /\A\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-][01]\d:[0-5]\d)?\z/ =~ dt
|
46
|
+
# convert to DateTime object
|
47
|
+
dt = DateTime.parse(dt)
|
48
|
+
# convert to given time_zone
|
49
|
+
return dt.to_time.localtime(@time_zone.utc_offset).to_datetime
|
50
|
+
end
|
51
|
+
|
52
|
+
raise "Could not parse date/datetime string #{dt}. Please README for examples."
|
53
|
+
else
|
54
|
+
raise "Invalid argument: #{dt}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def day_of_week_long_to_short(dow)
|
59
|
+
{
|
60
|
+
"Monday" => "mon",
|
61
|
+
"Tuesday" => "tue",
|
62
|
+
"Wednesday" => "wed",
|
63
|
+
"Thursday" => "thu",
|
64
|
+
"Friday" => "fri",
|
65
|
+
"Saturday" => "sat",
|
66
|
+
"Sunday" => "sun",
|
67
|
+
}[dow]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -96,8 +96,8 @@ module Periodoxical
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
unless( @limit || @
|
100
|
-
raise "Either `limit` or `
|
99
|
+
unless( @limit || @ending_at)
|
100
|
+
raise "Either `limit` or `ending_at` must be provided"
|
101
101
|
end
|
102
102
|
|
103
103
|
if @exclusion_times
|
data/lib/periodoxical/version.rb
CHANGED
data/lib/periodoxical.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "periodoxical/version"
|
2
2
|
require "periodoxical/validation"
|
3
|
+
require "periodoxical/helpers"
|
3
4
|
require "date"
|
4
5
|
require "time"
|
5
6
|
require "tzinfo"
|
@@ -14,11 +15,12 @@ module Periodoxical
|
|
14
15
|
|
15
16
|
class Core
|
16
17
|
include Periodoxical::Validation
|
18
|
+
include Periodoxical::Helpers
|
17
19
|
# @param [String] time_zone
|
18
20
|
# Ex: 'America/Los_Angeles', 'America/Chicago',
|
19
21
|
# TZInfo::DataTimezone#name from the tzinfo gem (https://github.com/tzinfo/tzinfo)
|
20
|
-
# @param [Date, String]
|
21
|
-
# @param [Date, String]
|
22
|
+
# @param [Date, String] starting_from
|
23
|
+
# @param [Date, String] ending_at
|
22
24
|
# @param [Array<Hash>] time_blocks
|
23
25
|
# Ex: [
|
24
26
|
# {
|
@@ -40,7 +42,7 @@ module Periodoxical
|
|
40
42
|
# @param [Array<Integer>, nil] months
|
41
43
|
# Months as integers, where 1 = Jan, 12 = Dec
|
42
44
|
# @param [Integer] limit
|
43
|
-
# How many date times to generate. To be used when `
|
45
|
+
# How many date times to generate. To be used when `ending_at` is nil.
|
44
46
|
# @param [Aray<String>] exclusion_dates
|
45
47
|
# Dates to be excluded when generating the time blocks
|
46
48
|
# Ex: ['2024-06-10', '2024-06-14']
|
@@ -65,8 +67,8 @@ module Periodoxical
|
|
65
67
|
# fri: { start_time: '7:00PM', end_time: '9:00PM' },
|
66
68
|
# }
|
67
69
|
def initialize(
|
68
|
-
|
69
|
-
|
70
|
+
starting_from:,
|
71
|
+
ending_at: nil,
|
70
72
|
time_blocks: nil,
|
71
73
|
day_of_week_time_blocks: nil,
|
72
74
|
limit: nil,
|
@@ -82,24 +84,24 @@ module Periodoxical
|
|
82
84
|
|
83
85
|
@time_zone = TZInfo::Timezone.get(time_zone)
|
84
86
|
if days_of_week.is_a?(Array)
|
85
|
-
@days_of_week = days_of_week
|
87
|
+
@days_of_week = deep_symbolize_keys(days_of_week)
|
86
88
|
elsif days_of_week.is_a?(Hash)
|
87
|
-
@days_of_week_with_alternations = days_of_week
|
89
|
+
@days_of_week_with_alternations = deep_symbolize_keys(days_of_week)
|
88
90
|
end
|
89
|
-
@nth_day_of_week_in_month = nth_day_of_week_in_month
|
91
|
+
@nth_day_of_week_in_month = deep_symbolize_keys(nth_day_of_week_in_month)
|
90
92
|
@days_of_month = days_of_month
|
91
93
|
@weeks_of_month = weeks_of_month
|
92
94
|
@months = months
|
93
|
-
@time_blocks = time_blocks
|
94
|
-
@day_of_week_time_blocks = day_of_week_time_blocks
|
95
|
-
@
|
96
|
-
@
|
95
|
+
@time_blocks = deep_symbolize_keys(time_blocks)
|
96
|
+
@day_of_week_time_blocks = deep_symbolize_keys(day_of_week_time_blocks)
|
97
|
+
@starting_from = date_object_from(starting_from)
|
98
|
+
@ending_at = date_object_from(ending_at)
|
97
99
|
@limit = limit
|
98
100
|
@exclusion_dates = if exclusion_dates && !exclusion_dates.empty?
|
99
101
|
exclusion_dates.map { |ed| Date.parse(ed) }
|
100
102
|
end
|
101
103
|
@exclusion_times = if exclusion_times
|
102
|
-
exclusion_times.map do |et|
|
104
|
+
deep_symbolize_keys(exclusion_times).map do |et|
|
103
105
|
{ start: DateTime.parse(et[:start]), end: DateTime.parse(et[:end]) }
|
104
106
|
end
|
105
107
|
end
|
@@ -130,18 +132,6 @@ module Periodoxical
|
|
130
132
|
|
131
133
|
private
|
132
134
|
|
133
|
-
def day_of_week_long_to_short(dow)
|
134
|
-
{
|
135
|
-
"Monday" => "mon",
|
136
|
-
"Tuesday" => "tue",
|
137
|
-
"Wednesday" => "wed",
|
138
|
-
"Thursday" => "thu",
|
139
|
-
"Friday" => "fri",
|
140
|
-
"Saturday" => "sat",
|
141
|
-
"Sunday" => "sun",
|
142
|
-
}[dow]
|
143
|
-
end
|
144
|
-
|
145
135
|
# @param [String] time_str
|
146
136
|
# Ex: '9:00AM'
|
147
137
|
# @param [Date] date
|
@@ -174,7 +164,11 @@ module Periodoxical
|
|
174
164
|
# Variables which manage flow of looping through time and generating slots
|
175
165
|
def initialize_looping_variables!
|
176
166
|
@output = []
|
177
|
-
|
167
|
+
if @starting_from.is_a?(DateTime)
|
168
|
+
@current_date = @starting_from.to_date
|
169
|
+
else
|
170
|
+
@current_date = @starting_from
|
171
|
+
end
|
178
172
|
@current_day_of_week = day_of_week_long_to_short(@current_date.strftime("%A"))
|
179
173
|
@current_count = 0
|
180
174
|
@keep_generating = true
|
@@ -205,6 +199,7 @@ module Periodoxical
|
|
205
199
|
def append_to_output_and_check_limit(time_block)
|
206
200
|
# Check if this particular time is conflicts with any times from `exclusion_times`.
|
207
201
|
return if overlaps_with_an_excluded_time?(time_block)
|
202
|
+
return if before_starting_from_or_after_ending_at?(time_block)
|
208
203
|
|
209
204
|
@output << {
|
210
205
|
start: time_str_to_object(@current_date, time_block[:start_time]),
|
@@ -224,7 +219,7 @@ module Periodoxical
|
|
224
219
|
|
225
220
|
@current_day_of_week = day_of_week_long_to_short(@current_date.strftime("%A"))
|
226
221
|
|
227
|
-
if @
|
222
|
+
if @ending_at && (@current_date > @ending_at)
|
228
223
|
@keep_generating = false
|
229
224
|
end
|
230
225
|
|
@@ -232,7 +227,7 @@ module Periodoxical
|
|
232
227
|
# there is bug, or poorly specified rules. If @current_date goes into
|
233
228
|
# 1000 years in the future, but still no dates have been generated yet, this is
|
234
229
|
# most likely an infinite loop situation, and needs to be killed.
|
235
|
-
if @limit && ((@current_date - @
|
230
|
+
if @limit && ((@current_date - @starting_from).to_i > 365000) && @output.empty?
|
236
231
|
raise "No end condition detected, causing infinite loop. Please check rules/conditions or raise github issue for potential bug fixed"
|
237
232
|
end
|
238
233
|
end
|
@@ -324,8 +319,8 @@ module Periodoxical
|
|
324
319
|
# end_time: '10:30AM'
|
325
320
|
# },
|
326
321
|
# ],
|
327
|
-
#
|
328
|
-
#
|
322
|
+
# starting_from: '2024-05-23',
|
323
|
+
# ending_at: '2024-05-27',
|
329
324
|
# )
|
330
325
|
# where if we don't specify any date-of-week/month constraints, we return all consecutive dates.
|
331
326
|
# In the future, if we don't support this case, we can use `false` as the return value.
|
@@ -373,6 +368,29 @@ module Periodoxical
|
|
373
368
|
@days_of_week_running_tally[@current_day_of_week.to_sym] = @days_of_week_running_tally[@current_day_of_week.to_sym] + 1
|
374
369
|
end
|
375
370
|
|
371
|
+
# @return [Boolean]
|
372
|
+
# Used only when `starting_from` and `ending_at` are instances of DateTime
|
373
|
+
# instead of Date, requiring more precision, calculation.
|
374
|
+
def before_starting_from_or_after_ending_at?(time_block)
|
375
|
+
return false unless @starting_from.is_a?(DateTime) || @ending_at.is_a?(DateTime)
|
376
|
+
|
377
|
+
if @starting_from.is_a?(DateTime)
|
378
|
+
start_time = time_str_to_object(@current_date, time_block[:start_time])
|
379
|
+
|
380
|
+
# If the candidate time block is starting earlier than @starting_from, we want to skip it
|
381
|
+
return true if start_time < @starting_from
|
382
|
+
end
|
383
|
+
|
384
|
+
if @ending_at.is_a?(DateTime)
|
385
|
+
end_time = time_str_to_object(@current_date, time_block[:end_time])
|
386
|
+
|
387
|
+
# If the candidate time block is ending after @ending_at, we want to skip it
|
388
|
+
return true if end_time > @ending_at
|
389
|
+
end
|
390
|
+
|
391
|
+
false
|
392
|
+
end
|
393
|
+
|
376
394
|
# @return [Boolean]
|
377
395
|
# Whether or not the given `time_block` in the @current_date and
|
378
396
|
# @time_zone overlaps with the times in `exclusion_times`.
|
@@ -391,24 +409,5 @@ module Periodoxical
|
|
391
409
|
|
392
410
|
false
|
393
411
|
end
|
394
|
-
|
395
|
-
# @param [Hash] time_block_1, time_block_2
|
396
|
-
# Ex: {
|
397
|
-
# start: #<DateTime>,
|
398
|
-
# end: #<DateTime>,
|
399
|
-
# }
|
400
|
-
def overlap?(time_block_1, time_block_2)
|
401
|
-
tb_1_start = time_block_1[:start]
|
402
|
-
tb_1_end = time_block_1[:end]
|
403
|
-
tb_2_start = time_block_2[:start]
|
404
|
-
tb_2_end = time_block_2[:end]
|
405
|
-
|
406
|
-
# Basicall overlap is when one starts before the other has ended
|
407
|
-
return true if tb_1_end > tb_2_start && tb_1_end < tb_2_end
|
408
|
-
# By symmetry
|
409
|
-
return true if tb_2_end > tb_1_start && tb_2_end < tb_1_end
|
410
|
-
|
411
|
-
false
|
412
|
-
end
|
413
412
|
end
|
414
413
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: periodoxical
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Li
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tzinfo
|
@@ -125,7 +125,6 @@ extra_rdoc_files: []
|
|
125
125
|
files:
|
126
126
|
- ".gitignore"
|
127
127
|
- ".rspec"
|
128
|
-
- ".travis.yml"
|
129
128
|
- CODE_OF_CONDUCT.md
|
130
129
|
- Gemfile
|
131
130
|
- Gemfile.lock
|
@@ -135,6 +134,7 @@ files:
|
|
135
134
|
- bin/console
|
136
135
|
- bin/setup
|
137
136
|
- lib/periodoxical.rb
|
137
|
+
- lib/periodoxical/helpers.rb
|
138
138
|
- lib/periodoxical/validation.rb
|
139
139
|
- lib/periodoxical/version.rb
|
140
140
|
- periodoxical.gemspec
|