time_chunk 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,102 @@
1
+ # time_chunk
2
+
3
+ Iterate over a time range in discrete chunks.
4
+
5
+ ## examples
6
+
7
+ ### Enumerate each hour in a day.
8
+ ```ruby
9
+ TimeChunk.each_hour('2013-05-15T00:00:00Z'..'2013-05-15T05:59:59Z') do |range|
10
+ puts range.inspect
11
+ end
12
+ ```
13
+
14
+ Strings are parsed into `Time` instances automatically.
15
+
16
+ ```
17
+ 2013-05-15 00:00:00 UTC..2013-05-15 00:59:59 UTC
18
+ 2013-05-15 01:00:00 UTC..2013-05-15 01:59:59 UTC
19
+ 2013-05-15 02:00:00 UTC..2013-05-15 02:59:59 UTC
20
+ 2013-05-15 03:00:00 UTC..2013-05-15 03:59:59 UTC
21
+ 2013-05-15 04:00:00 UTC..2013-05-15 04:59:59 UTC
22
+ 2013-05-15 05:00:00 UTC..2013-05-15 05:59:59 UTC
23
+ ```
24
+
25
+ ### Enumerate a range of days.
26
+
27
+ ```ruby
28
+ TimeChunk.each_day('2013-05-15T00:00:00Z'..'2013-05-20T23:59:59Z') do |range|
29
+ puts range.inspect
30
+ end
31
+ ```
32
+
33
+ ```
34
+ 2013-05-15 00:00:00 UTC..2013-05-15 23:59:59 UTC
35
+ 2013-05-16 00:00:00 UTC..2013-05-16 23:59:59 UTC
36
+ 2013-05-17 00:00:00 UTC..2013-05-17 23:59:59 UTC
37
+ 2013-05-18 00:00:00 UTC..2013-05-18 23:59:59 UTC
38
+ 2013-05-19 00:00:00 UTC..2013-05-19 23:59:59 UTC
39
+ 2013-05-20 00:00:00 UTC..2013-05-20 23:59:59 UTC
40
+ ```
41
+
42
+ If you supply a range of `Date`s instead of `Time` instances or strings,
43
+ `each_day` will yield `Date` instances instead of a time range.
44
+
45
+ ```ruby
46
+ start = Date.parse '2013-05-15'
47
+ finish = Date.parse '2013-05-20'
48
+ TimeChunk.each_day(start..finish) do |d|
49
+ puts d.to_s
50
+ end
51
+ ```
52
+
53
+ ```
54
+ 2013-05-15
55
+ 2013-05-16
56
+ 2013-05-17
57
+ 2013-05-18
58
+ 2013-05-19
59
+ 2013-05-20
60
+ ```
61
+
62
+
63
+ ### Enumerate using any chunk of time
64
+
65
+ ```ruby
66
+ TimeChunk.iterate('2013-05-15T00:00:00Z'..'2013-05-15T23:59:59Z', 6.hours) do |range|
67
+ puts range.inspect
68
+ end
69
+ ```
70
+
71
+ ```
72
+ 2013-05-15 00:00:00 UTC..2013-05-15 05:59:59 UTC
73
+ 2013-05-15 06:00:00 UTC..2013-05-15 11:59:59 UTC
74
+ 2013-05-15 12:00:00 UTC..2013-05-15 17:59:59 UTC
75
+ 2013-05-15 18:00:00 UTC..2013-05-15 23:59:59 UTC
76
+ ```
77
+
78
+ This example uses the `6.hours` convenience method from `ActiveSupport`, but you
79
+ can supply any number of seconds.
80
+
81
+ ### Enumerate using any chunk of days
82
+
83
+ `iterate_days` is the same as `iterate` except that the step size is specified
84
+ in days instead of seconds.
85
+
86
+ ```ruby
87
+ start = Date.parse '2013-05-01'
88
+ finish = Date.parse '2013-05-31'
89
+ TimeChunk.iterate_days(start..finish, 5) do |range|
90
+ puts "#{range.begin.to_s} .. #{range.end.to_s}"
91
+ end
92
+ ```
93
+
94
+ ```
95
+ 2013-05-01 .. 2013-05-05
96
+ 2013-05-06 .. 2013-05-10
97
+ 2013-05-11 .. 2013-05-15
98
+ 2013-05-16 .. 2013-05-20
99
+ 2013-05-21 .. 2013-05-25
100
+ 2013-05-26 .. 2013-05-30
101
+ 2013-05-31 .. 2013-05-31
102
+ ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 1.0.0
@@ -2,20 +2,33 @@ require 'time'
2
2
 
3
3
  module TimeChunk
4
4
 
5
- def self.each_day(range)
5
+ def self.each_minute(range)
6
6
  # &Proc.new : return a proc containing the block passed to the method
7
7
  # http://www.ruby-doc.org/core-1.9.3/Proc.html#method-c-new
8
- iterate(range, 86400, &Proc.new)
8
+ iterate(range, 60, &Proc.new)
9
9
  end
10
10
 
11
11
  def self.each_hour(range)
12
12
  iterate(range, 3600, &Proc.new)
13
13
  end
14
14
 
15
- def self.each_minute(range)
16
- iterate(range, 60, &Proc.new)
15
+ def self.each_day(range)
16
+ # if we're given a date range, yield individual dates instead of a range.
17
+ if range.begin.is_a?(Date)
18
+ iterate(range, 86400) {|chunk| yield chunk.begin }
19
+ # otherwise yield a range like all other methods do.
20
+ else
21
+ iterate(range, 86400, &Proc.new)
22
+ end
17
23
  end
18
24
 
25
+ # Iterate over any date or time range, yielding a range of no more than
26
+ # step_size duration (in seconds.) The final yielded range may be smaller than
27
+ # step_size if the total range is not a perfect multiple of the step_size.
28
+ #
29
+ # String arguments will be parsed into Times, and yield Time ranges.
30
+ # Date ranges will yield Date ranges. Note that step_size is always in seconds
31
+ # even for date ranges. If this feels weird, see iterate_days instead.
19
32
  def self.iterate(range, step_size)
20
33
  if range.first.is_a?(Time)
21
34
  begin_at = range.first
@@ -42,4 +55,14 @@ module TimeChunk
42
55
  yield current_begin..current_end
43
56
  end while current_end < end_at
44
57
  end
45
- end
58
+
59
+ # Same as iterate, but with step_size specified in days instead of seconds.
60
+ def self.iterate_days(range, step_size)
61
+ if ! range.begin.is_a?(Date) || ! range.end.is_a?(Date)
62
+ raise ArgumentError, "iterate_days requires a range of dates."
63
+ end
64
+
65
+ iterate(range, step_size*86400, &Proc.new)
66
+ end
67
+
68
+ end
@@ -105,17 +105,61 @@ describe TimeChunk do
105
105
  end
106
106
  end
107
107
 
108
- it "should iterate over each_day" do
109
- TimeChunk.each_day('2013-01-01T00:00:00Z'..'2013-01-04T23:59:59Z') do |range|
110
- @calls << range
108
+ describe "each_day" do
109
+ it "should yield time ranges when given string arguments" do
110
+ TimeChunk.each_day('2013-01-01T00:00:00Z'..'2013-01-04T23:59:59Z') do |range|
111
+ @calls << range
112
+ end
113
+
114
+ @calls.should eq [
115
+ (t('2013-01-01T00:00:00Z')..t('2013-01-01T23:59:59Z')),
116
+ (t('2013-01-02T00:00:00Z')..t('2013-01-02T23:59:59Z')),
117
+ (t('2013-01-03T00:00:00Z')..t('2013-01-03T23:59:59Z')),
118
+ (t('2013-01-04T00:00:00Z')..t('2013-01-04T23:59:59Z')),
119
+ ]
111
120
  end
112
121
 
113
- @calls.should eq [
114
- (t('2013-01-01T00:00:00Z')..t('2013-01-01T23:59:59Z')),
115
- (t('2013-01-02T00:00:00Z')..t('2013-01-02T23:59:59Z')),
116
- (t('2013-01-03T00:00:00Z')..t('2013-01-03T23:59:59Z')),
117
- (t('2013-01-04T00:00:00Z')..t('2013-01-04T23:59:59Z')),
118
- ]
122
+ it "should yield date instances when given date range arguments" do
123
+ start = Date.parse('2013-05-15')
124
+ finish = Date.parse('2013-05-20')
125
+
126
+ TimeChunk.each_day(start..finish) {|date| @calls << date}
127
+
128
+ expected = ["2013-05-15", "2013-05-16", "2013-05-17", "2013-05-18", "2013-05-19", "2013-05-20"]
129
+ @calls.map(&:to_s).should eq expected
130
+ end
131
+
132
+ it "should raise an error if the start is after the finish" do
133
+ finish = Date.parse('2013-05-15')
134
+ start = Date.parse('2013-05-20')
135
+
136
+ expect {
137
+ TimeChunk.each_day(start..finish) {|date| @calls << date}
138
+ }.to raise_error ArgumentError, "Given range's begin (2013-05-20T05:00:00Z) is after its end (2013-05-15T05:00:00Z)."
139
+
140
+ end
141
+ end
142
+
143
+ describe "iterate_days" do
144
+ it "should iterate in chunks of the given number of days" do
145
+ start = Date.parse('2013-05-01')
146
+ finish = Date.parse('2013-05-31')
147
+
148
+ TimeChunk.iterate_days(start..finish, 5) do |range|
149
+ @calls << [range.first.to_s, range.last.to_s]
150
+ end
151
+
152
+ expected = [
153
+ ["2013-05-01", "2013-05-05"],
154
+ ["2013-05-06", "2013-05-10"],
155
+ ["2013-05-11", "2013-05-15"],
156
+ ["2013-05-16", "2013-05-20"],
157
+ ["2013-05-21", "2013-05-25"],
158
+ ["2013-05-26", "2013-05-30"],
159
+ ["2013-05-31", "2013-05-31"]
160
+ ]
161
+ @calls.should eq expected
162
+ end
119
163
  end
120
164
 
121
165
  it "should iterate over each_hour" do
@@ -5,16 +5,16 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "time_chunk"
8
- s.version = "0.1.0"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alex Dean"]
12
- s.date = "2013-03-08"
12
+ s.date = "2013-05-17"
13
13
  s.description = "Iterate over time ranges in discrete chunks."
14
14
  s.email = "alex@crackpot.org"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
- "README.rdoc"
17
+ "README.md"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  "Gemfile",
23
23
  "Gemfile.lock",
24
24
  "LICENSE.txt",
25
- "README.rdoc",
25
+ "README.md",
26
26
  "Rakefile",
27
27
  "VERSION",
28
28
  "lib/time_chunk.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_chunk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-08 00:00:00.000000000 Z
12
+ date: 2013-05-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -81,14 +81,14 @@ executables: []
81
81
  extensions: []
82
82
  extra_rdoc_files:
83
83
  - LICENSE.txt
84
- - README.rdoc
84
+ - README.md
85
85
  files:
86
86
  - .document
87
87
  - .rspec
88
88
  - Gemfile
89
89
  - Gemfile.lock
90
90
  - LICENSE.txt
91
- - README.rdoc
91
+ - README.md
92
92
  - Rakefile
93
93
  - VERSION
94
94
  - lib/time_chunk.rb
@@ -110,7 +110,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
110
  version: '0'
111
111
  segments:
112
112
  - 0
113
- hash: -3932107950510678518
113
+ hash: -197955871905249564
114
114
  required_rubygems_version: !ruby/object:Gem::Requirement
115
115
  none: false
116
116
  requirements:
@@ -1,19 +0,0 @@
1
- = time_chunk
2
-
3
- Iterate over a time range in discrete chunks.
4
-
5
- == Contributing to time_chunk
6
-
7
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
- * Fork the project.
10
- * Start a feature/bugfix branch.
11
- * Commit and push until you are happy with your contribution.
12
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2013 Alex Dean. See LICENSE.txt for
18
- further details.
19
-