time_calc 0.0.3 → 0.0.4

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: 3222784ca4e6f520d4402ce84f5ea6f8a9becccb66e3640071d0a29b332297b7
4
- data.tar.gz: 9746e03e5a3e560a5f63780e87ea75f87597faa44e594228f075ae5daca3a83b
3
+ metadata.gz: b611cfb8c2a45b600235a6a7b3c1c2ce0688205cf9b2be7130b2efa3a5f6b0bd
4
+ data.tar.gz: cd1ea75b65a186e5f444a4c1fbd20f146d36635857bbe901797a770d8249ec00
5
5
  SHA512:
6
- metadata.gz: a6f3315fe5e4bc9334cbee7f089f50aebf7dfa854a6580f7cc53488afa0c8cb9ef0601f0d47c691b8427cbeea4dcc2842c97022666009e3b01b8e4056883b67c
7
- data.tar.gz: d0ccd1540d9010f5c4cec6c3fb4708b75c3fc795cbe8913f7a7e43455caa6bf209f6d39ca828dd83bae8d73f4a7e8b7a0a7a432eaeaaec33442e6ef1afe5716d
6
+ metadata.gz: 91f750a32bf00c3bec57458cf89cabcaf0a307204b5a94d4bc5fb1210af88849b8c5e07feb63a75f6d05b242f5b390b2c64610df13156d7c19bd8db598227543
7
+ data.tar.gz: 89d16a28e6744ee4d7fd0c0cb18cbaf7dba2e8c8d1e459760b271c87e4927ca5e6a898af5220bb8e5bc9ce3148665fc7eb8d0a23a1bceef7ba356d2b3543355a
@@ -1,5 +1,10 @@
1
1
  # TimeCalc changelog
2
2
 
3
+ ## 0.0.4 / 2020-04-11
4
+
5
+ * Support `ActiveSupport::TimeWithZone` as a calculation target.
6
+
7
+
3
8
  ## 0.0.3 / 2019-12-14
4
9
 
5
10
  * Add `TimeCalc#iterate` to easily operate in "business date/time" contexts.
@@ -11,4 +16,4 @@
11
16
 
12
17
  ## 0.0.1 / 2019-07-05
13
18
 
14
- First release. Rip-off of [time_math2](https://github.com/zverok/time_math2) with full API redesign and dropping of some less-used features ("resamplers").
19
+ First release. Rip-off of [time_math2](https://github.com/zverok/time_math2) with full API redesign and dropping of some less-used features ("resamplers").
data/README.md CHANGED
@@ -16,7 +16,8 @@ _**NB:** TimeCalc is a continuation of [TimeMath](https://github.com/zverok/time
16
16
  * Tries its best to preserve timezone/offset information:
17
17
  * **on Ruby 2.6+**, for `Time` with real timezones, preserves them;
18
18
  * on Ruby < 2.6, preserves at least `utc_offset` of `Time`;
19
- * for `DateTime` preserves zone name.
19
+ * for `DateTime` preserves zone name;
20
+ * _Since 0.0.4,_ supports `ActiveSupport::TimeWithZone`, too. While in ActiveSupport-enabled context TimeCalc may seem redundant (you'll probably use `time - 1.day` anyways), some of the functionality is easier with TimeCalc (rounding to different units) or just not present in ActiveSupport (time sequences, iterate with skippking); also may be helpful for third-party libraries which want to use TimeCalc underneath but don't want to be broken in Rails context.
20
21
 
21
22
  ## Synopsis
22
23
 
@@ -7,11 +7,16 @@ class TimeCalc
7
7
  extend self
8
8
 
9
9
  ATTRS = {
10
- Time => %i[year month day hour min sec subsec utc_offset],
11
- Date => %i[year month day],
12
- DateTime => %i[year month day hour min sec sec_fraction zone]
10
+ 'Time' => %i[year month day hour min sec subsec utc_offset],
11
+ 'Date' => %i[year month day],
12
+ 'DateTime' => %i[year month day hour min sec sec_fraction zone],
13
+ 'ActiveSupport::TimeWithZone' => %i[year month day hour min sec sec_fraction time_zone]
13
14
  }.freeze
14
15
 
16
+ # @private
17
+ # Because AS::TimeWithZone so frigging smart that it returns "Time" from redefined class name.
18
+ CLASS_NAME = Class.instance_method(:name)
19
+
15
20
  def compatible?(v1, v2)
16
21
  [v1, v2].all?(Date) || [v1, v2].all?(Time)
17
22
  end
@@ -46,6 +51,22 @@ class TimeCalc
46
51
  .values.then { |components| DateTime.new(*components) }
47
52
  end
48
53
 
54
+ def merge_activesupport__timewithzone(value, **attrs)
55
+ # You'd imagine we should be able to use just value.change(...) ActiveSupport's API here...
56
+ # But it is not available if you don't require all the core_ext's of Time, so I decided to
57
+ # be on the safe side and use similar approach everywhere.
58
+
59
+ # When we truncate, we use :subsec key as a sign to zeroefy second fractions
60
+ attrs[:sec_fraction] ||= attrs.delete(:subsec) if attrs.key?(:subsec)
61
+
62
+ _merge(value, **attrs)
63
+ .then { |components|
64
+ zone = components.delete(:time_zone)
65
+ components.merge!(mday: components.delete(:day), mon: components.delete(:month))
66
+ zone.__send__(:parts_to_time, components, value)
67
+ }
68
+ end
69
+
49
70
  private
50
71
 
51
72
  REAL_TIMEZONE = ->(z) { z.respond_to?(:utc_to_local) } # Ruby 2.6 real timezones
@@ -63,7 +84,7 @@ class TimeCalc
63
84
  end
64
85
 
65
86
  def _merge(value, attrs)
66
- attr_names = ATTRS.fetch(value.class)
87
+ attr_names = ATTRS.fetch(CLASS_NAME.bind(value.class).call)
67
88
  attr_names.to_h { |u| [u, value.public_send(u)] }.merge(**attrs.slice(*attr_names))
68
89
  end
69
90
  end
@@ -6,27 +6,7 @@ require 'backports/2.6.0/hash/to_h'
6
6
  require 'backports/2.6.0/kernel/then'
7
7
  require 'backports/2.5.0/hash/slice'
8
8
  require 'backports/2.5.0/enumerable/all'
9
-
10
- if RUBY_VERSION < '2.7'
11
- # @private
12
- # TODO: Replace with backports after 2.7 release
13
- class Enumerator
14
- NOVALUE = Object.new.freeze
15
-
16
- def self.produce(initial = NOVALUE)
17
- fail ArgumentError, 'No block given' unless block_given?
18
-
19
- Enumerator.new do |y|
20
- val = initial == NOVALUE ? yield() : initial
21
-
22
- loop do
23
- y << val
24
- val = yield(val)
25
- end
26
- end
27
- end
28
- end
29
- end
9
+ require 'backports/2.7.0/enumerator/produce'
30
10
 
31
11
  class TimeCalc
32
12
  # Wrapper (one can say "monad") around date/time value, allowing to perform several TimeCalc
@@ -40,10 +20,17 @@ class TimeCalc
40
20
  # @private
41
21
  TIMEY = proc { |t| t.respond_to?(:to_time) }
42
22
 
23
+ # @private
24
+ # Because AS::TimeWithZone so frigging smart that it returns "Time" from redefined class name.
25
+ CLASS_NAME = Class.instance_method(:name)
26
+
43
27
  # @private
44
28
  def self.wrap(value)
45
29
  case value
46
30
  when Time, Date, DateTime
31
+ # NB: ActiveSupport::TimeWithZone will also pass to this branch if
32
+ # active_support/core_ext/time is required. But it is doubtfully it is not -- TWZ will be
33
+ # mostly unusable :)
47
34
  new(value)
48
35
  when Value
49
36
  value
@@ -100,7 +87,8 @@ class TimeCalc
100
87
  # @param attrs [Hash<Symbol => Integer>]
101
88
  # @return [Value]
102
89
  def merge(**attrs)
103
- Value.new(Types.public_send("merge_#{internal.class.name.downcase}", internal, **attrs))
90
+ class_name = CLASS_NAME.bind(internal.class).call.tr(':', '_')
91
+ Value.new(Types.public_send("merge_#{class_name.downcase}", internal, **attrs))
104
92
  end
105
93
 
106
94
  # Truncates all time components lower than `unit`. In other words, "floors" (rounds down)
@@ -2,5 +2,5 @@
2
2
 
3
3
  class TimeCalc
4
4
  # @private
5
- VERSION = '0.0.3'
5
+ VERSION = '0.0.4'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_calc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-14 00:00:00.000000000 Z
11
+ date: 2020-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backports
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.15.0
19
+ version: 3.17.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 3.15.0
26
+ version: 3.17.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubocop
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.77.0
33
+ version: 0.81.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.77.0
40
+ version: 0.81.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop-rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.37.0
47
+ version: 1.38.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.37.0
54
+ version: 1.38.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 0.0.6
89
+ version: 0.0.7
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 0.0.6
96
+ version: 0.0.7
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -110,18 +110,32 @@ dependencies:
110
110
  version: '0.9'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: tzinfo
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: activesupport
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
116
130
  - !ruby/object:Gem::Version
117
- version: '0'
131
+ version: '5.0'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
- version: '0'
138
+ version: '5.0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: rake
127
141
  requirement: !ruby/object:Gem::Requirement