periodoxical 1.1.0 → 2.2.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: 2b67da50d1bba17e1d25babaa937440ccad41bf152d1df8d3adb50ff8c9199b3
4
- data.tar.gz: 954c91d5da06a9d4955fdb35576b11f1e209a8ab152825c3f09657e891787a5d
3
+ metadata.gz: ace9209a6c531a382b264e87513dc6e5075499fc90f1eba313404368d96e58ba
4
+ data.tar.gz: e1771a96128f204df520f39bfcb54d3a294c130da07d0c9f971b98908fe985ce
5
5
  SHA512:
6
- metadata.gz: ab9f0eb8538ea18407171b2d9dc435935821370f3f3d229f59d718e3e11f3eba6b6f926129274f33c5100b22a70d937ba6f9693d714f52abaf0f2a7be4965d28
7
- data.tar.gz: 64503a74a1879ae8d0cda934ad511530ff6c22e5f1aeb9fe331f0dda99ccf8d7b81c735e2d10a9c6ce468010ea64674c1d8bc86a24fa8f18aa5382cfd29facdd
6
+ metadata.gz: aaaf84f0c0af53ad1df2f595298a8327fc67574b7a35c08a27a921f0719ef6eea0990a7ee28423755f3baa0abe78d31e4bad7bcd42f82d1c9ebe6607b0fe0574
7
+ data.tar.gz: 8eed0bfd9236bb43084c0427a50ac6ce6b793411d30adffd1d12b303ae57d0cf8d5dc0281b1c654aa15584a436066dea7f1a39a5283bdc7ef398df9dde56ec5c
data/Gemfile.lock CHANGED
@@ -1,9 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- periodoxical (1.1.0)
4
+ periodoxical (2.2.0)
5
5
  tzinfo (~> 2.0, >= 2.0.0)
6
- week_of_month (= 1.2.6)
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
@@ -41,7 +40,6 @@ GEM
41
40
  rspec-support (3.13.1)
42
41
  tzinfo (2.0.6)
43
42
  concurrent-ruby (~> 1.0)
44
- week_of_month (1.2.6)
45
43
 
46
44
  PLATFORMS
47
45
  arm64-darwin-22
data/README.md CHANGED
@@ -47,20 +47,20 @@ Periodoxical.generate(
47
47
  #=>
48
48
  [
49
49
  {
50
- start_time: #<DateTime: 2024-05-23T09:00:00-0700>,
51
- end_time: #<DateTime: 2024-05-23T10:30:00-0700>,
50
+ start: #<DateTime: 2024-05-23T09:00:00-0700>,
51
+ end: #<DateTime: 2024-05-23T10:30:00-0700>,
52
52
  },
53
53
  {
54
- start_time: #<DateTime: 2024-05-24T09:00:00-0700>,
55
- end_time: #<DateTime: 2024-05-24T10:30:00-0700>,
54
+ start: #<DateTime: 2024-05-24T09:00:00-0700>,
55
+ end: #<DateTime: 2024-05-24T10:30:00-0700>,
56
56
  },
57
57
  {
58
- start_time: #<DateTime: 2024-05-25T09:00:00-0700>,
59
- end_time: #<DateTime: 2024-05-25T10:30:00-0700>,
58
+ start: #<DateTime: 2024-05-25T09:00:00-0700>,
59
+ end: #<DateTime: 2024-05-25T10:30:00-0700>,
60
60
  },
61
61
  {
62
- start_time: #<DateTime: 2024-05-26T09:00:00-0700>,
63
- end_time: #<DateTime: 2024-05-26T10:30:00-0700>,
62
+ start: #<DateTime: 2024-05-26T09:00:00-0700>,
63
+ end: #<DateTime: 2024-05-26T10:30:00-0700>,
64
64
  }
65
65
  ]
66
66
  ```
@@ -209,7 +209,7 @@ Periodoxical.generate(
209
209
  )
210
210
  ```
211
211
 
212
- ### Specifying time blocks using rules for day-of-month and/or week-of-month and/or month.
212
+ ### Specifying time blocks using rules for month(s) and/or day-of-month.
213
213
 
214
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.
215
215
 
@@ -240,41 +240,6 @@ Periodoxical.generate(
240
240
  ]
241
241
  ```
242
242
 
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.
244
-
245
- ```
246
- Periodoxical.generate(
247
- time_zone: 'America/Los_Angeles',
248
- starting_from: '2024-04-01',
249
- limit: 4,
250
- weeks_of_month: [1 2],
251
- months: [4, 5, 6],
252
- days_of_week: %w(mon),
253
- time_blocks: [
254
- { start_time: '8:00AM', end_time: '9:00AM' },
255
- ],
256
- )
257
- #=>
258
- [
259
- {
260
- start_time: #<DateTime: 2024-04-01T08:00:00-0700>,
261
- end_time: #<DateTime: 2024-04-01T09:00:00-0700>,
262
- },
263
- {
264
- start_time: #<DateTime: 2024-04-08T08:00:00-0700>,
265
- end_time: #<DateTime: 2024-04-08T09:00:00-0700>,
266
- },
267
- {
268
- start_time: #<DateTime: 2024-05-06T08:00:00-0700>,
269
- end_time: #<DateTime: 2024-05-06T09:00:00-0700>,
270
- },
271
- {
272
- start_time: #<DateTime: 2024-06-03T08:00:00-0700>,
273
- end_time: #<DateTime: 2024-06-03T09:00:00-0700>,
274
- },
275
- ]
276
- ```
277
-
278
243
  ### Example 6 - Specify nth day-of-week in month (ie. first Monday of the Month, second Tuesday of the Month, last Friday of Month)
279
244
  As a Ruby dev, I want to generate timeblocks for **8AM - 9AM** on the **first and second Mondays** and **last Fridays** of every month starting in June 2024. I can do this with the `nth_day_of_week_in_month` param.
280
245
 
@@ -474,6 +439,50 @@ Periodoxical.generate(
474
439
  ]
475
440
  ```
476
441
 
442
+ ### Use the `duration` key, to automatically partition the provided `time_blocks` into smaller chunks to the given duration.
443
+
444
+ As a Ruby dev, I want to generate **30 minute** time blocks between **9:00AM - 1:00PM, and 2:00PM - 5:00PM**. Because it is too tedious to generate all 14 of these time blocks, I prefer to pass in the `duration` key and have `periodoxical` generate them for me.
445
+
446
+ N.B. If you provide a duration that conflicts with your time blocks, `periodoxical` will not return any time blocks. For example, if you specify **9:00AM - 10:00AM** but set your **duration** as 90 minutes, no time blocks are generated since we can't fit 90 minutes into an hour!
447
+
448
+
449
+ ```rb
450
+ Periodoxical.generate(
451
+ time_zone: 'America/Los_Angeles',
452
+ time_blocks: [
453
+ {
454
+ start_time: '9:00AM',
455
+ end_time: '1:00PM'
456
+ },
457
+ {
458
+ start_time: '2:00PM',
459
+ end_time: '5:00PM'
460
+ },
461
+ ],
462
+ duration: 30, #(minutes)
463
+ starting_from: '2024-05-23',
464
+ ending_at: '2024-05-26',
465
+ )
466
+ # => [
467
+ {
468
+ start: #<DateTime: 2024-05-23T09:00:00--0700>
469
+ end: #<DateTime: 2024-05-23T09:30:00--0700>
470
+ },
471
+ {
472
+ start: #<DateTime: 2024-05-23T09:30:00--0700>
473
+ end: #<DateTime: 2024-05-23T10:00:00--0700>
474
+ },
475
+ {
476
+ start: #<DateTime: 2024-05-23T10:00:00--0700>
477
+ end: #<DateTime: 2024-05-23T10:30:00--0700>
478
+ },
479
+ {
480
+ start: #<DateTime: 2024-05-23T10:30:00--0700>
481
+ end: #<DateTime: 2024-05-23T11:00:00--0700>
482
+ }
483
+ ]
484
+ ```
485
+
477
486
  ### Having Some Fun
478
487
 
479
488
  Generate all the Friday the 13ths ever since May 1980 (when the first Friday the 13th film was released).
@@ -1,3 +1,3 @@
1
1
  module Periodoxical
2
- VERSION = "1.1.0"
2
+ VERSION = "2.2.0"
3
3
  end
data/lib/periodoxical.rb CHANGED
@@ -4,7 +4,6 @@ require "periodoxical/helpers"
4
4
  require "date"
5
5
  require "time"
6
6
  require "tzinfo"
7
- require "week_of_month"
8
7
 
9
8
  module Periodoxical
10
9
  class << self
@@ -66,6 +65,12 @@ module Periodoxical
66
65
  # tue: { start_time: '11:30PM', end_time: '12:00AM' },
67
66
  # fri: { start_time: '7:00PM', end_time: '9:00PM' },
68
67
  # }
68
+ # @param [Integer] duration
69
+ # Splits the time_blocks into this duration (in minutes). For example, if time_block is 9:00AM - 10:00AM,
70
+ # and duration is 20 minutes. It creates 3 timeblocks of:
71
+ # - 9:00AM - 9:20AM
72
+ # - 9:20AM - 9:40AM
73
+ # - 9:40AM - 10:00AM
69
74
  def initialize(
70
75
  starting_from:,
71
76
  ending_at: nil,
@@ -78,7 +83,7 @@ module Periodoxical
78
83
  days_of_week: nil,
79
84
  nth_day_of_week_in_month: nil,
80
85
  days_of_month: nil,
81
- weeks_of_month: nil,
86
+ duration: nil,
82
87
  months: nil
83
88
  )
84
89
 
@@ -90,13 +95,20 @@ module Periodoxical
90
95
  end
91
96
  @nth_day_of_week_in_month = deep_symbolize_keys(nth_day_of_week_in_month)
92
97
  @days_of_month = days_of_month
93
- @weeks_of_month = weeks_of_month
94
98
  @months = months
95
99
  @time_blocks = deep_symbolize_keys(time_blocks)
96
100
  @day_of_week_time_blocks = deep_symbolize_keys(day_of_week_time_blocks)
97
101
  @starting_from = date_object_from(starting_from)
98
102
  @ending_at = date_object_from(ending_at)
99
103
  @limit = limit
104
+
105
+ if duration
106
+ unless duration.is_a?(Integer)
107
+ raise "duration must be an integer"
108
+ else
109
+ @duration = duration
110
+ end
111
+ end
100
112
  @exclusion_dates = if exclusion_dates && !exclusion_dates.empty?
101
113
  exclusion_dates.map { |ed| Date.parse(ed) }
102
114
  end
@@ -201,19 +213,31 @@ module Periodoxical
201
213
  return if overlaps_with_an_excluded_time?(time_block)
202
214
  return if before_starting_from_or_after_ending_at?(time_block)
203
215
 
204
- @output << {
205
- start: time_str_to_object(@current_date, time_block[:start_time]),
206
- end: time_str_to_object(@current_date, time_block[:end_time])
207
- }
216
+ strtm = time_str_to_object(@current_date, time_block[:start_time])
217
+ endtm = time_str_to_object(@current_date, time_block[:end_time])
208
218
 
209
- # increment count, if `limit` is used to stop generating
210
- @current_count = @current_count + 1
211
- if @limit && @current_count == @limit
212
- @keep_generating = false
213
- throw :done
219
+ if @duration
220
+ split_by_duration_and_append(strtm, endtm)
221
+ else
222
+ @output << {
223
+ start: strtm,
224
+ end: endtm
225
+ }
226
+ increment_and_check_limit
214
227
  end
215
228
  end
216
229
 
230
+ # increment count, if `limit` is used to stop generating
231
+ def increment_and_check_limit
232
+ return unless @limit
233
+
234
+ @current_count += 1
235
+ return if @current_count < @limit
236
+
237
+ @keep_generating = false
238
+ throw :done
239
+ end
240
+
217
241
  def advance_current_date_and_check_if_reached_end_date
218
242
  @current_date = @current_date + 1
219
243
 
@@ -240,11 +264,6 @@ module Periodoxical
240
264
  return false if @exclusion_dates.include?(@current_date)
241
265
  end
242
266
 
243
- # If weeks_of_months are specified but not satisified, return false
244
- if @weeks_of_month
245
- return false unless @weeks_of_month.include?(@current_date.week_of_month)
246
- end
247
-
248
267
  # If months are specified, but current_date does not satisfy months,
249
268
  # return false
250
269
  if @months
@@ -409,5 +428,20 @@ module Periodoxical
409
428
 
410
429
  false
411
430
  end
431
+
432
+ def split_by_duration_and_append(strtm, endtm)
433
+ delta = Rational(@duration, 24 * 60)
434
+ si = strtm
435
+ ei = strtm + delta
436
+ while ei <= endtm
437
+ @output << {
438
+ start: si,
439
+ end: ei
440
+ }
441
+ si += delta
442
+ ei += delta
443
+ increment_and_check_limit
444
+ end
445
+ end
412
446
  end
413
447
  end
data/periodoxical.gemspec CHANGED
@@ -35,7 +35,6 @@ Gem::Specification.new do |spec|
35
35
  spec.require_paths = ["lib"]
36
36
 
37
37
  spec.add_dependency 'tzinfo', '~> 2.0', '>= 2.0.0'
38
- spec.add_dependency 'week_of_month', '1.2.6'
39
38
 
40
39
  spec.add_development_dependency "bundler", "~> 2.4"
41
40
  spec.add_development_dependency "rake", "~> 12.3.3"
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: 1.1.0
4
+ version: 2.2.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-12 00:00:00.000000000 Z
11
+ date: 2024-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tzinfo
@@ -30,20 +30,6 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 2.0.0
33
- - !ruby/object:Gem::Dependency
34
- name: week_of_month
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - '='
38
- - !ruby/object:Gem::Version
39
- version: 1.2.6
40
- type: :runtime
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - '='
45
- - !ruby/object:Gem::Version
46
- version: 1.2.6
47
33
  - !ruby/object:Gem::Dependency
48
34
  name: bundler
49
35
  requirement: !ruby/object:Gem::Requirement