timerage 2.2.0 → 2.4.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 +4 -4
 - data/lib/timerage/time_interval.rb +49 -12
 - data/lib/timerage/version.rb +1 -1
 - data/lib/timerage.rb +16 -3
 - data/spec/timerage/time_interval_spec.rb +85 -19
 - data/spec/timerage_spec.rb +16 -0
 - metadata +3 -6
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: dd5297580375d5da0f4f8e0c5565cbe0b5e87bb27e01a3f6ab7b53e322f0836b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 1095aa363d5652855d905dfeeecc74291cdb4399c5769ac115c2bed2ad889043
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: c8114be85281560a2d7c08fad17ab9db72809b3a992cf2fff1433e6e4fe3e04673e9fa53bfa93070c4c1b3643bad913c550ca68d11f1ff2f04c2c4b04a9f8188
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 701cd90ba28da27218c23f0346bc15d33c63646bf0a96d8f79ff39dc6a8fe55974fc848b5bca7266bfdf4fe6709fc70448242930e6ffd284f9519b04e40da4bf
         
     | 
| 
         @@ -5,11 +5,34 @@ module Timerage 
     | 
|
| 
       5 
5 
     | 
    
         
             
              class TimeInterval < Range
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
                class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # Returns a new TimeInterval
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # start_time - the beginning of the interval
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # end_time   - the end of the interval
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # exclude_end - whether the end time is excluded from the interval
         
     | 
| 
       8 
13 
     | 
    
         
             
                  def new(*args)
         
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                     
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
                    return from_range(*args) if args.first.respond_to?(:exclude_end?)
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    super
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  # Returns a new TimeInterval
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # time - the beginning or end of the interval
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # duration - the duration of the interval, if negative the
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #   interval will start before`time`
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # exclude_end - whether the end time is excluded from the interval
         
     | 
| 
      
 25 
     | 
    
         
            +
                  def from_time_and_duration(time, duration, exclude_end: true)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if duration >= 0
         
     | 
| 
      
 27 
     | 
    
         
            +
                      new(time, time + duration, exclude_end)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    else
         
     | 
| 
      
 29 
     | 
    
         
            +
                      new(time + duration, time, exclude_end)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  # Returns a new TimeInterval based on the specified range 
         
     | 
| 
      
 34 
     | 
    
         
            +
                  def from_range(range)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    new(range.begin, range.end, range.exclude_end?)
         
     | 
| 
       13 
36 
     | 
    
         
             
                  end
         
     | 
| 
       14 
37 
     | 
    
         
             
                end
         
     | 
| 
       15 
38 
     | 
    
         | 
| 
         @@ -32,12 +55,12 @@ module Timerage 
     | 
|
| 
       32 
55 
     | 
    
         
             
                  end
         
     | 
| 
       33 
56 
     | 
    
         
             
                end
         
     | 
| 
       34 
57 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                def slice( 
     | 
| 
       36 
     | 
    
         
            -
                  time_enumerator( 
     | 
| 
       37 
     | 
    
         
            -
                    .map{| 
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                       
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                def slice(duration)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  time_enumerator(duration)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    .each_cons(2).map { |s_begin, s_end| TimeInterval.new(s_begin, s_end, exclusive_end_slice?(s_end)) }
         
     | 
| 
      
 61 
     | 
    
         
            +
                    .then do |slices|
         
     | 
| 
      
 62 
     | 
    
         
            +
                      slices << TimeInterval.new(slices.last.end, self.end, exclusive_end_slice?(slices.last.end + duration)) if slices.present?
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
       41 
64 
     | 
    
         
             
                end
         
     | 
| 
       42 
65 
     | 
    
         | 
| 
       43 
66 
     | 
    
         
             
                # Return new TimeInterval that is the concatenation of self and
         
     | 
| 
         @@ -54,7 +77,7 @@ module Timerage 
     | 
|
| 
       54 
77 
     | 
    
         
             
                # Returns an ISO8601 interval representation of self
         
     | 
| 
       55 
78 
     | 
    
         
             
                # Takes same args as Time#iso8601
         
     | 
| 
       56 
79 
     | 
    
         
             
                def iso8601(*args)
         
     | 
| 
       57 
     | 
    
         
            -
                  "#{self.begin 
     | 
| 
      
 80 
     | 
    
         
            +
                  "#{self.begin&.iso8601(*args) || ".."}/#{self.end&.iso8601(*args) || ".."}"
         
     | 
| 
       58 
81 
     | 
    
         
             
                end
         
     | 
| 
       59 
82 
     | 
    
         | 
| 
       60 
83 
     | 
    
         
             
                def getutc
         
     | 
| 
         @@ -134,6 +157,10 @@ module Timerage 
     | 
|
| 
       134 
157 
     | 
    
         
             
                    an_obj.respond_to?(:end)
         
     | 
| 
       135 
158 
     | 
    
         
             
                end
         
     | 
| 
       136 
159 
     | 
    
         | 
| 
      
 160 
     | 
    
         
            +
                def exclusive_end_slice?(slice_end)
         
     | 
| 
      
 161 
     | 
    
         
            +
                  !((slice_end > self.end) && !exclude_end?)
         
     | 
| 
      
 162 
     | 
    
         
            +
                end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
       137 
164 
     | 
    
         
             
                def time_enumerator(step)
         
     | 
| 
       138 
165 
     | 
    
         
             
                  next_offset = step * 0
         
     | 
| 
       139 
166 
     | 
    
         | 
| 
         @@ -155,7 +182,17 @@ module Timerage 
     | 
|
| 
       155 
182 
     | 
    
         
             
                #
         
     | 
| 
       156 
183 
     | 
    
         
             
                # Currently this only supports `<begin>/<end>` style time intervals.
         
     | 
| 
       157 
184 
     | 
    
         
             
                def self.iso8601(str, exclusive_end: true)
         
     | 
| 
       158 
     | 
    
         
            -
                   
     | 
| 
      
 185 
     | 
    
         
            +
                  str
         
     | 
| 
      
 186 
     | 
    
         
            +
                    .split("/", 2)
         
     | 
| 
      
 187 
     | 
    
         
            +
                    .tap { |it| fail ArgumentError, "Invalid iso8601 interval: #{str.inspect}" unless it.size == 2 }
         
     | 
| 
      
 188 
     | 
    
         
            +
                    .map {|s|
         
     | 
| 
      
 189 
     | 
    
         
            +
                      if s.strip == ".."
         
     | 
| 
      
 190 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 191 
     | 
    
         
            +
                      else
         
     | 
| 
      
 192 
     | 
    
         
            +
                        Time.iso8601(s)
         
     | 
| 
      
 193 
     | 
    
         
            +
                      end
         
     | 
| 
      
 194 
     | 
    
         
            +
                    }
         
     | 
| 
      
 195 
     | 
    
         
            +
                    .then { |b, e| new(b, e, exclusive_end) }
         
     | 
| 
       159 
196 
     | 
    
         | 
| 
       160 
197 
     | 
    
         
             
                rescue ArgumentError
         
     | 
| 
       161 
198 
     | 
    
         
             
                  raise ArgumentError, "Invalid iso8601 interval: #{str.inspect}"
         
     | 
    
        data/lib/timerage/version.rb
    CHANGED
    
    
    
        data/lib/timerage.rb
    CHANGED
    
    | 
         @@ -16,17 +16,30 @@ module Timerage 
     | 
|
| 
       16 
16 
     | 
    
         
             
                Time.iso8601(str)
         
     | 
| 
       17 
17 
     | 
    
         
             
              end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
              # Returns a new TimeInterval from a time and duration or two times.
         
     | 
| 
      
 20 
     | 
    
         
            +
              #
         
     | 
| 
      
 21 
     | 
    
         
            +
              # signature:
         
     | 
| 
      
 22 
     | 
    
         
            +
              #  Interval(begin_time, end_time, exclude_end: true)
         
     | 
| 
      
 23 
     | 
    
         
            +
              #  Interval(begin_or_end_time, duration, exclude_end: true)
         
     | 
| 
      
 24 
     | 
    
         
            +
              def self.Interval(begin_or_end_time, end_time_or_duration, exclude_end: true)
         
     | 
| 
      
 25 
     | 
    
         
            +
                if end_time_or_duration.respond_to?(:since)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  TimeInterval.from_time_and_duration(begin_or_end_time, end_time_or_duration, exclude_end: exclude_end)
         
     | 
| 
      
 27 
     | 
    
         
            +
                else
         
     | 
| 
      
 28 
     | 
    
         
            +
                  TimeInterval.new(begin_or_end_time, end_time_or_duration, exclude_end)
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
       19 
32 
     | 
    
         
             
              refine Range do
         
     | 
| 
       20 
33 
     | 
    
         
             
                def step(n, &blk)
         
     | 
| 
       21 
34 
     | 
    
         
             
                  if self.begin.kind_of?(Time) || self.begin.kind_of?(Date)
         
     | 
| 
       22 
     | 
    
         
            -
                    Timerage::TimeInterval. 
     | 
| 
      
 35 
     | 
    
         
            +
                    Timerage::TimeInterval.from_range(self).step(n, &blk)
         
     | 
| 
       23 
36 
     | 
    
         
             
                  else
         
     | 
| 
       24 
37 
     | 
    
         
             
                    super
         
     | 
| 
       25 
38 
     | 
    
         
             
                  end
         
     | 
| 
       26 
39 
     | 
    
         
             
                end
         
     | 
| 
       27 
40 
     | 
    
         | 
| 
       28 
41 
     | 
    
         
             
                def to_time_interval
         
     | 
| 
       29 
     | 
    
         
            -
                  Timerage::TimeInterval. 
     | 
| 
      
 42 
     | 
    
         
            +
                  Timerage::TimeInterval.from_range(self)
         
     | 
| 
       30 
43 
     | 
    
         
             
                end
         
     | 
| 
       31 
44 
     | 
    
         
             
              end
         
     | 
| 
       32 
45 
     | 
    
         
             
            end
         
     | 
| 
         @@ -40,7 +53,7 @@ module Kernel 
     | 
|
| 
       40 
53 
     | 
    
         
             
                  thing
         
     | 
| 
       41 
54 
     | 
    
         | 
| 
       42 
55 
     | 
    
         
             
                when ->(x) { x.respond_to? :exclude_end? }
         
     | 
| 
       43 
     | 
    
         
            -
                  Timerage::TimeInterval. 
     | 
| 
      
 56 
     | 
    
         
            +
                  Timerage::TimeInterval.from_range(thing)
         
     | 
| 
       44 
57 
     | 
    
         | 
| 
       45 
58 
     | 
    
         
             
                when ->(x) { x.respond_to? :to_str }
         
     | 
| 
       46 
59 
     | 
    
         
             
                  Timerage.parse_iso8601(thing.to_str)
         
     | 
| 
         @@ -6,18 +6,64 @@ describe Timerage::TimeInterval do 
     | 
|
| 
       6 
6 
     | 
    
         
             
              let(:duration) { 3600 }
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
              describe "creation" do
         
     | 
| 
       9 
     | 
    
         
            -
                specify { expect(described_class.new(now-1 
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                specify { expect(described_class.new(now-1, now, true)) 
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
                specify { expect(described_class.new(now-1.day, now))
         
     | 
| 
      
 10 
     | 
    
         
            +
                  .to be_kind_of(described_class).and eq now-1.day..now }
         
     | 
| 
      
 11 
     | 
    
         
            +
                specify { expect(described_class.new(now-1.day, now, true))
         
     | 
| 
      
 12 
     | 
    
         
            +
                  .to be_kind_of(described_class).and eq now-1.day...now }
         
     | 
| 
      
 13 
     | 
    
         
            +
                specify { expect(described_class.new(now-1.day, now, false ))
         
     | 
| 
      
 14 
     | 
    
         
            +
                  .to be_kind_of(described_class).and eq now-1.day..now }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                it "support new(range) for backwards compatibility" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                  expect(described_class.new((now-1.day)..now)).to eq (now-1.day)..now 
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
       13 
19 
     | 
    
         
             
              end
         
     | 
| 
       14 
20 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
              describe ".iso8601" do
         
     | 
| 
       16 
     | 
    
         
            -
                specify  
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                 
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
              describe ".iso8601" do 
         
     | 
| 
      
 22 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  expect(described_class.iso8601("2001-01-01T00:00:00Z/2001-01-02T00:00:00-06:00"))
         
     | 
| 
      
 24 
     | 
    
         
            +
                    .to be_kind_of described_class 
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  expect{described_class.iso8601("2001-01-01T00:00:00Z")}
         
     | 
| 
      
 29 
     | 
    
         
            +
                    .to raise_error ArgumentError
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  expect(described_class.iso8601("2001-01-01T00:00:00Z/.."))
         
     | 
| 
      
 34 
     | 
    
         
            +
                    .to (be_kind_of described_class)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      .and (have_attributes(begin: Time.parse("2001-01-01T00:00:00Z"), end: nil))
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 39 
     | 
    
         
            +
                  expect(described_class.iso8601("\t2001-01-01T00:00:00Z/..\t"))
         
     | 
| 
      
 40 
     | 
    
         
            +
                    .to (be_kind_of described_class)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      .and (have_attributes(begin: Time.parse("2001-01-01T00:00:00Z"), end: nil))
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  expect(described_class.iso8601(" 2001-01-01T00:00:00Z/.. "))
         
     | 
| 
      
 46 
     | 
    
         
            +
                    .to (be_kind_of described_class)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      .and (have_attributes(begin: Time.parse("2001-01-01T00:00:00Z"), end: nil))
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 51 
     | 
    
         
            +
                  expect(described_class.iso8601("../2001-01-01T00:00:00Z"))
         
     | 
| 
      
 52 
     | 
    
         
            +
                    .to (be_kind_of described_class)
         
     | 
| 
      
 53 
     | 
    
         
            +
                      .and (have_attributes(begin: nil, end: Time.parse("2001-01-01T00:00:00Z")))
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 57 
     | 
    
         
            +
                  expect(described_class.iso8601("\t../2001-01-01T00:00:00Z\t"))
         
     | 
| 
      
 58 
     | 
    
         
            +
                    .to (be_kind_of described_class)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      .and (have_attributes(begin: nil, end: Time.parse("2001-01-01T00:00:00Z")))
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                specify do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  expect(described_class.iso8601(" ../2001-01-01T00:00:00Z "))
         
     | 
| 
      
 64 
     | 
    
         
            +
                    .to (be_kind_of described_class)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      .and (have_attributes(begin: nil, end: Time.parse("2001-01-01T00:00:00Z")))
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
       21 
67 
     | 
    
         
             
              end
         
     | 
| 
       22 
68 
     | 
    
         | 
| 
       23 
69 
     | 
    
         
             
              describe "#getutc" do
         
     | 
| 
         @@ -60,6 +106,18 @@ describe Timerage::TimeInterval do 
     | 
|
| 
       60 
106 
     | 
    
         
             
                        .to eq "#{interval.begin.iso8601(3)}/#{interval.end.iso8601(3)}" }
         
     | 
| 
       61 
107 
     | 
    
         
             
              specify { expect( interval.duration).to eq duration  }
         
     | 
| 
       62 
108 
     | 
    
         | 
| 
      
 109 
     | 
    
         
            +
              context "open-ended intervals" do
         
     | 
| 
      
 110 
     | 
    
         
            +
                subject(:interval) { described_class.new(now-duration, nil) }
         
     | 
| 
      
 111 
     | 
    
         
            +
                specify { expect(interval.iso8601).to eq "#{interval.begin.iso8601}/.." }
         
     | 
| 
      
 112 
     | 
    
         
            +
                specify { expect(interval.iso8601(3)).to eq "#{interval.begin.iso8601(3)}/.." }
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              context "open-start intervals" do
         
     | 
| 
      
 116 
     | 
    
         
            +
                subject(:interval) { described_class.new(nil, now) }
         
     | 
| 
      
 117 
     | 
    
         
            +
                specify { expect(interval.iso8601).to eq "../#{interval.end.iso8601}" }
         
     | 
| 
      
 118 
     | 
    
         
            +
                specify { expect(interval.iso8601(3)).to eq "../#{interval.end.iso8601(3)}" }
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
       63 
121 
     | 
    
         
             
              specify { expect(interval.cover? interval.begin+1..interval.end-1).to be_truthy }
         
     | 
| 
       64 
122 
     | 
    
         
             
              specify { expect(interval.cover? interval.begin...interval.end).to be_truthy }
         
     | 
| 
       65 
123 
     | 
    
         
             
              specify { expect(interval.cover? interval.begin-1..interval.end-1).to be_falsy }
         
     | 
| 
         @@ -86,12 +144,12 @@ describe Timerage::TimeInterval do 
     | 
|
| 
       86 
144 
     | 
    
         
             
                specify { expect( interval & (interval.begin...interval.end) ).to eq interval.begin...interval.end }
         
     | 
| 
       87 
145 
     | 
    
         
             
                specify { expect( interval & (interval.begin...interval.end-1) )
         
     | 
| 
       88 
146 
     | 
    
         
             
                          .to eq interval.begin...interval.end-1 }
         
     | 
| 
       89 
     | 
    
         
            -
                specify { expect( described_class.new(interval.begin 
     | 
| 
       90 
     | 
    
         
            -
                          .to eq described_class.new(interval.begin 
     | 
| 
      
 147 
     | 
    
         
            +
                specify { expect( described_class.new(interval.begin, interval.end-1) & interval )
         
     | 
| 
      
 148 
     | 
    
         
            +
                          .to eq described_class.new(interval.begin,interval.end-1) }
         
     | 
| 
       91 
149 
     | 
    
         
             
              end
         
     | 
| 
       92 
150 
     | 
    
         | 
| 
       93 
151 
     | 
    
         
             
              describe "==" do
         
     | 
| 
       94 
     | 
    
         
            -
                specify { expect( described_class. 
     | 
| 
      
 152 
     | 
    
         
            +
                specify { expect( described_class.from_range(interval) == interval ).to be true }
         
     | 
| 
       95 
153 
     | 
    
         
             
                specify { expect( described_class.new(interval.begin, interval.end) == interval ).to be true }
         
     | 
| 
       96 
154 
     | 
    
         
             
              end
         
     | 
| 
       97 
155 
     | 
    
         | 
| 
         @@ -159,7 +217,7 @@ describe Timerage::TimeInterval do 
     | 
|
| 
       159 
217 
     | 
    
         
             
              end
         
     | 
| 
       160 
218 
     | 
    
         | 
| 
       161 
219 
     | 
    
         
             
              context "exclusive end" do
         
     | 
| 
       162 
     | 
    
         
            -
                subject(:interval) { described_class. 
     | 
| 
      
 220 
     | 
    
         
            +
                subject(:interval) { described_class.from_range(now-duration...now) }
         
     | 
| 
       163 
221 
     | 
    
         | 
| 
       164 
222 
     | 
    
         
             
                specify { expect(interval.exclude_end?).to be true }
         
     | 
| 
       165 
223 
     | 
    
         
             
                specify { expect(interval.cover? now).to be false }
         
     | 
| 
         @@ -187,29 +245,29 @@ describe Timerage::TimeInterval do 
     | 
|
| 
       187 
245 
     | 
    
         
             
              end
         
     | 
| 
       188 
246 
     | 
    
         | 
| 
       189 
247 
     | 
    
         
             
              context "exclusive 0 length interval" do
         
     | 
| 
       190 
     | 
    
         
            -
                subject(:interval) { described_class. 
     | 
| 
      
 248 
     | 
    
         
            +
                subject(:interval) { described_class.from_range(now...now) }
         
     | 
| 
       191 
249 
     | 
    
         
             
                specify { expect{ |b| subject.step(1, &b) }.not_to yield_control }
         
     | 
| 
       192 
250 
     | 
    
         
             
              end
         
     | 
| 
       193 
251 
     | 
    
         | 
| 
       194 
252 
     | 
    
         
             
              context "inclusive 0 length interval" do
         
     | 
| 
       195 
     | 
    
         
            -
                subject(:interval) { described_class. 
     | 
| 
      
 253 
     | 
    
         
            +
                subject(:interval) { described_class.from_range(now..now) }
         
     | 
| 
       196 
254 
     | 
    
         
             
                specify { expect{ |b| subject.step(1, &b) }.to yield_control.once }
         
     | 
| 
       197 
255 
     | 
    
         
             
              end
         
     | 
| 
       198 
256 
     | 
    
         | 
| 
       199 
257 
     | 
    
         
             
              context "includes leap day" do
         
     | 
| 
       200 
     | 
    
         
            -
                subject(:interval) { described_class.new(before_leap_day 
     | 
| 
      
 258 
     | 
    
         
            +
                subject(:interval) { described_class.new(before_leap_day, after_leap_day) }
         
     | 
| 
       201 
259 
     | 
    
         
             
                specify { expect{ |b| subject.step(1.day, &b) }.to yield_control.exactly(3).times }
         
     | 
| 
       202 
260 
     | 
    
         
             
                specify { expect{ |b| subject.step(86_400, &b) }.to yield_control.exactly(3).times }
         
     | 
| 
       203 
261 
     | 
    
         
             
              end
         
     | 
| 
       204 
262 
     | 
    
         | 
| 
       205 
263 
     | 
    
         
             
              context "transition into dst with explicit time zone" do
         
     | 
| 
       206 
     | 
    
         
            -
                subject(:interval) { described_class.new(before_dst 
     | 
| 
      
 264 
     | 
    
         
            +
                subject(:interval) { described_class.new(before_dst, after_dst) }
         
     | 
| 
       207 
265 
     | 
    
         
             
                specify { expect{ |b| subject.step(1.hour, &b) }.to yield_control.exactly(2).times }
         
     | 
| 
       208 
266 
     | 
    
         
             
                specify { expect{ |b| subject.step(3_600, &b) }.to yield_control.exactly(2).times }
         
     | 
| 
       209 
267 
     | 
    
         
             
              end
         
     | 
| 
       210 
268 
     | 
    
         | 
| 
       211 
269 
     | 
    
         
             
              context "transition into dst without explicit time zone" do
         
     | 
| 
       212 
     | 
    
         
            -
                subject(:interval) { described_class.new(before_dst 
     | 
| 
      
 270 
     | 
    
         
            +
                subject(:interval) { described_class.new(before_dst, (before_dst + 1.hour)) }
         
     | 
| 
       213 
271 
     | 
    
         
             
                specify { expect{ |b| subject.step(1.hour, &b) }.to yield_control.exactly(2).times }
         
     | 
| 
       214 
272 
     | 
    
         
             
                specify { expect{ |b| subject.step(3_600, &b) }.to yield_control.exactly(2).times }
         
     | 
| 
       215 
273 
     | 
    
         
             
              end
         
     | 
| 
         @@ -230,6 +288,14 @@ describe Timerage::TimeInterval do 
     | 
|
| 
       230 
288 
     | 
    
         
             
                end
         
     | 
| 
       231 
289 
     | 
    
         
             
              end
         
     | 
| 
       232 
290 
     | 
    
         | 
| 
      
 291 
     | 
    
         
            +
              context "produces complete slices" do
         
     | 
| 
      
 292 
     | 
    
         
            +
                it "slices a range into intervals without missing any time inbetween" do
         
     | 
| 
      
 293 
     | 
    
         
            +
                  range = Timerage(Time.parse("2023-10-31T00:00:00+00:00")...Time.parse("2024-06-30 00:00:00 UTC"))
         
     | 
| 
      
 294 
     | 
    
         
            +
                  slices = range.slice(1.month)
         
     | 
| 
      
 295 
     | 
    
         
            +
                  expect(slices.map(&:duration).sum).to eq range.duration
         
     | 
| 
      
 296 
     | 
    
         
            +
                end
         
     | 
| 
      
 297 
     | 
    
         
            +
              end
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
       233 
299 
     | 
    
         
             
              let(:leap_day) { Time.parse("2016-02-29 12:00:00 UTC") }
         
     | 
| 
       234 
300 
     | 
    
         
             
              let(:before_leap_day) { leap_day - 1.day }
         
     | 
| 
       235 
301 
     | 
    
         
             
              let(:after_leap_day) { leap_day + 1.day}
         
     | 
    
        data/spec/timerage_spec.rb
    CHANGED
    
    | 
         @@ -17,6 +17,22 @@ describe Timerage do 
     | 
|
| 
       17 
17 
     | 
    
         
             
                            .to be_kind_of Time }
         
     | 
| 
       18 
18 
     | 
    
         
             
                end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
                describe ".Interval" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  let(:t) { Time.now }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  let(:one_day) { 1.day }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  specify { expect(described_class.Interval(t, 1.day)).to eq t...(t+1.day) }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  specify { expect(described_class.Interval(t, 1.day, exclude_end: false)).to eq(t..(t+1.day)) }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  specify { expect(described_class.Interval(t, -1.day)).to eq((t-1.day)...t) }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  specify { expect(described_class.Interval(t, -1.day, exclude_end: false)).to eq((t+-1.day)..t) }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  specify { expect{ described_class.Interval(t, (t+1.day)).to eq(t...(t+1.day)) } }
         
     | 
| 
      
 31 
     | 
    
         
            +
                  specify { expect{ described_class.Interval(t, (t+1.day), exclude_end: false).to eq(t..(t+1.day)) } }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  specify { expect{ described_class.Interval(t..(t+1.day)).to eq(t..(t+1.day)) } }
         
     | 
| 
      
 34 
     | 
    
         
            +
                end 
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       20 
36 
     | 
    
         
             
                context "interval include end" do
         
     | 
| 
       21 
37 
     | 
    
         
             
                  specify { expect{|b| range.step(1200, &b) }
         
     | 
| 
       22 
38 
     | 
    
         
             
                      .to yield_successive_args now-duration, now-(duration-1200), now-(duration-2400), now }
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,15 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: timerage
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.4.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Peter Williams
         
     | 
| 
       8 
8 
     | 
    
         
             
            - Chris Schneider
         
     | 
| 
       9 
     | 
    
         
            -
            autorequire:
         
     | 
| 
       10 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 1980-01-02 00:00:00.000000000 Z
         
     | 
| 
       13 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
14 
     | 
    
         
             
              name: bundler
         
     | 
| 
         @@ -96,7 +95,6 @@ homepage: '' 
     | 
|
| 
       96 
95 
     | 
    
         
             
            licenses:
         
     | 
| 
       97 
96 
     | 
    
         
             
            - MIT
         
     | 
| 
       98 
97 
     | 
    
         
             
            metadata: {}
         
     | 
| 
       99 
     | 
    
         
            -
            post_install_message:
         
     | 
| 
       100 
98 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       101 
99 
     | 
    
         
             
            require_paths:
         
     | 
| 
       102 
100 
     | 
    
         
             
            - lib
         
     | 
| 
         @@ -111,8 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       111 
109 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       112 
110 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       113 
111 
     | 
    
         
             
            requirements: []
         
     | 
| 
       114 
     | 
    
         
            -
            rubygems_version: 3.2 
     | 
| 
       115 
     | 
    
         
            -
            signing_key:
         
     | 
| 
      
 112 
     | 
    
         
            +
            rubygems_version: 3.7.2
         
     | 
| 
       116 
113 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       117 
114 
     | 
    
         
             
            summary: Simple refinement to Range to allow Time or Date as arguments
         
     | 
| 
       118 
115 
     | 
    
         
             
            test_files:
         
     |