active_period 7.1.2 → 7.1.4

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: e197dc4558fd215fc7090f5a14ad074e769457abfa7665b4b2393e5ba2a23d52
4
- data.tar.gz: 54c3de6172706d0f08e2885b6401b3f1c964526498193a63c13af4fbfab6eb99
3
+ metadata.gz: 29fd67cfde1ddca02696bf27400b13b0f1887d6bd64bf4e0749d3b2395f87730
4
+ data.tar.gz: fdba3eaf0997e0a4ad05948269b5a09f3ec18980caa2394d3fc41fb98aee7e99
5
5
  SHA512:
6
- metadata.gz: a228d61ffcb56d1f9206127e22775e2a3ec109822ce0b8242e6e778d8edb08531dd9b2834cc7def80cb42ec7cf148b2abc8776059228c5fb7b7d9cb90ec68562
7
- data.tar.gz: 25550cbd55706774bfd34e68690be5d39b2e01b6681f33b3134d3c7169949c9e1d017ac40cadd24d041eef2c85d3ce6c05dbb8fe76761d6a2fabebe501230e24
6
+ metadata.gz: 4107662e9c026dd3d2390534ab22800bf352b51f72747f2b018443d95a7d12982f5e2f6638ea1e78630c9a889551091af2bbf4d41e9504209f50fbd441b6872d
7
+ data.tar.gz: 5f06ee831b6199212561ef01352c7f02b6ba455f96381bda6ec3fe2b03af627a4223f924713e811848ad34098581eef876d863f09a9c65a8c80c6e45851730bc
data/README.md CHANGED
@@ -134,7 +134,7 @@ Period.week('10/02/2000') + 67.day
134
134
  **StandardPeriod** also respond to `.next` and `.prev`
135
135
  ```ruby
136
136
  Period.month('01/01/2000').next.next.next
137
- # Return the month of April 2020
137
+ # Return the month of April 2000
138
138
  ```
139
139
 
140
140
  You can quickly access convenient periods of time with `.(last|this|next)_(day|week|month|quarter|year)` and `.yesterday` `.today` `.tomorrow`
@@ -242,6 +242,27 @@ Period['01/01/2021'...'09/01/2021'] | Period['10/01/2021'..'20/01/2021']
242
242
  => nil
243
243
  ```
244
244
 
245
+ ## Period clamping with `clamp_on`
246
+
247
+ You can use `clamp_on` to clamp a `Period`, a date or a range of dates, within a `Period`.
248
+ If you user `clamp_on` on a range of dates, the return value will also be a range of dates, this is to preserve hours/minutes/second precision
249
+ :warning: The classic `clamp` apply the param to the caller. It's `42.clamp(1..10) -> 10` **and this don't exist** `(1..10).clamp(42)`
250
+ `clamp_on` reverse this logic, and apply the caller to the params.
251
+ This choice has been made to avoid a monkey patch on `clamp`
252
+ :warning: If you `clamp_on` a `range` that don't overlap with the caller, the return value is `nil`
253
+
254
+ ```ruby
255
+ Period.today.clamp_on(Period.this_week)
256
+ => Period.today
257
+
258
+ Period.today.clamp_on(Period.last_week)
259
+ => nil
260
+
261
+ Period.today.clamp_on(3.from_now)
262
+ => # 3.from_now or today ending's time
263
+
264
+ ```
265
+
245
266
  ## Boundless Period
246
267
 
247
268
  Boundless period are fully supported and work as you expect them to do
@@ -10,21 +10,75 @@ module ActivePeriod
10
10
  include_period?(ActivePeriod::Day.new(other))
11
11
  when ActivePeriod::Period
12
12
  include_period?(other)
13
+ when Range
14
+ include?(other.first) && include?(other.last)
13
15
  else
14
16
  raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable])
15
17
  end
16
18
  end
17
19
 
18
20
  def <=>(other)
19
- raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable]) unless other.is_a?(ActiveSupport::Duration)
20
-
21
- if other.is_a?(ActiveSupport::Duration) || other.is_a?(Numeric)
21
+ case other
22
+ when DateTime, Time, ActiveSupport::TimeWithZone
23
+ if first < other && last < other
24
+ -1
25
+ elsif first > other && last > other
26
+ 1
27
+ else
28
+ 0
29
+ end
30
+ when ActiveSupport::Duration, Numeric
22
31
  to_i <=> other.to_i
23
- elsif self.class != other.class
24
- raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable])
25
32
  else
26
- (self.begin <=> other)
33
+ if self.class != other.class
34
+ raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable])
35
+ else
36
+ (self.begin <=> other)
37
+ end
38
+ end
39
+ end
40
+
41
+ # Reverse clamp where the `other` is clamped by `self`
42
+ # If other is an ActivePeriod::Period then `clamp_on` will return an ActivePeriod::Period
43
+ # If other is not an ActivePeriod::Period then `clamp_on` will return a range
44
+ def clamp_on(other)
45
+ case other
46
+ when DateTime, Time, ActiveSupport::TimeWithZone
47
+ case self <=> other
48
+ when -1
49
+ last
50
+ when 0
51
+ other
52
+ when 1
53
+ first
54
+ end
55
+ when ActivePeriod::Period
56
+ self & other
57
+ when Range
58
+ if (other.first > last && other.last > last) ||
59
+ (other.first < first && other.last < first)
60
+ return nil
61
+ end
62
+
63
+ clamped = clamp_on(other.first) .. clamp_on(other.last)
64
+
65
+ if other.is_a? ActivePeriod::Period
66
+ clamped.to_period
67
+ else
68
+ clamped
69
+ end
70
+ else
71
+ raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable])
27
72
  end
73
+ #
74
+ # new_first = other.first < first ? first : other.first
75
+ # new_last = other.last > last ? last : other.last
76
+ #
77
+ # if other.is_a? ActivePeriod::Period
78
+ # Period.new(new_first .. new_last)
79
+ # else
80
+ # new_first .. new_last
81
+ # end
28
82
  end
29
83
 
30
84
  private
@@ -32,8 +86,6 @@ module ActivePeriod
32
86
  def include_period?(other)
33
87
  if self.class.in?([Month, Quarter, Year]) && other.is_a?(Week)
34
88
  self.include_time?(other.include_date)
35
- # elsif (other.class.in?([Month, Quarter, Year]) && self.is_a?(Week)
36
- # other.include_time?(self.include_date)
37
89
  else
38
90
  self.include_time?(other.begin) && self.include_time?(other.calculated_end)
39
91
  end
@@ -107,11 +107,11 @@ class ActivePeriod::Period < Range
107
107
  # self 5-----8
108
108
  # other 1-----------10
109
109
  elsif other.include?(self)
110
- other
110
+ self
111
111
  # self 1-----------10
112
112
  # other 5-----8
113
113
  elsif self.include?(other)
114
- self
114
+ other
115
115
  else
116
116
  nil
117
117
  end
@@ -1,5 +1,5 @@
1
1
  module ActivePeriod
2
2
 
3
- VERSION = '7.1.2'.freeze
3
+ VERSION = '7.1.4'.freeze
4
4
 
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_period
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.2
4
+ version: 7.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - billau_l
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-16 00:00:00.000000000 Z
11
+ date: 2024-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
161
  requirements: []
162
- rubygems_version: 3.3.22
162
+ rubygems_version: 3.5.9
163
163
  signing_key:
164
164
  specification_version: 4
165
165
  summary: Manage time ranges without brain damage.