periodoxical 1.0.0 → 1.1.0

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: 3836bd7c49ec987409e70592d93cb8c021a009ce3587e48a6419c12121af3b1d
4
- data.tar.gz: 510bb79570482c8019e911c8900ec15ee5016b59c1d51677d38d53f7c632523f
3
+ metadata.gz: 2b67da50d1bba17e1d25babaa937440ccad41bf152d1df8d3adb50ff8c9199b3
4
+ data.tar.gz: 954c91d5da06a9d4955fdb35576b11f1e209a8ab152825c3f09657e891787a5d
5
5
  SHA512:
6
- metadata.gz: 0afbe7ebba86480f7d04766a087020734135bb0075245fbe6ba03f75590eb0c74710991b14e5fad653779ba7d6a74811d11adaeb7cfa28ec194dc9eea05adfb9
7
- data.tar.gz: ddc843c9de7c3ae536f939f0c7bfc6c6d5ce2a37d4bde07d2941bd2ef7f7e0a41328d347fe1e9d8d1c1e1ba9bf916648424bd18795ad8642531d37529841d913
6
+ metadata.gz: ab9f0eb8538ea18407171b2d9dc435935821370f3f3d229f59d718e3e11f3eba6b6f926129274f33c5100b22a70d937ba6f9693d714f52abaf0f2a7be4965d28
7
+ data.tar.gz: 64503a74a1879ae8d0cda934ad511530ff6c22e5f1aeb9fe331f0dda99ccf8d7b81c735e2d10a9c6ce468010ea64674c1d8bc86a24fa8f18aa5382cfd29facdd
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- periodoxical (1.0.0)
4
+ periodoxical (1.1.0)
5
5
  tzinfo (~> 2.0, >= 2.0.0)
6
6
  week_of_month (= 1.2.6)
7
7
 
data/README.md CHANGED
@@ -29,7 +29,7 @@ Or install it yourself as:
29
29
 
30
30
  ## Usage
31
31
 
32
- ### Example 1
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
@@ -65,7 +65,7 @@ Periodoxical.generate(
65
65
  ]
66
66
  ```
67
67
 
68
- The `starting_from` and `ending_at` params can also accept datetimes in ISO 8601 format for more precision. This example generate all the datetime blocks of **9:00AM - 10:30AM** but starting from **May 23, 2024 at 9:30AM**.
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
69
 
70
70
  ```rb
71
71
  Periodoxical.generate(
@@ -80,7 +80,8 @@ Periodoxical.generate(
80
80
  ending_at: DateTime.parse('2024-05-26T17:00:00-07:00'), # or an instance of DateTime
81
81
  )
82
82
  #=> [
83
- # 2024-05-23 was skipped because the 9AM timeslot was before the `starting_from` of '2024-05-23T09:30:00-07:00'
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'
84
85
  {
85
86
  start_time: #<DateTime: 2024-05-24T09:00:00-0700>,
86
87
  end_time: #<DateTime: 2024-05-24T10:30:00-0700>,
@@ -89,8 +90,8 @@ Periodoxical.generate(
89
90
  ]
90
91
  ```
91
92
 
92
- ### Example 2 - specify days of the week
93
- 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. This can be represented visually as:
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:
94
95
 
95
96
  <div align="center">
96
97
  <img width="558" alt="calendar_image_1" src="https://github.com/StevenJL/periodoxical/assets/2191808/e92fc6ff-03fd-44ed-a955-d3a0dd0f5d0a">
@@ -139,9 +140,9 @@ Periodoxical.generate(
139
140
  ]
140
141
  ```
141
142
 
142
- ### Example 3 - using the `limit` key.
143
+ ### Example using the `limit` parameter.
143
144
 
144
- 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** using the `limit` key.
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`.
145
146
 
146
147
  ```rb
147
148
  Periodoxical.generate(
@@ -177,9 +178,9 @@ Periodoxical.generate(
177
178
  ]
178
179
  ```
179
180
 
180
- ### Example 4 - when time blocks vary between days
181
+ ### Time blocks that vary between days-of-the-week
181
182
 
182
- 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.
183
184
 
184
185
  <div align="center">
185
186
  <img width="628" alt="calendar_image_2" src="https://github.com/StevenJL/periodoxical/assets/2191808/26d14824-08ff-481a-97e2-9b6b11beea29">
@@ -208,9 +209,9 @@ Periodoxical.generate(
208
209
  )
209
210
  ```
210
211
 
211
- ### Example 5 - when specifying time blocks using day-of-month and/or week-of-month and/or month.
212
+ ### Specifying time blocks using rules for day-of-month and/or week-of-month and/or month.
212
213
 
213
- 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.
214
215
 
215
216
  ```rb
216
217
  Periodoxical.generate(
@@ -239,7 +240,7 @@ Periodoxical.generate(
239
240
  ]
240
241
  ```
241
242
 
242
- 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.
243
244
 
244
245
  ```
245
246
  Periodoxical.generate(
@@ -284,7 +285,7 @@ Periodoxical.generate(
284
285
  limit: 5,
285
286
  nth_day_of_week_in_month: {
286
287
  mon: [1, 2], # valid values: -1,1,2,3,4,5
287
- fri: [-1], # Use -1 to specify "last" of the month.
288
+ fri: [-1], # Use -1 to specify the last Friday of the month.
288
289
  },
289
290
  time_blocks: [
290
291
  { start_time: '8:00AM', end_time: '9:00AM' },
@@ -316,7 +317,7 @@ Periodoxical.generate(
316
317
  ```
317
318
 
318
319
  ### Example 7 - Exclude time blocks using the `exclusion_dates` and `exclusion_times` parameters
319
- 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.
320
321
 
321
322
  ```rb
322
323
  Periodoxical.generate(
@@ -403,7 +404,7 @@ Periodoxical.generate(
403
404
 
404
405
  ### Example 8 - Every-other-nth day-of-week rules (ie. every other Tuesday, every 3rd Wednesday, every 10th Friday)
405
406
 
406
- 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.
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.
407
408
 
408
409
  This can be visualized as:
409
410
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Periodoxical
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
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,6 +15,7 @@ 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)
@@ -82,16 +84,16 @@ 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
+ @time_blocks = deep_symbolize_keys(time_blocks)
96
+ @day_of_week_time_blocks = deep_symbolize_keys(day_of_week_time_blocks)
95
97
  @starting_from = date_object_from(starting_from)
96
98
  @ending_at = date_object_from(ending_at)
97
99
  @limit = limit
@@ -99,7 +101,7 @@ module Periodoxical
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
@@ -419,44 +409,5 @@ module Periodoxical
419
409
 
420
410
  false
421
411
  end
422
-
423
- # @param [Hash] time_block_1, time_block_2
424
- # Ex: {
425
- # start: #<DateTime>,
426
- # end: #<DateTime>,
427
- # }
428
- def overlap?(time_block_1, time_block_2)
429
- tb_1_start = time_block_1[:start]
430
- tb_1_end = time_block_1[:end]
431
- tb_2_start = time_block_2[:start]
432
- tb_2_end = time_block_2[:end]
433
-
434
- # Basicall overlap is when one starts before the other has ended
435
- return true if tb_1_end > tb_2_start && tb_1_end < tb_2_end
436
- # By symmetry
437
- return true if tb_2_end > tb_1_start && tb_2_end < tb_1_end
438
-
439
- false
440
- end
441
-
442
- def date_object_from(dt)
443
- return unless dt
444
- return dt if dt.is_a?(Date) || dt.is_a?(DateTime)
445
-
446
- if dt.is_a?(String)
447
- return Date.parse(dt) if /\A\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01])\z/ =~ dt
448
-
449
- 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
450
- # convert to DateTime object
451
- dt = DateTime.parse(dt)
452
- # convert to given time_zone
453
- return dt.to_time.localtime(@time_zone.utc_offset).to_datetime
454
- end
455
-
456
- raise "Could not parse date/datetime string #{dt}. Please README for examples."
457
- else
458
- raise "Invalid argument: #{dt}"
459
- end
460
- end
461
412
  end
462
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: 1.0.0
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-04 00:00:00.000000000 Z
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
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.10
7
- before_install: gem install bundler -v 1.17.2