activesupport-duration-change 1.0.0
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 +7 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Changelog.md +14 -0
- data/Gemfile +6 -0
- data/License +21 -0
- data/Rakefile +6 -0
- data/Readme.md +77 -0
- data/activesupport-duration-change.gemspec +35 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/active_support/duration/change/version.rb +9 -0
- data/lib/active_support/duration/change.rb +218 -0
- data/lib/activesupport-duration-change.rb +1 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7339f01b9c0cb2e98702c59b463b2e9919b5b5ebeda8b248e6683b0ae6f3eb5d
|
4
|
+
data.tar.gz: 3bce02d7c7ab9f1d3c18726814cddd6c963071b420a19bb6b5ab8956b9171525
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fceb5ea4dc1f38eae7f56d580a9e458b1291f864d85f92aa3d56a1ffd316d184ef28c72bd6fd019d1b622705ca31155d85cccc7a16ac0dffea33a76e443b0147
|
7
|
+
data.tar.gz: b846cae81544e325def271ca47e8fed45a77e81521e21e62c8153e6e43d1e11eb078a4e3a9175c629b950a464fa813abe10cd2e9907f97c33b3d9353d9db6429
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Changelog.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
## 1.0.0 (2024-02-16)
|
2
|
+
|
3
|
+
Fixes:
|
4
|
+
|
5
|
+
- Relax activesupport dependency version
|
6
|
+
|
7
|
+
Breaking changes:
|
8
|
+
|
9
|
+
- Extract `#change`, `#truncate`, `#round`, etc. out of this gem into the [activesupport-duration-change](https://github.com/TylerRick/activesupport-duration-change) gem
|
10
|
+
|
11
|
+
## 0.1.1 (2019-04-02)
|
12
|
+
|
13
|
+
Initial release
|
14
|
+
|
data/Gemfile
ADDED
data/License
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Tyler Rick
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# ActiveSupport::Duration#change [](https://badge.fury.io/rb/activesupport-duration-change)
|
2
|
+
|
3
|
+
Change/manipulate [ActiveSupport::Duration](https://api.rubyonrails.org/classes/ActiveSupport/Duration.html) objects with these added methods:
|
4
|
+
|
5
|
+
# API
|
6
|
+
|
7
|
+
## `#change`, `#change_cascade`
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
(9.hours + 10.minutes + 40.seconds).change(hours: 12) #=> 12 hours, 10 minutes, and 40 seconds
|
11
|
+
(9.hours + 10.minutes + 40.seconds).change(hours: 12, minutes: 5) #=> 12 hours, 5 minutes, and 40 seconds
|
12
|
+
(9.hours + 10.minutes + 40.seconds).change(minutes: 5) #=> 9 hours, 5 minutes, and 40 seconds
|
13
|
+
|
14
|
+
(9.hours + 10.minutes + 40.seconds).change_cascade(hours: 12) # => 12 hours
|
15
|
+
(9.hours + 10.minutes + 40.seconds).change_cascade(minutes: 5) # => 9 hours and 5 minutes
|
16
|
+
```
|
17
|
+
|
18
|
+
## `#normalize`
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
90.seconds.normalize #=> 1 minute and 30 seconds
|
22
|
+
23.hours + 59.minutes + 60.seconds).normalize #=> 1 day
|
23
|
+
```
|
24
|
+
|
25
|
+
## `#round`
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
30.seconds.round(:minutes) #=> 1 minute
|
29
|
+
89.seconds.round(:minutes) #=> 1 minute
|
30
|
+
90.seconds.round(:minutes) #=> 2 minutes
|
31
|
+
(1.hour + 30.seconds).round(:minutes) #=> 1 hour and 1 minute
|
32
|
+
|
33
|
+
2.5.seconds.round #=> 3 seconds
|
34
|
+
2.5.seconds.round(half: :down) #=> 2 seconds
|
35
|
+
```
|
36
|
+
|
37
|
+
## `#truncate`
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
30.seconds.truncate(:minutes) #=> 0 seconds
|
41
|
+
|
42
|
+
# This could be surprising, but remember that it just looks at the values as they exist in each part.
|
43
|
+
90.seconds.truncate(:minutes) #=> 0 seconds
|
44
|
+
|
45
|
+
# If needed, you can always normalize the duration first...
|
46
|
+
90.seconds.normalize #=> 1 minute and 30 seconds
|
47
|
+
90.seconds.normalize.truncate(:minutes) #=> 1 minute
|
48
|
+
```
|
49
|
+
|
50
|
+
## .from_parts
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# This is the inverse of #parts.
|
54
|
+
duration = ActiveSupport::Duration.from_parts({hours: 9, minutes: 10, seconds: 40})
|
55
|
+
```
|
56
|
+
|
57
|
+
# Installation
|
58
|
+
|
59
|
+
Add this line to your application's Gemfile:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
gem 'activesupport-duration-change'
|
63
|
+
```
|
64
|
+
|
65
|
+
# See also
|
66
|
+
|
67
|
+
- [activesupport-duration-human_string](https://github.com/TylerRick/activesupport-duration-human_string), which lets you convert `Duration` objects to human-friendly strings like '2h 30m 17s'
|
68
|
+
|
69
|
+
# Development
|
70
|
+
|
71
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
72
|
+
|
73
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
74
|
+
|
75
|
+
# Contributing
|
76
|
+
|
77
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/TylerRick/activesupport-duration-change.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "active_support/duration/change/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "activesupport-duration-change"
|
8
|
+
spec.version = ActiveSupport::Duration::Change.version
|
9
|
+
spec.authors = ["Tyler Rick"]
|
10
|
+
spec.email = ["tyler@tylerrick.com"]
|
11
|
+
spec.license = "MIT"
|
12
|
+
|
13
|
+
spec.summary = %q{Adds methods such as `#change`, `#truncate`, `#round` to `Duration`}
|
14
|
+
spec.homepage = "https://github.com/TylerRick/activesupport-duration-change"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
18
|
+
spec.metadata["changelog_uri"] = "#{spec.metadata["source_code_uri"]}/blob/master/Changelog.md"
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.required_ruby_version = ">= 2.3.0"
|
30
|
+
spec.add_dependency "activesupport", [">= 5.2"]
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler"
|
33
|
+
spec.add_development_dependency "rake"
|
34
|
+
spec.add_development_dependency "rspec"
|
35
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "active_support/duration/change"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'active_support/duration'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
class Duration
|
5
|
+
class << self
|
6
|
+
# Creates a new Duration from a Hash of parts (inverse of Duration#parts).
|
7
|
+
#
|
8
|
+
# Surprising that upstream ActiveSupport doesn't provide this method
|
9
|
+
#
|
10
|
+
# normalize: true (the default) changes 30.5m into 30m, 30s, for example.
|
11
|
+
def from_parts(parts, normalize: true)
|
12
|
+
parts = parts.compact.reject { |k, v| v.zero? }
|
13
|
+
duration = new(calculate_total_seconds(parts), parts)
|
14
|
+
if normalize
|
15
|
+
duration.normalize
|
16
|
+
else
|
17
|
+
duration
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias parse_parts from_parts
|
22
|
+
|
23
|
+
def units_largest_first
|
24
|
+
# Reverse since PARTS_IN_SECONDS is ordered smallest to largest
|
25
|
+
PARTS_IN_SECONDS.keys.reverse.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def next_smaller_unit(unit)
|
29
|
+
i = PARTS.index(unit) or raise(ArgumentError, "unknown unit #{unit}")
|
30
|
+
PARTS[i + 1]
|
31
|
+
end
|
32
|
+
|
33
|
+
def smaller_units(unit)
|
34
|
+
# The index of unit; we only want parts with indexes > this index
|
35
|
+
unit_i = units_largest_first.index(unit) or raise(ArgumentError, "unknown unit #{unit}")
|
36
|
+
units_largest_first.select.with_index { |key, i| i > unit_i }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Re-builds the Duration using build(value). Useful if you may have "extra" seconds, minutes,
|
41
|
+
# etc. that could be carried over to the next higher unit, such as if you've built a Duration
|
42
|
+
# using Duration.seconds and a number of seconds > 60.
|
43
|
+
#
|
44
|
+
# ActiveSupport::Duration.seconds(61).normalize
|
45
|
+
# => 1 minute and 1 second
|
46
|
+
#
|
47
|
+
def normalize
|
48
|
+
Duration.build(value)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Replaces parts of duration with given part values. Unlike #change_cascade and Time#change,
|
52
|
+
# *only* ever changes the given parts; it does *not* reset any smaller-unit parts.
|
53
|
+
def change(**changes)
|
54
|
+
self.class.from_parts(
|
55
|
+
parts.merge(changes),
|
56
|
+
normalize: false
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Changes the given part(s) of the duration and resets any smaller parts.
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
# (9.hours + 10.minutes + 40.seconds).change_cascade(hours: 12) # => 12 hours
|
64
|
+
# (9.hours + 10.minutes + 40.seconds).change_cascade(minutes: 5) # => 9 hours and 5 minutes
|
65
|
+
#
|
66
|
+
# Similar to Time#change
|
67
|
+
# But note that the keys are plural, so :years instead of :year.
|
68
|
+
# Should we allow key aliases? Should we raise ArgumentError if key not recognized? Yes. (Why doesn't Time#change?)
|
69
|
+
# or should this be named truncate? or change_reset_smaller_parts?
|
70
|
+
#
|
71
|
+
#-----------
|
72
|
+
# Returns a new Duration where one or more of the elements have been changed according
|
73
|
+
# to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
|
74
|
+
# <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
|
75
|
+
# the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
|
76
|
+
# and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
|
77
|
+
# takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
|
78
|
+
# <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
|
79
|
+
# <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
|
80
|
+
#
|
81
|
+
# Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
|
82
|
+
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
|
83
|
+
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
|
84
|
+
def change_cascade(options)
|
85
|
+
options.assert_valid_keys(*PARTS_IN_SECONDS, :nsec, :usec)
|
86
|
+
|
87
|
+
reset = false
|
88
|
+
new_parts = {}
|
89
|
+
new_parts[:years] = options.fetch(:years, parts[:years]) ; reset ||= options.key?(:years)
|
90
|
+
new_parts[:months] = options.fetch(:months, reset ? 0 : parts[:months]) ; reset ||= options.key?(:months)
|
91
|
+
new_parts[:days] = options.fetch(:days, reset ? 0 : parts[:days]) ; reset ||= options.key?(:days)
|
92
|
+
new_parts[:hours] = options.fetch(:hours, reset ? 0 : parts[:hours]) ; reset ||= options.key?(:hours)
|
93
|
+
new_parts[:minutes] = options.fetch(:minutes, reset ? 0 : parts[:minutes]); reset ||= options.key?(:minutes)
|
94
|
+
new_parts[:seconds] = options.fetch(:seconds, reset ? 0 : parts[:seconds])
|
95
|
+
|
96
|
+
if new_nsec = options[:nsec]
|
97
|
+
raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
|
98
|
+
new_usec = Rational(new_nsec, 1000)
|
99
|
+
else
|
100
|
+
new_usec = nil
|
101
|
+
# new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 :
|
102
|
+
# Rational(nsec, 1000))
|
103
|
+
end
|
104
|
+
if new_usec
|
105
|
+
raise ArgumentError, "argument out of range" if new_usec >= 1000000
|
106
|
+
|
107
|
+
new_parts[:seconds] += Rational(new_usec, 1000000)
|
108
|
+
end
|
109
|
+
|
110
|
+
self.class.from_parts(
|
111
|
+
new_parts.compact.reject { |k, v| v.zero? },
|
112
|
+
normalize: false,
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
# Returns duration rounded to the nearest value having a precision of `precision`, which is a
|
118
|
+
# unit such as :hours, which would mean "round to the nearest hour". The smaller parts (:minutes
|
119
|
+
# and :seconds in this example) are turned into a fraction of the requested precision (:hours),
|
120
|
+
# which is then added to requested precision part. Finally, `round` is called on the requested
|
121
|
+
# precision part (hours in this example).
|
122
|
+
#
|
123
|
+
# If optional [ndigits] [, half: mode] arguments are supplied, they are passed along to
|
124
|
+
# [round](https://ruby-doc.org/core/Float.html#method-i-round).
|
125
|
+
#
|
126
|
+
# @example
|
127
|
+
# 30.seconds.round(:minutes) #=> 1 minute
|
128
|
+
# 89.seconds.round(:minutes) #=> 1 minute
|
129
|
+
# 90.seconds.round(:minutes) #=> 2 minutes
|
130
|
+
# (1.hour + 30.seconds).round(:minutes) #=> 1 hour and 1 minute
|
131
|
+
#
|
132
|
+
# 2.5.seconds.round #=> 3 seconds
|
133
|
+
# 2.5.seconds.round(half: :down) #=> 2 seconds
|
134
|
+
#
|
135
|
+
# @raises ArgumentError
|
136
|
+
# TODO raise ArgumentError if precision not recognized as a unit
|
137
|
+
#
|
138
|
+
def round(precision = smallest_unit, *args, **opts)
|
139
|
+
#puts "Rounding #{parts.inspect} (in particular #{parts[precision]} #{precision}) to nearest #{precision.inspect}"
|
140
|
+
|
141
|
+
new_part_value = orig_part_value = (parts[precision] || 0)
|
142
|
+
fraction = smaller_parts_to_fraction_of(precision)
|
143
|
+
# Usually fraction is in the range 0..1, unless the smaller units are overflowed (non-normalized)
|
144
|
+
new_part_value += fraction
|
145
|
+
#puts "Adding #{orig_part_value} + fraction parts #{fraction.inspect} (#{fraction.to_f}) = #{new_part_value} (#{new_part_value.to_f})"
|
146
|
+
|
147
|
+
new_part_value = new_part_value.round(*args, **opts)
|
148
|
+
|
149
|
+
change_cascade(
|
150
|
+
precision => new_part_value
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Convert the parts that are smaller than `unit` to be a fraction (Rational) of that
|
155
|
+
# `unit`.
|
156
|
+
#
|
157
|
+
# For example, if `unit` is :hours and self is 1h 29m 60s, then it would look at the parts
|
158
|
+
# smaller than hour, 29m 60s, which is the same as 30m, and would convert that to a fraction of
|
159
|
+
# hours, which would be 30m/60m = 1/2r.
|
160
|
+
#
|
161
|
+
def smaller_parts_to_fraction_of(unit)
|
162
|
+
#next_smaller_unit = self.class.next_smaller_unit(unit)
|
163
|
+
#next_smaller_unit_in_s = ActiveSupport::Duration::PARTS_IN_SECONDS[next_smaller_unit] # 1 if unit == :minutes
|
164
|
+
#puts %(unit_in_s=#{(unit_in_s).inspect}, next_smaller_unit_in_s=#{(next_smaller_unit_in_s).inspect})
|
165
|
+
|
166
|
+
smaller_parts = smaller_parts(unit)
|
167
|
+
numerator_s = ActiveSupport::Duration.send(:calculate_total_seconds, smaller_parts)
|
168
|
+
denominator_s = ActiveSupport::Duration::PARTS_IN_SECONDS[unit] # 60 if unit == :minutes
|
169
|
+
|
170
|
+
fraction = Rational(numerator_s, denominator_s)
|
171
|
+
#puts "#{smaller_parts.inspect} converted to fraction #{numerator_s}/#{denominator_s} = #{fraction} (#{fraction.to_f})"
|
172
|
+
fraction
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns all parts than `unit` as a Hash that is a subset of self.parts.
|
176
|
+
#
|
177
|
+
# For example, if `unit` is :hours and self is 1h 29m 60s, then it would return the parts
|
178
|
+
# smaller than hour, 29m 60s, as the hash { minutes: 29, seconds: 60 }.
|
179
|
+
#
|
180
|
+
def smaller_parts(unit)
|
181
|
+
parts.slice *ActiveSupport::Duration.smaller_units(unit)
|
182
|
+
end
|
183
|
+
|
184
|
+
def smallest_part
|
185
|
+
[parts.to_a.last].to_h
|
186
|
+
end
|
187
|
+
|
188
|
+
def smallest_unit
|
189
|
+
parts.to_a.last[0]
|
190
|
+
end
|
191
|
+
|
192
|
+
# Truncates the Duration to the specified precision. All smaller parts are discarded.
|
193
|
+
#
|
194
|
+
# Similar to https://ruby-doc.org/core-2.7.1/Float.html#method-i-truncate
|
195
|
+
#
|
196
|
+
def truncate(precision = smallest_unit, *args, **opts)
|
197
|
+
#puts %(Truncating #{parts.inspect} to #{precision.inspect})
|
198
|
+
|
199
|
+
# TODO: only use truncate here if :seconds or if part is Float ?
|
200
|
+
# or just always pass them along, although they are probably only needed for :seconds
|
201
|
+
part_value = (parts[precision] || 0)
|
202
|
+
new_part_value = part_value.truncate(*args)
|
203
|
+
change_cascade(
|
204
|
+
precision => new_part_value
|
205
|
+
)
|
206
|
+
end
|
207
|
+
|
208
|
+
# TODO: For completeness to complement truncate:
|
209
|
+
# https://ruby-doc.org/3.2.2/Float.html#method-i-ceil
|
210
|
+
# https://ruby-doc.org/3.2.2/Rational.html#method-i-round
|
211
|
+
# def ceil
|
212
|
+
# end
|
213
|
+
|
214
|
+
# def floor
|
215
|
+
# end
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_support/duration/change'
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activesupport-duration-change
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tyler Rick
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-02-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- tyler@tylerrick.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Changelog.md
|
80
|
+
- Gemfile
|
81
|
+
- License
|
82
|
+
- Rakefile
|
83
|
+
- Readme.md
|
84
|
+
- activesupport-duration-change.gemspec
|
85
|
+
- bin/console
|
86
|
+
- bin/setup
|
87
|
+
- lib/active_support/duration/change.rb
|
88
|
+
- lib/active_support/duration/change/version.rb
|
89
|
+
- lib/activesupport-duration-change.rb
|
90
|
+
homepage: https://github.com/TylerRick/activesupport-duration-change
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata:
|
94
|
+
homepage_uri: https://github.com/TylerRick/activesupport-duration-change
|
95
|
+
source_code_uri: https://github.com/TylerRick/activesupport-duration-change
|
96
|
+
changelog_uri: https://github.com/TylerRick/activesupport-duration-change/blob/master/Changelog.md
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 2.3.0
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubygems_version: 3.5.1
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Adds methods such as `#change`, `#truncate`, `#round` to `Duration`
|
116
|
+
test_files: []
|