periodoxical 0.8.3 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78125f7c8e33a8588c933d7b0438daa5d0913394fe9c141e752dd73fc1968d88
4
- data.tar.gz: 60acbba0684d36991ac7bffcb21dc8a97e27bfb313d1ab9641668463e73c718c
3
+ metadata.gz: 1028e4261c9759e49e7446a1ff506fcb4d3b789b4bdd1ef40dbec0bd8df18ae8
4
+ data.tar.gz: c7dece06fabe86ede77b98203bea7716d0d1e039393f1e6e693c8a232615ef01
5
5
  SHA512:
6
- metadata.gz: df7a8cc7abe1139af195aebe455feb7c66b75e27e3a8d43e4c862ec362111756a461b7293efe3c3fdcca50eb1f70d5fdb5de04e740014a4fc33fe3f324e8d6ec
7
- data.tar.gz: '070876a087c2712b12f497054966f9cd98ac3d0e3eab1e4337e165e2ea42cef5ea4dd5b43b714393d92d14ddab2119b426128cf9d85f5de845b9e32959f72b1d'
6
+ metadata.gz: '08dc98ece1a24ed33564c60f32c31fcf76defddbab51fbf2c0c3df04b296759767fc1dde8a4ed744a24b700fe812ce97bcdc06c052c382e61872c55426116258'
7
+ data.tar.gz: c8edb8ea410b88c5888edda103752c27c149e4e06421b74fb7c4a29ed0f09ae32726536ed495702156b8e6e054da0a5140e1a3487bbbac4468abb94ed7cfb79f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- periodoxical (0.8.3)
4
+ periodoxical (0.9.3)
5
5
  tzinfo (~> 2.0, >= 2.0.0)
6
6
  week_of_month (= 1.2.6)
7
7
 
data/README.md CHANGED
@@ -291,7 +291,7 @@ Periodoxical.generate(
291
291
  ]
292
292
  ```
293
293
 
294
- ### Example 7 - Exclude time blocks using the `exclusion_dates` parameter
294
+ ### Example 7 - Exclude time blocks using the `exclusion_dates` and `exclusion_times` parameters
295
295
  As a Ruby dev, I want to generate timeblocks for **8AM - 9AM** on **Mondays**, except for the **Monday of June 10, 2024**.
296
296
 
297
297
  ```rb
@@ -328,10 +328,68 @@ Periodoxical.generate(
328
328
  ]
329
329
  ```
330
330
 
331
+ As a Ruby dev, I want to generate timeblocks for **8AM - 9AM**, and **10AM - 11AM** on **Mondays**, except for those that conflict (meaning overlap) with the time block of **10:30AM - 11:30AM** on the **Monday of June 10, 2024**. I can skip the conflicting time blocks by using the `exclusion_times` parameter.
332
+
333
+ ```rb
334
+ Periodoxical.generate(
335
+ time_zone: 'America/Los_Angeles',
336
+ start_date: '2024-06-3',
337
+ limit: 4,
338
+ days_of_week: %(mon),
339
+ time_blocks: [
340
+ { start_time: '8:00AM', end_time: '9:00AM' },
341
+ { start_time: '10:00AM', end_time: '11:00AM' },
342
+ ],
343
+ exclusion_times: [
344
+ {
345
+ start: '2024-06-10T10:30:00-07:00',
346
+ end: '2024-06-10T11:30:00-07:00',
347
+ }
348
+ ],
349
+ )
350
+ # =>
351
+ [
352
+ {
353
+ start: #<DateTime 2024-06-03T08:00:00-0700>,
354
+ end: #<DateTime 2024-06-03T09:00:00-0700>,
355
+ },
356
+ {
357
+ start: #<DateTime 2024-06-03T10:00:00-0700>,
358
+ end: #<DateTime 2024-06-03T11:00:00-0700>,
359
+ },
360
+ {
361
+ start: #<DateTime 2024-06-10T08:00:00-0700>,
362
+ end: #<DateTime 2024-06-10T09:00:00-0700>,
363
+ },
364
+ # The June 10 10AM - 11AM was skipped because it overlapped with the June 10 10:30AM - 11:30AM exclusion time.
365
+ {
366
+ start: #<DateTime 2024-06-17T08:00:00-0700>,
367
+ end: #<DateTime 2024-06-17T09:00:00-0700>,
368
+ },
369
+ {
370
+ start: #<DateTime 2024-06-17T10:00:00-0700>,
371
+ end: #<DateTime 2024-06-17T11:00:00-0700>,
372
+ },
373
+ {
374
+ start: #<DateTime 2024-06-24T08:00:00-0700>,
375
+ end: #<DateTime 2024-06-24T09:00:00-0700>,
376
+ },
377
+ ]
378
+ ```
379
+
331
380
  ### Example 8 - Every-other-nth day-of-week rules (ie. every other Tuesday, every 3rd Wednesday, every 10th Friday)
332
381
 
333
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, but also using the `every` and `every_other_nth` keys to specify the every-other-nth-rules.
334
383
 
384
+ This can be visualized as:
385
+
386
+ <div align="center">
387
+ <img width="600" alt="alt_google_cal_image" src="https://github.com/StevenJL/periodoxical/assets/2191808/d663da17-a94a-4715-886a-8223b129dd60">
388
+ <p><i>(image courtesy of calendar.google.com)</i></p>
389
+ </div>
390
+
391
+ <br>
392
+
335
393
  ```rb
336
394
  Periodoxical.generate(
337
395
  time_zone: 'America/Los_Angeles',
@@ -464,7 +522,8 @@ Periodoxical.generate(
464
522
  {
465
523
  start: #<DateTime: 2028-11-23T17:00:00-0800>,
466
524
  end: #<DateTime: 2028-11-23T18:00:00-0800>,
467
- }
525
+ },
526
+ ...
468
527
  ]
469
528
  ```
470
529
 
@@ -99,6 +99,14 @@ module Periodoxical
99
99
  unless( @limit || @end_date)
100
100
  raise "Either `limit` or `end_date` must be provided"
101
101
  end
102
+
103
+ if @exclusion_times
104
+ @exclusion_times.each do |tb|
105
+ unless tb[:start] < tb[:end]
106
+ raise "Exclusion times must have `start` before `end`. #{tb[:start]} not before #{tb[:end]}"
107
+ end
108
+ end
109
+ end
102
110
  end
103
111
  end
104
112
  end
@@ -1,3 +1,3 @@
1
1
  module Periodoxical
2
- VERSION = "0.8.3"
2
+ VERSION = "0.9.3"
3
3
  end
data/lib/periodoxical.rb CHANGED
@@ -44,6 +44,19 @@ module Periodoxical
44
44
  # @param [Aray<String>] exclusion_dates
45
45
  # Dates to be excluded when generating the time blocks
46
46
  # Ex: ['2024-06-10', '2024-06-14']
47
+ # @param [Aray<Hash>] exclusion_times
48
+ # Timeblocks to be excluded when generating the time blocks if there is conflict (ie. overlap)
49
+ # Ex: [
50
+ # {
51
+ # start: '2024-06-10T10:30:00-07:00',
52
+ # end: '2024-06-10T11:30:00-07:00'
53
+ # },
54
+ # {
55
+ # start: '2024-06-10T14:30:00-07:00',
56
+ # end: '2024-06-10T15:30:00-07:00'
57
+ # },
58
+ # ]
59
+ #
47
60
  # @param [Hash<Array<Hash>>] day_of_week_time_blocks
48
61
  # To be used when hours are different between days of the week
49
62
  # Ex: {
@@ -58,6 +71,7 @@ module Periodoxical
58
71
  day_of_week_time_blocks: nil,
59
72
  limit: nil,
60
73
  exclusion_dates: nil,
74
+ exclusion_times: nil,
61
75
  time_zone: 'Etc/UTC',
62
76
  days_of_week: nil,
63
77
  nth_day_of_week_in_month: nil,
@@ -84,6 +98,11 @@ module Periodoxical
84
98
  @exclusion_dates = if exclusion_dates && !exclusion_dates.empty?
85
99
  exclusion_dates.map { |ed| Date.parse(ed) }
86
100
  end
101
+ @exclusion_times = if exclusion_times
102
+ exclusion_times.map do |et|
103
+ { start: DateTime.parse(et[:start]), end: DateTime.parse(et[:end]) }
104
+ end
105
+ end
87
106
  validate!
88
107
  end
89
108
 
@@ -184,6 +203,9 @@ module Periodoxical
184
203
  # }
185
204
  # Generates time block but also checks if we should stop generating
186
205
  def append_to_output_and_check_limit(time_block)
206
+ # Check if this particular time is conflicts with any times from `exclusion_times`.
207
+ return if overlaps_with_an_excluded_time?(time_block)
208
+
187
209
  @output << {
188
210
  start: time_str_to_object(@current_date, time_block[:start_time]),
189
211
  end: time_str_to_object(@current_date, time_block[:end_time])
@@ -350,5 +372,43 @@ module Periodoxical
350
372
  def update_days_of_week_running_tally!
351
373
  @days_of_week_running_tally[@current_day_of_week.to_sym] = @days_of_week_running_tally[@current_day_of_week.to_sym] + 1
352
374
  end
375
+
376
+ # @return [Boolean]
377
+ # Whether or not the given `time_block` in the @current_date and
378
+ # @time_zone overlaps with the times in `exclusion_times`.
379
+ def overlaps_with_an_excluded_time?(time_block)
380
+ return false unless @exclusion_times
381
+
382
+ @exclusion_times.each do |exclusion_timeblock|
383
+ return true if overlap?(
384
+ exclusion_timeblock,
385
+ {
386
+ start: time_str_to_object(@current_date, time_block[:start_time]),
387
+ end: time_str_to_object(@current_date, time_block[:end_time]),
388
+ }
389
+ )
390
+ end
391
+
392
+ false
393
+ 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
353
413
  end
354
414
  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: 0.8.3
4
+ version: 0.9.3
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-03 00:00:00.000000000 Z
11
+ date: 2024-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tzinfo