timerage 1.8.0 → 2.0.0

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
  SHA1:
3
- metadata.gz: a516908d80d7444bc7558fe488fe546aba2d123f
4
- data.tar.gz: d3ca42c6b1190a24c9030f6e91cebb5844447c05
3
+ metadata.gz: f82bbd7083065080ca7d80bf905a6f77d8bf2e7f
4
+ data.tar.gz: fbbcc51556bbdcf68e000937cb0d219c78f942e1
5
5
  SHA512:
6
- metadata.gz: aca0bf8520121da781d8e28a0f80974d619feba6f1e1a2f6b15055ff83e09489fc138a8dabfb47b594b43b738650294ed63ad089f9c2630e17a4467fc3c874d4
7
- data.tar.gz: b73c86c3d951f1cd9571b63015647e67635d45a1cef8bec33d2794a213e08154765a0ea74575c7399a4e0dfd3522f5b0e651ef660b90624d0560233a25bfd6ba
6
+ metadata.gz: 0f3d81194d057830e4fe1743df1b8fe65c79af78ebf71f406792d1d26f513aac2f42321dea5cc58633c9733aa043321b091f96e6fc6244d99952b9bc81c8ea66
7
+ data.tar.gz: 04d3101baf65ab9eef0b4ffd3ccd7b6081016debe211e69cdf40c7f26395809f2efb29e66fbd785cbb94749da93fb5d2ae7a8cdcd9ec79f67b6865a1f9edb3d2
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Timerage
2
2
 
3
- Simple refinement to make Time Ranges work a little.
3
+ Time Ranges that are actually useful.
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,15 +20,66 @@ Or install it yourself as:
20
20
 
21
21
  ```ruby
22
22
  require 'timerage'
23
+ ```
24
+
25
+ ### Coercion to Time (related) objects
26
+
27
+ ``` ruby
28
+ a_time = Timerage("2016-01-18T22:25:37Z")
29
+ # => 2016-01-18 22:25:37 +0000
30
+
31
+ Timerage(a_time)
32
+ # => 2016-01-18 22:25:37 +0000
33
+
34
+ Timerage("2016-01-18T21:25:37+00:00/2016-01-18T22:25:37+00:00")
35
+ # => 2016-01-18 21:25:37 +0000...2016-01-18 22:25:37 +0000
36
+
37
+ interval = Timerage((a_time-3600)...a_time)
38
+ # => 2016-01-18 21:25:37 +0000...2016-01-18 22:25:37 +0000
39
+ ```
23
40
 
24
- class MyClass
25
- using Timerage
41
+ ### Stepping over a time inteval
42
+
43
+ ```ruby
44
+ interval.step(30*60).map { |time| time }
45
+ # => [2016-01-18 21:25:37 +0000, 2016-01-18 21:55:37 +0000]
46
+ ```
47
+
48
+ ### Slicing a time interval
49
+
50
+ ```ruby
51
+ interval.slice(30*60).map { |time| time }
52
+ # => [2016-01-18 21:25:37 UTC...2016-01-18 21:55:37 UTC, 2016-01-18 21:55:37 UTC...2016-01-18 22:25:37 UTC]
53
+ ```
26
54
 
27
- # Step over these two times in 10 second steps
28
- def my_method(time1, time2)
29
- (time1..time2).step(10) { |time| puts time}
30
- end
31
- end
55
+ ### ISO 8601 output
56
+
57
+ ```ruby
58
+ interval.iso8601
59
+ # => "2016-01-18T21:25:37+00:00/2016-01-18T22:25:37+00:00"
60
+ ```
61
+
62
+ ### Comparisons
63
+
64
+ Supports most range/set comparisons
65
+
66
+ * `#overlap?`
67
+ * `#cover?`
68
+ * `#adjacent_to?`
69
+ * `#==`
70
+
71
+ ### Concatenation
72
+
73
+ ```ruby
74
+ interval + Timerage("2016-01-18T20:25:37+00:00/2016-01-18T21:25:37+00:00")
75
+ # => 2016-01-18 20:25:37 UTC..2016-01-18 22:25:37 UTC
76
+ ```
77
+
78
+ ### Duration
79
+
80
+ ```ruby
81
+ interval.duration
82
+ # => 3600.0
32
83
  ```
33
84
 
34
85
  ## Gotchas
@@ -10,8 +10,8 @@ module Timerage
10
10
  # --
11
11
  #
12
12
  # Currently this only supports `<begin>/<end>` style time intervals.
13
- def self.parse_iso8601(str)
14
- TimeInterval.iso8601(str)
13
+ def self.parse_iso8601(str, exclusive_end: true)
14
+ TimeInterval.iso8601(str, exclusive_end: exclusive_end)
15
15
  rescue ArgumentError
16
16
  Time.iso8601(str)
17
17
  end
@@ -30,3 +30,27 @@ module Timerage
30
30
  end
31
31
  end
32
32
  end
33
+
34
+ module Kernel
35
+ def Timerage(time_or_time_interval_ish)
36
+ thing = time_or_time_interval_ish
37
+
38
+ case thing
39
+ when ->(x) { x.respond_to? :to_time_interval }
40
+ thing
41
+
42
+ when ->(x) { x.respond_to? :exclude_end? }
43
+ Timerage::TimeInterval.new(thing)
44
+
45
+ when ->(x) { x.respond_to? :to_str }
46
+ Timerage.parse_iso8601(thing.to_str)
47
+
48
+ when ->(x) { x.respond_to? :to_time }
49
+ thing.to_time
50
+
51
+ else
52
+ fail TypeError, "unable to coerce #{thing} to a time or interval"
53
+
54
+ end
55
+ end
56
+ end
@@ -13,6 +13,10 @@ module Timerage
13
13
  super rng
14
14
  end
15
15
 
16
+ def to_time_interval
17
+ self
18
+ end
19
+
16
20
  alias_method :to_time, :begin
17
21
 
18
22
  # Returns number of seconds in this interval
@@ -53,37 +57,41 @@ module Timerage
53
57
  "#{self.begin.iso8601(*args)}/#{self.end.iso8601(*args)}"
54
58
  end
55
59
 
60
+ def getutc
61
+ return self if self.begin.utc? && self.end.utc?
62
+ self.class.new(self.begin.getutc, self.end.getutc, self.exclude_end?)
63
+ end
64
+
56
65
  def adjacent_to?(other)
57
66
  other.begin == self.end || other.end == self.begin
58
67
  end
59
68
 
60
69
  def cover?(time_or_interval)
61
- return super unless rangeish?(time_or_interval)
62
-
63
70
  other = time_or_interval
71
+ return super unless rangeish?(other)
72
+ return false unless overlap?(other)
64
73
 
65
- self.begin <= other.begin &&
66
- if self.exclude_end? && other.exclude_end?
67
- self.end > other.begin && self.begin < other.end && other.end <= self.end
68
-
69
- elsif self.exclude_end?
70
- self.end > other.begin && self.begin <= other.end && other.end < self.end
71
-
72
- elsif other.exclude_end?
73
- self.end >= other.begin && self.begin < other.end && other.end <= self.end
74
-
74
+ self_end, other_end = self.end, other.end
75
+ other.begin >= self.begin &&
76
+ if !self.exclude_end? || other.exclude_end?
77
+ other_end <= self_end
75
78
  else
76
- self.end >= other.begin && self.begin <= other.end && other.end <= self.end
79
+ other_end < self_end
77
80
  end
78
81
  end
79
82
 
80
83
  def overlap?(other)
81
- cover?(other) ||
82
- other.cover?(self) ||
83
- cover?(other.begin) ||
84
- other.cover?(self.begin) ||
85
- cover?(other.end) && (!other.exclude_end? || other.end != self.begin) ||
86
- other.cover?(self.end) && (!self.exclude_end? || other.begin != self.end)
84
+ earliest, latest = if self.begin <= other.begin
85
+ [self, other]
86
+ else
87
+ [other, self]
88
+ end
89
+
90
+ latest_begin, earliest_end = latest.begin, earliest.end
91
+ return true if latest_begin < earliest_end
92
+ return false if earliest_end < latest_begin
93
+
94
+ !earliest.exclude_end?
87
95
  end
88
96
 
89
97
  def <=>(other)
@@ -159,11 +167,12 @@ module Timerage
159
167
  # --
160
168
  #
161
169
  # Currently this only supports `<begin>/<end>` style time intervals.
162
- def self.iso8601(str)
163
- new *str.split("/").map{|s| Time.iso8601(s)}
170
+ def self.iso8601(str, exclusive_end: true)
171
+ new *str.split("/", 2).map{|s| Time.iso8601(s)}, exclusive_end
164
172
 
165
173
  rescue ArgumentError
166
174
  raise ArgumentError, "Invalid iso8601 interval: #{str.inspect}"
167
175
  end
168
176
  end
177
+
169
178
  end
@@ -1,3 +1,3 @@
1
1
  module Timerage
2
- VERSION = "1.8.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -19,6 +19,24 @@ describe Timerage::TimeInterval do
19
19
  .to raise_error ArgumentError }
20
20
  end
21
21
 
22
+ describe "#getutc" do
23
+ subject(:interval_utc) { described_class.new(now-duration, now).getutc }
24
+ specify { expect(interval_utc).to be_kind_of described_class }
25
+
26
+ context "interval not in utc" do
27
+ specify { expect(now).not_to be_utc }
28
+ specify { expect(interval_utc.begin).to be_utc }
29
+ specify { expect(interval_utc.end).to be_utc }
30
+ end
31
+
32
+ context "interval already in utc" do
33
+ let(:now) { Time.now.getutc }
34
+ specify { expect(now).to be_utc }
35
+ specify { expect(interval_utc.begin).to be_utc }
36
+ specify { expect(interval_utc.end).to be_utc }
37
+ end
38
+ end
39
+
22
40
  subject(:interval) { described_class.new(now-duration, now) }
23
41
 
24
42
  it { is_expected.to behave_like_a Range }
@@ -9,7 +9,7 @@ describe Timerage do
9
9
  specify { expect(range.to_time_interval).to be_kind_of Timerage::TimeInterval }
10
10
  specify { expect{|b| range.step(1200, &b) }.to yield_control.at_least(:once) }
11
11
 
12
- describe ".iso8601" do
12
+ describe ".parse_iso8601" do
13
13
  specify { expect(described_class
14
14
  .parse_iso8601("2001-01-01T00:00:00Z/2001-01-02T00:00:00-06:00"))
15
15
  .to be_kind_of Timerage::TimeInterval }
@@ -30,7 +30,23 @@ describe Timerage do
30
30
  .to yield_successive_args now-duration, now-(duration-1200), now-(duration-2400) }
31
31
  end
32
32
 
33
- let(:now) { Time.now }
33
+ describe "Kernel.Timerage" do
34
+ specify { expect( Timerage(a_time) ).to eq a_time }
35
+
36
+ specify { expect( Timerage(a_time_interval) ).to eq a_time_interval }
37
+ specify { expect( Timerage(a_range_of_times) ).to eq a_time_interval }
38
+
39
+ specify { expect( Timerage(a_time.iso8601(20)) ).to eq a_time }
40
+ specify { expect( Timerage(a_time_interval.iso8601(20)) ).to eq a_time_interval }
41
+
42
+ specify { expect{ Timerage(nil) }.to raise_error TypeError }
43
+ specify { expect{ Timerage(42) }.to raise_error TypeError }
44
+ end
45
+
46
+ let(:now) { Time.now.getutc }
47
+ let(:a_time) { now }
48
+ let(:a_time_interval) { Timerage::TimeInterval.new(now, now+duration, true) }
49
+ let(:a_range_of_times) { a_time_interval.begin...a_time_interval.end }
34
50
  let(:duration) { 3600 }
35
51
  end
36
52
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timerage
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Williams
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-09-03 00:00:00.000000000 Z
12
+ date: 2016-01-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  version: '0'
99
99
  requirements: []
100
100
  rubyforge_project:
101
- rubygems_version: 2.2.2
101
+ rubygems_version: 2.4.5
102
102
  signing_key:
103
103
  specification_version: 4
104
104
  summary: Simple refinement to Range to allow Time or Date as arguments
@@ -106,4 +106,3 @@ test_files:
106
106
  - spec/spec_helper.rb
107
107
  - spec/timerage/time_interval_spec.rb
108
108
  - spec/timerage_spec.rb
109
- has_rdoc: