active_period 7.0.0 → 7.1.1

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: 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