duration.rb 0.4.0 → 0.5.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 +4 -4
- data/CHANGELOG +21 -0
- data/README.md +16 -2
- data/lib/Duration/Common.rb +32 -0
- data/lib/Duration/VERSION.rb +1 -1
- data/test/Duration/Common_test.rb +40 -0
- data/test/Duration/VERSION_test.rb +22 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6ba0b1a782117f5c6f5b7798620456110e617f5cf2f59ccedd45845cab01674
|
|
4
|
+
data.tar.gz: aa225e9b5369e6f334fc0a0962e57cb64c5a6ead3008d91fcbc74448c91fba2e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '045846aba621660eabc73c4115457a15e5f3838a0ba8fcced57fa5381c20ce68cc73ea64b51c2acf1d5bfbe7efc3c36c4854c41f019e9d156eb2687826ad4a4a'
|
|
7
|
+
data.tar.gz: d0f3455bd9631c7f423151f3aa14fc1a0b4f9bca264a4fe83ad56e535404e4d48b246af457814d5077f429ccfcc064b3f376d9bf649995fe1abff71301d9a349
|
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 20260812
|
|
4
|
+
|
|
5
|
+
0.5.1: + VERSION test.
|
|
6
|
+
|
|
7
|
+
1. + test/Duration/VERSION_test.rb: Ensure that VERSION is a string, that it has three dotted numbers, and that it matches the newest entry in the CHANGELOG. A release edits both files and this now ensure that one moves with the other.
|
|
8
|
+
2. + .gitignore
|
|
9
|
+
3. ~ README.md: /Months is slated for removal in 0.5.0/Months is therefore slated for removal/, 0.5.0 having been and gone with Months still in place.
|
|
10
|
+
4. ~ Duration::VERSION: /0.5.0/0.5.1/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## 20260811
|
|
14
|
+
|
|
15
|
+
0.5.0: + Multiplication and division, and with them the dimensionless ratio.
|
|
16
|
+
|
|
17
|
+
1. + Duration::Common#*: a duration times a number is a duration, in the receiver's own unit as the rest of the arithmetic is. A duration times a duration raises TypeError, there being no unit of time squared: refused rather than quietly given some plausible answer.
|
|
18
|
+
2. + Duration::Common#/: divided by a number a duration stays a duration; divided by a duration it becomes the dimensionless ratio of the two, the units having cancelled. That ratio is the shape of a rate or a speedup, and until now it could not be written at all: a timing had to be dropped back to a bare number before it could be divided, which is the point at which its unit is lost.
|
|
19
|
+
3. + Duration::Common#scale and #ratio, private, being the two halves of what #* and #/ mean. Division goes through Numeric#quo rather than #/, so that an Integer quantity divides exactly: 1.quo(3) is (1/3) where 1 / 3 is 0. A Float quantity stays a Float, this library manufacturing no precision it was not given.
|
|
20
|
+
4. + test/Duration/Common_test.rb: multiplication and division, including that 1.second / 3 holds a third rather than nothing, that 1.hour / 30.minutes is 2, and that 1.second / 3.milliseconds is exactly 1000/3.
|
|
21
|
+
5. ~ Duration::VERSION: /0.4.0/0.5.0/
|
|
22
|
+
|
|
23
|
+
|
|
3
24
|
## 20260718
|
|
4
25
|
|
|
5
26
|
0.4.0: + Nanoseconds and Microseconds, arithmetic and comparison, exact conversions without a base, and the Numeric monkeypatch made opt-in.
|
data/README.md
CHANGED
|
@@ -98,6 +98,20 @@ The examples below use the `Numeric` sugar, so they assume
|
|
|
98
98
|
90.seconds > 1.minute # => true
|
|
99
99
|
[1.hour, 30.seconds, 5.minutes].sort
|
|
100
100
|
# => [30.seconds, 5.minutes, 1.hour]
|
|
101
|
+
|
|
102
|
+
# Scaled by a number, a duration stays a duration and keeps its unit:
|
|
103
|
+
5.minutes * 3 # => #<Minutes @minutes=15>
|
|
104
|
+
1.hour / 4 # => #<Hours @hours=(1/4)>
|
|
105
|
+
1.second / 3 # => #<Seconds @seconds=(1/3)> (not 0)
|
|
106
|
+
|
|
107
|
+
# Divided by a duration, the units cancel and a plain number is left. It is a
|
|
108
|
+
# Rational when both quantities are exact, as Numeric#quo gives, so it compares
|
|
109
|
+
# and calculates as the number it is; call to_f at the edge.
|
|
110
|
+
1.hour / 30.minutes # => (2/1)
|
|
111
|
+
1.second / 3.milliseconds # => (1000/3)
|
|
112
|
+
|
|
113
|
+
# There is no unit of time squared, so this is refused rather than answered:
|
|
114
|
+
5.minutes * 3.minutes # => TypeError
|
|
101
115
|
```
|
|
102
116
|
|
|
103
117
|
### Time Calculations
|
|
@@ -124,8 +138,8 @@ the calendar. Its conversions use the Gregorian mean month (2629746 seconds),
|
|
|
124
138
|
so they are honest only as a statistical average, never as calendar-correct
|
|
125
139
|
arithmetic. Its `ago`/`hence` inherit this — they displace by the mean month,
|
|
126
140
|
so they are approximate rather than calendar-correct; reach for a
|
|
127
|
-
calendar-anchored type such as `month.rb` when that matters. `Months` is
|
|
128
|
-
for removal
|
|
141
|
+
calendar-anchored type such as `month.rb` when that matters. `Months` is
|
|
142
|
+
therefore slated for removal.
|
|
129
143
|
|
|
130
144
|
## Contributing
|
|
131
145
|
|
data/lib/Duration/Common.rb
CHANGED
|
@@ -13,6 +13,24 @@ module Duration
|
|
|
13
13
|
combine(:-, other)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# A duration times a number is a duration. A duration times a duration
|
|
17
|
+
# would be time squared, which has no unit here and few enough anywhere, so
|
|
18
|
+
# it is refused rather than quietly given some plausible answer.
|
|
19
|
+
def *(other)
|
|
20
|
+
if other.is_a?(Duration::Common)
|
|
21
|
+
raise TypeError, "can't multiply #{self.class} by #{other.class}: there is no unit of time squared"
|
|
22
|
+
end
|
|
23
|
+
scale(:*, other)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Divided by a number a duration stays a duration. Divided by a duration it
|
|
27
|
+
# becomes the dimensionless ratio of the two, the units having cancelled,
|
|
28
|
+
# which is how a rate or a speedup is arrived at.
|
|
29
|
+
def /(other)
|
|
30
|
+
return ratio(other) if other.is_a?(Duration::Common)
|
|
31
|
+
scale(:quo, other)
|
|
32
|
+
end
|
|
33
|
+
|
|
16
34
|
def <=>(other)
|
|
17
35
|
return nil unless other.is_a?(Duration::Common)
|
|
18
36
|
quantity <=> other.send(:"to_#{unit}").quantity
|
|
@@ -32,5 +50,19 @@ module Duration
|
|
|
32
50
|
end
|
|
33
51
|
self.class.new(quantity.send(operator, other.send(:"to_#{unit}").quantity))
|
|
34
52
|
end
|
|
53
|
+
|
|
54
|
+
# Division goes through #quo rather than #/ so that an Integer quantity
|
|
55
|
+
# divides exactly: 1.quo(3) is (1/3) where 1 / 3 is 0. A Float quantity
|
|
56
|
+
# stays a Float, this library manufacturing no precision it was not given.
|
|
57
|
+
def scale(operator, other)
|
|
58
|
+
unless other.is_a?(Numeric)
|
|
59
|
+
raise TypeError, "can't scale #{self.class} by #{other.class}"
|
|
60
|
+
end
|
|
61
|
+
self.class.new(quantity.send(operator, other))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def ratio(other)
|
|
65
|
+
quantity.quo(other.send(:"to_#{unit}").quantity)
|
|
66
|
+
end
|
|
35
67
|
end
|
|
36
68
|
end
|
data/lib/Duration/VERSION.rb
CHANGED
|
@@ -30,6 +30,46 @@ describe Duration::Common do
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
describe "multiplication" do
|
|
34
|
+
it "scales a duration by a number, keeping the unit" do
|
|
35
|
+
result = 5.minutes * 3
|
|
36
|
+
_(result).must_be_instance_of Duration::Minutes
|
|
37
|
+
_(result.to_i).must_equal 15
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "raises upon a duration, there being no unit of time squared" do
|
|
41
|
+
_{5.minutes * 3.minutes}.must_raise TypeError
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "raises upon a non-numeric" do
|
|
45
|
+
_{5.minutes * "3"}.must_raise TypeError
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "division" do
|
|
50
|
+
it "scales a duration by a number, keeping the unit" do
|
|
51
|
+
result = 1.hour / 4
|
|
52
|
+
_(result).must_be_instance_of Duration::Hours
|
|
53
|
+
_(result.to_minutes.to_f).must_equal 15.0
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "divides exactly rather than as integers" do
|
|
57
|
+
_(1.second / 3).must_equal Duration::Seconds.new(Rational(1, 3))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "returns the dimensionless ratio of two durations" do
|
|
61
|
+
_(1.hour / 30.minutes).must_equal 2
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "takes the ratio across units exactly" do
|
|
65
|
+
_(1.second / 3.milliseconds).must_equal Rational(1000, 3)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "raises upon a non-numeric" do
|
|
69
|
+
_{5.minutes / "3"}.must_raise TypeError
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
33
73
|
describe "comparison" do
|
|
34
74
|
it "compares durations of different units exactly" do
|
|
35
75
|
_(5.minutes).must_equal 300.seconds
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# test/duration/version_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../test_helper'
|
|
4
|
+
|
|
5
|
+
# Note that VERSION.rb is the one file duration.rb requires rather than autoloaded, because an autoloaded file goes unread until its constant is named and nothing else here names this one.
|
|
6
|
+
|
|
7
|
+
describe Duration do
|
|
8
|
+
describe "VERSION" do
|
|
9
|
+
it "is a string" do
|
|
10
|
+
_(Duration::VERSION).must_be_instance_of String
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "is three numbers separated by dots" do
|
|
14
|
+
_(Duration::VERSION).must_match(/\A\d+\.\d+\.\d+\z/)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "matches the newest entry in the CHANGELOG" do
|
|
18
|
+
changelog = File.read(File.expand_path('../../CHANGELOG', __dir__))
|
|
19
|
+
_(changelog[/^(\d+\.\d+\.\d+):/, 1]).must_equal Duration::VERSION
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: duration.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -87,6 +87,7 @@ files:
|
|
|
87
87
|
- test/Duration/Nanoseconds_test.rb
|
|
88
88
|
- test/Duration/Numeric_test.rb
|
|
89
89
|
- test/Duration/Seconds_test.rb
|
|
90
|
+
- test/Duration/VERSION_test.rb
|
|
90
91
|
- test/Duration/Weeks_test.rb
|
|
91
92
|
- test/test_helper.rb
|
|
92
93
|
homepage: http://github.com/thoran/duration.rb
|
|
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
107
108
|
- !ruby/object:Gem::Version
|
|
108
109
|
version: '0'
|
|
109
110
|
requirements: []
|
|
110
|
-
rubygems_version: 4.0.
|
|
111
|
+
rubygems_version: 4.0.18
|
|
111
112
|
specification_version: 4
|
|
112
113
|
summary: Objects for handling durations of time.
|
|
113
114
|
test_files: []
|