active_period 7.0.0 → 7.1.1

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: f52b743020890ffb49224e7b0dd129901233a4d1cdd639d412a88872c66b97d0
4
- data.tar.gz: 0eb862ce0e5aa128ce81fd93e28dd887c64f0f70ec000c9dd7988e281288be39
3
+ metadata.gz: bfac8dacceda500a1902d5294bc1085a70471c3b8d9abf0c0bf039c5e6a5bdba
4
+ data.tar.gz: a016fb107d49981e8eb89caf285012277c30b21a46928c460bc7ad9c5f5e80ec
5
5
  SHA512:
6
- metadata.gz: bce08f3f5b1b10347469b43a832d525bec3a470b09e798539f84bc80b4aca768898734565acadf5600670fcbb9e7a3e6a427b9c4fcbccc402e5b5c0109a05a62
7
- data.tar.gz: 5e3dcdb1f0328b1baf28ad298e951d893c9e9102faa703890ba47f3c6983947c666dad61e810364ff2bb2b4648542be859d7bfee5f081472da4bb7d3293da07a
6
+ metadata.gz: f164a66d035b1f4488a5851fdc9205c2a1836c35c145d63f551fe52038749d86e0c11d6d57eb266aa0c980516e28211a004b0fbe7019335a9ffd29ee0687f22d
7
+ data.tar.gz: ec860e7598cf0263def6444a9a119efb04aa3631d9f5c1106a7ca690adb9a0c7d1e413ccfd567cb4e9be61de4613c9a77e54dbe06979dc434fd342e92cf50fd4
data/Gemfile.lock CHANGED
@@ -1,20 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_period (7.0.0)
5
- activesupport (~> 7, >= 5)
4
+ active_period (7.1.0)
5
+ activesupport (>= 5, <= 7)
6
6
  i18n (~> 1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (7.0.2.2)
11
+ activesupport (6.1.4)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 1.6, < 2)
14
14
  minitest (>= 5.1)
15
15
  tzinfo (~> 2.0)
16
+ zeitwerk (~> 2.3)
16
17
  builder (3.2.4)
17
- concurrent-ruby (1.1.9)
18
+ concurrent-ruby (1.1.10)
18
19
  cucumber (7.0.0)
19
20
  builder (~> 3.2, >= 3.2.4)
20
21
  cucumber-core (~> 10.0, >= 10.0.1)
@@ -48,18 +49,19 @@ GEM
48
49
  cucumber-messages (~> 17.0, >= 17.0.1)
49
50
  diff-lcs (1.4.4)
50
51
  ffi (1.15.3)
51
- i18n (1.10.0)
52
+ i18n (1.12.0)
52
53
  concurrent-ruby (~> 1.0)
53
54
  mime-types (3.3.1)
54
55
  mime-types-data (~> 3.2015)
55
56
  mime-types-data (3.2021.0704)
56
- minitest (5.15.0)
57
+ minitest (5.16.3)
57
58
  multi_test (0.1.2)
58
59
  rake (10.5.0)
59
60
  sys-uname (1.2.2)
60
61
  ffi (~> 1.1)
61
- tzinfo (2.0.4)
62
+ tzinfo (2.0.5)
62
63
  concurrent-ruby (~> 1.0)
64
+ zeitwerk (2.6.0)
63
65
 
64
66
  PLATFORMS
65
67
  ruby
data/README.md CHANGED
@@ -82,6 +82,9 @@ Period.new(params[:start_date]..params[:end_date])
82
82
 
83
83
  # or from a range
84
84
  ('01/01/2000'...'01/02/2000').to_period
85
+
86
+ # you can also use [] if .new is too long for you
87
+ Period['01/01/2000'...'01/02/2000']
85
88
  ```
86
89
 
87
90
  **Note** : `to_period` will always return a **FreePeriod**
@@ -204,6 +207,41 @@ These methods return a **StandardPeriod** who include the current period
204
207
  Period.this_year.months.second.weeks.last.days.third
205
208
  ```
206
209
 
210
+ ## Period Combination with `&` and `|`
211
+
212
+ You can use `&` to combine overlapping periods
213
+ And `|` to combine overlapping and tail to head periods
214
+ If the given periods cannot combine, then `nil` will be return
215
+ The period we take the ending date from, determine if the ending date is included or excluded
216
+
217
+ #### Example for `&`
218
+ ```ruby
219
+ # Overlapping periods
220
+ (Period['01/01/2021'..'20/01/2021'] & Period['10/01/2021'...'30/01/2021']).to_s
221
+ => "From the 10 January 2021 to the 20 January 2021 included"
222
+
223
+ # Theses period cannot combine
224
+ Period.this_month & Period.next_month
225
+ => nil
226
+ ```
227
+
228
+ #### Example for `|`
229
+ ```ruby
230
+ # Overlapping periods
231
+ (Period['01/01/2021'..'20/01/2021'] | Period['10/01/2021'...'30/01/2021']).to_s
232
+ => "From the 01 January 2021 to the 30 January 2021 excluded"
233
+
234
+ # Example with tail to head
235
+ (Period.this_month | Period.next_month).to_s
236
+ => "From the 01 September 2022 to the 31 October 2022 included"
237
+ (Period['01/01/2021'..'09/01/2021'] | Period['10/01/2021'..'20/01/2021']).to_s
238
+ => "From the 01 January 2021 to the 20 January 2021 included"
239
+
240
+ # Theses period cannot combine
241
+ Period['01/01/2021'...'09/01/2021'] | Period['10/01/2021'..'20/01/2021']
242
+ => nil
243
+ ```
244
+
207
245
  ## Boundless Period
208
246
 
209
247
  Boundless period are fully supported and work as you expect them to do
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
38
38
 
39
39
  spec.required_ruby_version = '>= 2.7'
40
40
 
41
- spec.add_runtime_dependency 'activesupport', '>= 5', '~> 7'
41
+ spec.add_runtime_dependency 'activesupport', '>= 5', '< 8'
42
42
  spec.add_runtime_dependency 'i18n', '~> 1'
43
43
 
44
44
  spec.add_development_dependency 'bundler', '~> 2.0'
@@ -5,7 +5,7 @@ fr:
5
5
  comparable:
6
6
  incomparable_error: Les arguments ne sont pas comparables
7
7
  collection:
8
- param_period_must_be_a_period: Le paramètre doit hériter de la class Period
8
+ param_period_must_be_a_period: Le paramètre doit hériter de la class Period
9
9
  period:
10
10
  base_class_is_abstract: Period est une class abstraite qui ne doit pas être utiliser directement
11
11
  begin_date_is_invalid: Date de début invalide
@@ -16,12 +16,14 @@ module ActivePeriod
16
16
  end
17
17
 
18
18
  def <=>(other)
19
+ raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable]) unless other.is_a?(ActiveSupport::Duration)
20
+
19
21
  if other.is_a?(ActiveSupport::Duration) || other.is_a?(Numeric)
20
22
  to_i <=> other.to_i
21
23
  elsif self.class != other.class
22
24
  raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable])
23
25
  else
24
- (from <=> other)
26
+ (self.begin <=> other)
25
27
  end
26
28
  end
27
29
 
@@ -9,7 +9,7 @@ class ActivePeriod::Period < Range
9
9
  # @param range [Range] A valid range
10
10
  # @param allow_beginless [Boolean] Is it allow to creat a beginless range
11
11
  # @param allow_endless [Boolean] Is it allow to creat an endless range
12
- # @return [self] A new instance of ActivePeriod::FreePeriod
12
+ # @return [self] A new instance of ActivePeriod::Period
13
13
  # @raise ArgumentError if the params range is not a Range
14
14
  # @raise ArgumentError if the params range is invalid
15
15
  def initialize(range, allow_beginless: true, allow_endless: true)
@@ -25,8 +25,6 @@ class ActivePeriod::Period < Range
25
25
  raise ::ArgumentError, I18n.t(:end_date_is_invalid, scope: %i[active_period period]) if !allow_endless && to.nil?
26
26
  to = to.try(:end_of_day) || to
27
27
 
28
- # raise ::ArgumentError, I18n.t(:endless_excluded_end_is_forbiden, scope: %i[active_period period]) if to.nil? && range.exclude_end?
29
- # to = to.prev_day if range.exclude_end?
30
28
  if range.exclude_end? && from && to && from.to_date == to.to_date
31
29
  raise ::ArgumentError, I18n.t(:start_is_equal_to_end_excluded, scope: %i[active_period period])
32
30
  end
@@ -70,19 +68,79 @@ class ActivePeriod::Period < Range
70
68
  raise NotImplementedError
71
69
  end
72
70
 
73
- # @param other [ActivePeriod::FreePeriod] Any kind of ActivePeriod::FreePeriod object
71
+ # @param other [ActivePeriod::Period, ActiveSupport::Duration, Numeric] Any kind of ActivePeriod::Period, ActiveSupport::Duration or Numeric (in seconds)
74
72
  # @return [Boolean] true if period are equals, false otherwise
75
- # @raise ArgumentError if params other is not a ActivePeriod::FreePeriod of some kind
73
+ # @raise ArgumentError if params other is not a ActivePeriod::Period of some kind
76
74
  def ==(other)
77
75
  if other.class.ancestors.include?(ActivePeriod::Period)
78
76
  from == other.from && self.calculated_end == other.calculated_end
79
- elsif other.is_a?(ActiveSupport::Duration) || other.is_a?(Numeric)
77
+ elsif other.is_a?(ActiveSupport::Duration)
80
78
  super(other)
79
+ elsif other.is_a?(Numeric)
80
+ super(other.seconds)
81
81
  else
82
82
  raise ArgumentError
83
83
  end
84
84
  end
85
85
 
86
+ # @param other [ActivePeriod::Period] Any kind of ActivePeriod::Period object
87
+ # @return [Boolean] true if period and class are the same, false otherwise
88
+ # @raise ArgumentError if params other is not a ActivePeriod::Period of some kind
89
+ def ===(other)
90
+ self == other && self.class == other.class
91
+ end
92
+
93
+ # @param other [ActivePeriod::Period] Any kind of ActivePeriod::Period object
94
+ # @return [ActivePeriod::Period, nil] Any kind of ActivePeriod::FreePeriod if period overlap, nil otherwise
95
+ # @raise ArgumentError if params other is not a ActivePeriod::Period of some kind
96
+ def &(other)
97
+ raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable]) unless other.class.ancestors.include?(ActivePeriod::Period)
98
+
99
+ # self 9------12
100
+ # other 1-----------10
101
+ if self.begin.in?(other) && !calculated_end.in?(other)
102
+ Period.new( Range.new(self.begin, other.to, other.exclude_end?) )
103
+ # self 1-----------10
104
+ # other 9------12
105
+ elsif !self.begin.in?(other) && calculated_end.in?(other)
106
+ Period.new( Range.new(other.begin, to, exclude_end?) )
107
+ # self 5-----8
108
+ # other 1-----------10
109
+ elsif other.include?(self)
110
+ other
111
+ # self 1-----------10
112
+ # other 5-----8
113
+ elsif self.include?(other)
114
+ self
115
+ else
116
+ nil
117
+ end
118
+ end
119
+
120
+ # @param other [ActivePeriod::Period] Any kind of ActivePeriod::Period object
121
+ # @return [ActivePeriod::Period, nil] Any kind of ActivePeriod::FreePeriod if period overlap, nil otherwise
122
+ # @raise ArgumentError if params other is not a ActivePeriod::Period of some kind
123
+ def |(other)
124
+ raise ArgumentError, I18n.t(:incomparable_error, scope: %i[active_period comparable]) unless other.class.ancestors.include?(ActivePeriod::Period)
125
+
126
+ # overlapping or tail to head
127
+ if self.begin.in?(other) || self.calculated_end.in?(other) || (
128
+ ((self.calculated_end+1.day).beginning_of_day == other.from) ^
129
+ ((other.calculated_end+1.day).beginning_of_day == self.from)
130
+ )
131
+ Period.new(
132
+ Range.new(
133
+ [self.begin, other.begin].min,
134
+ [self.to, other.to].max,
135
+ self.calculated_end > other.calculated_end ? self.exclude_end? : other.exclude_end?
136
+ )
137
+ )
138
+ # no overlapping
139
+ else
140
+ nil
141
+ end
142
+ end
143
+
86
144
  # @raise NotImplementedError This method should be implemented in daughter class
87
145
  def strftime
88
146
  raise NotImplementedError
@@ -1,5 +1,5 @@
1
1
  module ActivePeriod
2
2
 
3
- VERSION = '7.0.0'.freeze
3
+ VERSION = '7.1.1'.freeze
4
4
 
5
5
  end
data/lib/period.rb CHANGED
@@ -12,6 +12,11 @@ module Period
12
12
  ActivePeriod::FreePeriod.new(range, allow_beginless: false, allow_endless: false)
13
13
  end
14
14
 
15
+ # Shorthand to Period.new
16
+ def self.[](range)
17
+ Period.new(range)
18
+ end
19
+
15
20
  # env_time provide a Fallback if the project dont specify any Time.zone
16
21
  def self.env_time
17
22
  (Time.zone || Time)
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.0.0
4
+ version: 7.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - billau_l
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-22 00:00:00.000000000 Z
11
+ date: 2022-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -17,9 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '5'
20
- - - "~>"
20
+ - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '7'
22
+ version: '8'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +27,9 @@ dependencies:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  version: '5'
30
- - - "~>"
30
+ - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '7'
32
+ version: '8'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: i18n
35
35
  requirement: !ruby/object:Gem::Requirement