rounding 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4d99f27fefc944b1bcc3a0a47db81474752063b
4
+ data.tar.gz: 4a189b36da5764596dc6ab7aafab2ebecc1ecdd8
5
+ SHA512:
6
+ metadata.gz: 27f3843718eeedbd3729d67dd769342b5e862345a98bdac80b7a1c60eaf074b06018c319658cfa55f76dfa03efc0ea6795deafed07d1f4ca8e86a516e8ce3e24
7
+ data.tar.gz: e53bc824025c5c8c3f78474678a0e738b93d3513f0e6c77eae8735d6d4009301c839413101e62c984c15e3bfc78ccb0cdc308577a2f8403ebf6c498f5c4ee343
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ - 2.0.0
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rounding.gemspec
4
+ gemspec
@@ -0,0 +1,3 @@
1
+ Rounding is dedicated to the public domain by its author, Brian Hempel. No rights are reserved. No restrictions are placed on the use of Rounding. That freedom also means, of course, that no warrenty of fitness is claimed; use Rounding at your own risk.
2
+
3
+ Public domain dedication is explained by the CC0 1.0 summary (and only the summary) at https://creativecommons.org/publicdomain/zero/1.0/
@@ -0,0 +1,239 @@
1
+ # Rounding
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rounding.svg)](http://badge.fury.io/rb/rounding)
4
+ [![Build Status](https://travis-ci.org/brianhempel/rounding.svg)](https://travis-ci.org/brianhempel/rounding)
5
+
6
+ Rounding allows you to round any numeric value to anything you want. You can also round a Time to, for example, the nearest 15 minutes.
7
+
8
+ Some quick examples:
9
+
10
+ ```ruby
11
+ require 'rounding'
12
+
13
+ 26.round_to(10) # => 30
14
+ 8.77.floor_to(2.5) # => 7.5
15
+ 101.ceil_to(25) # => 125
16
+ Time.now.round_to(15.minutes) # => 2014-09-08 22:30:00 -0400
17
+ ```
18
+
19
+ Rounding is compatible with ActiveSupport's Time extensions, but also works fine without ActiveSupport.
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'rounding'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ $ bundle
32
+
33
+ Or install it yourself like so:
34
+
35
+ $ gem install rounding
36
+
37
+ ## Usage
38
+
39
+ First, require the gem.
40
+
41
+ ```ruby
42
+ require 'rounding'
43
+ ```
44
+
45
+ Rounding adds three methods to all Numeric objects: `round_to`, `floor_to`, and `ceil_to`.
46
+
47
+ `round_to` rounds to the nearest multiple of the chosen step.
48
+
49
+ ```ruby
50
+ 254.round_to(100) # => 300
51
+ 1.4.round_to(3) # => 0
52
+ 1.5.round_to(3) # => 3
53
+ 1.6.round_to(3) # => 3
54
+ -8.round_to(3) # => -9
55
+ ```
56
+
57
+ `floor_to` rounds down to a multiple of the chosen step.
58
+
59
+ ```ruby
60
+ 299.floor_to(100) # => 200
61
+ 1.81.floor_to(0.5) # => 1.5
62
+ 60.floor_to(15) # => 60
63
+ -8.floor_to(3) # => -9
64
+ ```
65
+
66
+ `ceil_to` rounds up to a multiple of the chosen step.
67
+
68
+ ```ruby
69
+ 201.ceil_to(100) # => 300
70
+ 1.71.ceil_to(0.5) # => 2.0
71
+ 60.ceil_to(15) # => 60
72
+ -8.ceil_to(3) # => -6
73
+ ```
74
+
75
+ For all methods, the class of the result depends on the input arguments.
76
+
77
+ ```ruby
78
+ 16.round_to(10) # => 20
79
+ 16.round_to(10.0) # => 20.0
80
+ 16.0.round_to(10) # => 20
81
+ 16.0.round_to(10.0) # => 20.0
82
+ ```
83
+
84
+ If you need super-precise rounding, use Rationals.
85
+
86
+ ```ruby
87
+ time = Time.now.to_f # => 1410230400.4758651
88
+ time.round_to(0.0001) # => 1410230400.4759002 # Float is not exact
89
+ time.round_to(1.to_r/10_000) # => (14102304004759/10000)
90
+ ```
91
+
92
+ You can provide an offset if you want the multiples to start counting from something other than zero.
93
+
94
+ ```ruby
95
+ # rounding by 10 with an offset of 3 will round to 3, 13, 23, 33, 43, 53 etc.
96
+ 18.round_to(10, 3) # => 23
97
+ 18.floor_to(10, 3) # => 13
98
+ 18.ceil_to(10, 3) # => 23
99
+ 0.ceil_to(10, 3) # => 3
100
+ 0.floor_to(10, 3) # => -7
101
+ ```
102
+
103
+ ### Usage with Time and TimeWithZone objects
104
+
105
+ You can round times to whatever you like. The units are seconds.
106
+
107
+ ```ruby
108
+ time = Time.now # => 2014-09-08 22:57:34 -0400
109
+
110
+ # to next 10 minutes...
111
+ time.ceil_to(60*10) # => 2014-09-08 23:00:00 -0400
112
+
113
+ # to previous 15 minutes...
114
+ time.floor_to(60*15) # => 2014-09-08 22:45:00 -0400
115
+
116
+ # to nearest hour...
117
+ time.round_to(60*60) # => 2014-09-08 23:00:00 -0400
118
+ ```
119
+
120
+ If you need to round to something smaller than one second, use rationals to avoid precision loss.
121
+
122
+ ```ruby
123
+ time.xmlschema(6) # => "2014-09-08T22:57:34.433197-04:00"
124
+ time.round_to(1.to_r/1000).xmlschema(6) # => "2014-09-08T22:57:34.433000-04:00"
125
+ ```
126
+
127
+ Times are rounded in their time zone.
128
+
129
+ ```ruby
130
+ ONE_DAY = 60*60*24
131
+
132
+ time.round_to(ONE_DAY) # => 2014-09-09 00:00:00 -0400
133
+ ```
134
+
135
+ If you want to round in UTC, use `round_in_utc_to`, `floor_in_utc_to`, and `ceil_in_utc_to`.
136
+
137
+ ```ruby
138
+ time.round_in_utc_to(ONE_DAY) # => 2014-09-08 20:00:00 -0400
139
+ time.floor_in_utc_to(ONE_DAY) # => 2014-09-08 20:00:00 -0400
140
+ time.ceil_in_utc_to(ONE_DAY) # => 2014-09-09 20:00:00 -0400
141
+ ```
142
+
143
+ If you want the result in UTC instead of the original time zone, convert to UTC first.
144
+
145
+ ```ruby
146
+ time.dup.utc.round_to(ONE_DAY) # => 2014-09-09 00:00:00 UTC
147
+ ```
148
+
149
+ You can provide a base value to round around.
150
+
151
+ ```ruby
152
+ # round to Wednesday
153
+
154
+ wednesday = Time.parse("2014-09-03 -0400")
155
+ one_week = ONE_DAY*7
156
+
157
+ time.round_to(one_week, wednesday) # => 2014-09-10 00:00:00 -0400
158
+ ```
159
+
160
+ If you've loaded ActiveSupport, you can use ActiveSupport's duration sugar to write expressions like `1.day` instead of `60*60*24`.
161
+
162
+ ```ruby
163
+ require "active_support/time"
164
+
165
+ time.round_to(1.day) # => 2014-09-09 00:00:00 -0400
166
+ time.round_to(5.minutes) # => 2014-09-08 23:00:00 -0400
167
+ ```
168
+
169
+ ActiveSupport's TimeWithZone is fully supported.
170
+
171
+ ```ruby
172
+ time = ActiveSupport::TimeZone["Bern"].parse("2014-09-08 22:57:34 -0400")
173
+ # => Tue, 09 Sep 2014 04:57:34 CEST +02:00
174
+
175
+ time.round_to(12.hours) # => Tue, 09 Sep 2014 00:00:00 CEST +02:00
176
+ time.round_to(12.hours).class # => ActiveSupport::TimeWithZone
177
+ ```
178
+
179
+ For rounding to the month or year, you should use ActiveSupport's time extensions. Months and years have variable numbers of days and thus are not correctly supported by Rounding.
180
+
181
+ ### Usage with DateTime objects
182
+
183
+ Rounding also works with DateTime objects. Unlike Time objects, you will be rounding to a chosen number of days rather than a number of seconds.
184
+
185
+ ```ruby
186
+ require 'date'
187
+
188
+ date_time = DateTime.now # => Mon, 08 Sep 2014 23:46:16 -0400
189
+
190
+ date_time.round_to(1) # => Tue, 09 Sep 2014 00:00:00 -0400
191
+ ```
192
+
193
+ Use rational fractions of a day to round to the desired unit.
194
+
195
+ ```ruby
196
+ # 1 hour
197
+ date_time.floor_to(1.to_r/24) # => Mon, 08 Sep 2014 23:00:00 -0400
198
+ # 5 minutes
199
+ date_time.floor_to(1.to_r/24/60*5) # => Mon, 08 Sep 2014 23:45:00 -0400
200
+ ```
201
+
202
+ ActiveSupport's duration helpers can save you from writing ugly expressions.
203
+
204
+ ```ruby
205
+ date_time.floor_to(1.hour) # => Mon, 08 Sep 2014 23:00:00 -0400
206
+ date_time.floor_to(5.minutes) # => Mon, 08 Sep 2014 23:45:00 -0400
207
+ ```
208
+
209
+ The `round_in_utc_to`, `floor_in_utc_to`, and `ceil_in_utc_to` are also available on DateTime objects. However, to round around the UNIX epoch in your time zone, you will need to provide a custom center for rounding.
210
+
211
+ ```ruby
212
+ fortnight = 2.weeks
213
+
214
+ # UNIX epoch is a Thursday in UTC, Julian epoch is a Monday
215
+
216
+ date_time.round_to(fortnight) # => Mon, 15 Sep 2014 00:00:00 -0400
217
+ date_time.round_in_utc_to(fortnight) # => Wed, 10 Sep 2014 20:00:00 -0400
218
+
219
+ unix_epoch_minus_four = DateTime.new(1970, 1, 1, 0, 0, 0, "-0400")
220
+ date_time.round_to(fortnight, unix_epoch_minus_four) # => Thu, 11 Sep 2014 00:00:00 -0400
221
+ ```
222
+
223
+ Happy rounding!
224
+
225
+ ## License
226
+
227
+ Rounding is dedicated to the public domain by its author, Brian Hempel. No rights are reserved. No restrictions are placed on the use of Rounding. That freedom also means, of course, that no warrenty of fitness is claimed; use Rounding at your own risk.
228
+
229
+ Public domain dedication is explained by the CC0 1.0 summary (and only the summary) at https://creativecommons.org/publicdomain/zero/1.0/
230
+
231
+ ## Contributing
232
+
233
+ 1. Fork it ( https://github.com/brianhempel/rounding/fork )
234
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
235
+ 3. Run the tests with `rspec`
236
+ 4. There is also a `bin/console` command to load up a REPL for playing around
237
+ 5. Commit your changes (`git commit -am 'Add some feature'`)
238
+ 6. Push to the branch (`git push origin my-new-feature`)
239
+ 7. Create a new Pull Request
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default => :spec
4
+
5
+ desc "Run the tests"
6
+ task :spec do
7
+ exec "bundle exec rspec"
8
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require "rounding"
5
+ require "active_support/time"
6
+ require "pry"
7
+
8
+ TIME_ZONE = ActiveSupport::TimeZone["Bern"]
9
+ AST = ActiveSupport::TimeZone["Kuwait"] # something without DST
10
+
11
+ binding.pry
@@ -0,0 +1,5 @@
1
+ require "rounding/version"
2
+ require "rounding/core_ext/numeric"
3
+ require "rounding/core_ext/time"
4
+ require "rounding/core_ext/date_time"
5
+ require "rounding/active_support_ext/time_with_zone"
@@ -0,0 +1,7 @@
1
+ require 'rounding/time_extensions'
2
+
3
+ module ActiveSupport
4
+ class TimeWithZone
5
+ include Rounding::TimeExtensions
6
+ end
7
+ end
@@ -0,0 +1,53 @@
1
+ require 'rounding/time_extensions'
2
+
3
+ class DateTime < Date
4
+ include Rounding::TimeExtensions
5
+
6
+ UNIX_EPOCH = 2440588
7
+
8
+ raise "DateTime#to_r already defined! Definitions may conflict" if method_defined?(:to_r)
9
+ def to_r
10
+ no_offset = new_offset(0)
11
+ no_offset.jd + no_offset.day_fraction
12
+ end
13
+
14
+ def floor_to(step, around=-offset)
15
+ step = decode_duration(step)
16
+ around = decode_duration(around)
17
+ super(step, around)
18
+ end
19
+
20
+ def ceil_to(step, around=-offset)
21
+ step = decode_duration(step)
22
+ around = decode_duration(around)
23
+ super(step, around)
24
+ end
25
+
26
+ def round_to(step, around=-offset)
27
+ step = decode_duration(step)
28
+ around = decode_duration(around)
29
+ super(step, around)
30
+ end
31
+
32
+ def floor_in_utc_to(step)
33
+ floor_to(step, UNIX_EPOCH)
34
+ end
35
+
36
+ def ceil_in_utc_to(step)
37
+ ceil_to(step, UNIX_EPOCH)
38
+ end
39
+
40
+ def round_in_utc_to(step)
41
+ round_to(step, UNIX_EPOCH)
42
+ end
43
+
44
+ private
45
+
46
+ def decode_duration(value)
47
+ if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === value
48
+ value.to_r / 1.day.to_r
49
+ else
50
+ value
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,18 @@
1
+ class Numeric
2
+ def floor_to(step, around=0)
3
+ whole, _ = (self - around).divmod(step)
4
+ whole * step + around
5
+ end
6
+
7
+ def ceil_to(step, around=0)
8
+ whole, remainder = (self - around).divmod(step)
9
+ num_steps = remainder > 0 ? whole + 1 : whole
10
+ num_steps * step + around
11
+ end
12
+
13
+ def round_to(step, around=0)
14
+ whole, remainder = (self - around).divmod(step)
15
+ num_steps = remainder*2 >= step ? whole + 1 : whole
16
+ num_steps * step + around
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ require 'rounding/time_extensions'
2
+
3
+ class Time
4
+ include Rounding::TimeExtensions
5
+ end
@@ -0,0 +1,34 @@
1
+ module Rounding::TimeExtensions
2
+ def floor_to(step, around=-utc_offset)
3
+ around = around.to_r
4
+ rational_self = self.to_r
5
+ difference = rational_self - rational_self.floor_to(step, around)
6
+ self - difference
7
+ end
8
+
9
+ def ceil_to(step, around=-utc_offset)
10
+ around = around.to_r
11
+ rational_self = self.to_r
12
+ difference = rational_self - rational_self.ceil_to(step, around)
13
+ self - difference
14
+ end
15
+
16
+ def round_to(step, around=-utc_offset)
17
+ around = around.to_r
18
+ rational_self = self.to_r
19
+ difference = rational_self - rational_self.round_to(step, around)
20
+ self - difference
21
+ end
22
+
23
+ def floor_in_utc_to(step)
24
+ floor_to(step, 0)
25
+ end
26
+
27
+ def ceil_in_utc_to(step)
28
+ ceil_to(step, 0)
29
+ end
30
+
31
+ def round_in_utc_to(step)
32
+ round_to(step, 0)
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Rounding
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rounding/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rounding"
8
+ spec.version = Rounding::VERSION
9
+ spec.authors = ["Brian Hempel"]
10
+ spec.email = ["plasticchicken@gmail.com"]
11
+ spec.summary = %q{Floor/nearest/ceiling rounding by arbitrary steps for Integers, Floats, Times, TimeWithZones, and DateTimes.}
12
+ spec.description = spec.summary
13
+ spec.homepage = "https://github.com/brianhempel/rounding"
14
+ spec.license = "Public Domain"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ # spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "activesupport"
25
+ end
@@ -0,0 +1,318 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "rounding"
3
+ require "date"
4
+ require "active_support/time"
5
+
6
+ TIME_ZONE = ActiveSupport::TimeZone["Bern"]
7
+ AST = ActiveSupport::TimeZone["Kuwait"] # something without DST
8
+
9
+ ONE_DAY = 60*60*24
10
+ ONE_WEEK = ONE_DAY * 7
11
+ WEDNESDAY = Time.new(2014, 9, 3, 0, 0, 0, "-06:00")
12
+
13
+ describe "Rounding" do
14
+
15
+ def self.it_rounds_correctly(method, input, step, expected)
16
+ it "should be #{expected.inspect} for #{input.class} #{input.inspect} step by #{step.inspect}" do
17
+ result = input.send(method, step)
18
+ expect(result).to eq(expected)
19
+ end
20
+
21
+ it "should be class #{expected.class.inspect} for #{input.inspect} step by #{step.inspect}" do
22
+ result = input.send(method, step)
23
+ expect(result.class).to eq(expected.class)
24
+ end
25
+
26
+ if input.respond_to?(:utc_offset)
27
+ it "should have utc_offset #{expected.utc_offset.inspect} for #{input.inspect} step by #{step.inspect}" do
28
+ result_utc_offset = input.send(method, step).utc_offset
29
+ expect(result_utc_offset).to eq(expected.utc_offset)
30
+ end
31
+ end
32
+
33
+ if input.respond_to?(:offset)
34
+ it "should have offset #{expected.offset.inspect} for #{input.inspect} step by #{step.inspect}" do
35
+ result_offset = input.send(method, step).offset
36
+ expect(result_offset).to eq(expected.offset)
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#floor_to" do
42
+ FLOOR_TO_EXPECTATIONS = {
43
+ [3, 2] => 2,
44
+ [2, 2] => 2,
45
+ [0, 2] => 0,
46
+ [-1, 2] => -2,
47
+ [-2, 2] => -2,
48
+ [104, 5] => 100,
49
+ [3.0, 2] => 2,
50
+ [2.0, 2] => 2,
51
+ [0.0, 2] => 0,
52
+ [-1.0, 2] => -2,
53
+ [-2.0, 2] => -2,
54
+ [104.0, 5] => 100,
55
+ [3, 2.5] => 2.5,
56
+ [-3, 2.5] => -5.0,
57
+ [105, 2.5] => 105.0,
58
+ [4.9, 2.5] => 2.5,
59
+ [Time.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-04:00"),
60
+ [Time.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-05:00"),
61
+ [Time.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-06:00"),
62
+ [Time.new(2014, 9, 5, 11, 59, 59, "-07:00"), ONE_DAY] => Time.new(2014, 9, 5, 0, 0, 00, "-07:00"),
63
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY] => Time.new(2014, 9, 5, 0, 0, 00, "-08:00"),
64
+ [Time.new(2014, 9, 5, 12, 0, 01, "-09:00"), ONE_DAY] => Time.new(2014, 9, 5, 0, 0, 00, "-09:00"),
65
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY*365] => Time.new(2013, 12, 21, 0, 0, 00, "-08:00"),
66
+ [Time.at(1409955065, 284499), 1.to_r/1000] => Time.at(1409955065, 284000),
67
+ [Time.at(1409955065, 284500), 1.to_r/1000] => Time.at(1409955065, 284000),
68
+ [Time.at(1409955065, 284501), 1.to_r/1000] => Time.at(1409955065, 284000),
69
+ [TIME_ZONE.local(2014, 9, 5, 18, 8, 30), 60] => TIME_ZONE.local(2014, 9, 5, 18, 8, 00),
70
+ [DateTime.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-04:00"),
71
+ [DateTime.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-05:00"),
72
+ [DateTime.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-06:00"),
73
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1] => DateTime.new(2014, 9, 5, 0, 0, 00, "-07:00"),
74
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1] => DateTime.new(2014, 9, 5, 0, 0, 00, "-08:00"),
75
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1] => DateTime.new(2014, 9, 5, 0, 0, 00, "-09:00"),
76
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1.day] => DateTime.new(2014, 9, 5, 0, 0, 00, "-07:00"),
77
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1.day] => DateTime.new(2014, 9, 5, 0, 0, 00, "-08:00"),
78
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1.day] => DateTime.new(2014, 9, 5, 0, 0, 00, "-09:00"),
79
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 365] => DateTime.new(2014, 6, 6, 0, 0, 00, "-08:00"), # rounds around Julian epoch: -4712-01-01 00:00:00
80
+ [DateTime.jd(106138433640660311.to_r/43200000000), 1.to_r/1000/ONE_DAY] => DateTime.jd(1768973894011.to_r/720000), # fractional seconds test
81
+ }
82
+
83
+ FLOOR_TO_EXPECTATIONS.each do |(input, step), expected|
84
+ it_rounds_correctly(:floor_to, input, step, expected)
85
+ end
86
+
87
+ it "allows an around offset to center the rounding" do
88
+ expect(4.floor_to(2.5, 1)).to eq(3.5)
89
+ expect(4.5.floor_to(2, 1)).to eq(3.0)
90
+ end
91
+
92
+ it "allows a time around offset to center the rounding" do
93
+ time = Time.new(2014, 9, 5, 12, 0, 00, "-06:00")
94
+ expect(time.floor_to(ONE_WEEK, WEDNESDAY)).to eq(Time.new(2014, 9, 3, 0, 0, 0, "-06:00"))
95
+ end
96
+ end
97
+
98
+ describe "#ceil_to" do
99
+ CEIL_TO_EXPECTATIONS = {
100
+ [3, 2] => 4,
101
+ [2, 2] => 2,
102
+ [0, 2] => 0,
103
+ [-1, 2] => 0,
104
+ [-2, 2] => -2,
105
+ [104, 5] => 105,
106
+ [3.0, 2] => 4,
107
+ [2.0, 2] => 2,
108
+ [0.0, 2] => 0,
109
+ [-1.0, 2] => 0,
110
+ [-2.0, 2] => -2,
111
+ [104.0, 5] => 105,
112
+ [3, 2.5] => 5.0,
113
+ [-3, 2.5] => -2.5,
114
+ [105, 2.5] => 105.0,
115
+ [4.9, 2.5] => 5.0,
116
+ [Time.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-04:00"),
117
+ [Time.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-05:00"),
118
+ [Time.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-06:00"),
119
+ [Time.new(2014, 9, 5, 11, 59, 59, "-07:00"), 60*60*24] => Time.new(2014, 9, 6, 0, 0, 00, "-07:00"),
120
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), 60*60*24] => Time.new(2014, 9, 6, 0, 0, 00, "-08:00"),
121
+ [Time.new(2014, 9, 5, 12, 0, 01, "-09:00"), 60*60*24] => Time.new(2014, 9, 6, 0, 0, 00, "-09:00"),
122
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY*365] => Time.new(2014, 12, 21, 0, 0, 00, "-08:00"),
123
+ [Time.at(1409955065, 284499), 1.to_r/1000] => Time.at(1409955065, 285000),
124
+ [Time.at(1409955065, 284500), 1.to_r/1000] => Time.at(1409955065, 285000),
125
+ [Time.at(1409955065, 284501), 1.to_r/1000] => Time.at(1409955065, 285000),
126
+ [TIME_ZONE.local(2014, 9, 5, 18, 8, 30), 60] => TIME_ZONE.local(2014, 9, 5, 18, 9, 00),
127
+ [DateTime.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-04:00"),
128
+ [DateTime.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-05:00"),
129
+ [DateTime.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-06:00"),
130
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1] => DateTime.new(2014, 9, 6, 0, 0, 00, "-07:00"),
131
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1] => DateTime.new(2014, 9, 6, 0, 0, 00, "-08:00"),
132
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1] => DateTime.new(2014, 9, 6, 0, 0, 00, "-09:00"),
133
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1.day] => DateTime.new(2014, 9, 6, 0, 0, 00, "-07:00"),
134
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1.day] => DateTime.new(2014, 9, 6, 0, 0, 00, "-08:00"),
135
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1.day] => DateTime.new(2014, 9, 6, 0, 0, 00, "-09:00"),
136
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 365] => DateTime.new(2015, 6, 6, 0, 0, 00, "-08:00"), # rounds around Julian epoch: -4712-01-01 00:00:00
137
+ [DateTime.jd(106138433640660311.to_r/43200000000), 1.to_r/1000/ONE_DAY] => DateTime.jd(212276867281321.to_r/86400000), # fractional seconds test
138
+ }
139
+
140
+ CEIL_TO_EXPECTATIONS.each do |(input, step), expected|
141
+ it_rounds_correctly(:ceil_to, input, step, expected)
142
+ end
143
+
144
+ it "allows an around offset to center the rounding" do
145
+ expect(4.ceil_to(2.5, 1)).to eq(6.0)
146
+ expect(4.5.ceil_to(2, 1)).to eq(5.0)
147
+ end
148
+
149
+ it "allows a time around offset to center the rounding" do
150
+ time = Time.new(2014, 9, 5, 12, 0, 00, "-06:00")
151
+ expect(time.ceil_to(ONE_WEEK, WEDNESDAY)).to eq(Time.new(2014, 9, 10, 0, 0, 0, "-06:00"))
152
+ end
153
+ end
154
+
155
+ describe "#round_to" do
156
+ TO_NEAREST_EXPECTATIONS = {
157
+ [3, 2] => 4,
158
+ [2, 2] => 2,
159
+ [0, 2] => 0,
160
+ [-1, 2] => 0,
161
+ [-2, 2] => -2,
162
+ [102, 5] => 100,
163
+ [103, 5] => 105,
164
+ [104, 5] => 105,
165
+ [105, 5] => 105,
166
+ [84, 10] => 80,
167
+ [85, 10] => 90,
168
+ [3.0, 2] => 4,
169
+ [2.0, 2] => 2,
170
+ [0.0, 2] => 0,
171
+ [-1.0, 2] => 0,
172
+ [-2.0, 2] => -2,
173
+ [102.0, 5] => 100,
174
+ [103.0, 5] => 105,
175
+ [104.0, 5] => 105,
176
+ [105.0, 5] => 105,
177
+ [84.0, 10] => 80,
178
+ [85.0, 10] => 90,
179
+ [3, 2.5] => 2.5,
180
+ [-3, 2.5] => -2.5,
181
+ [1.24, 2.5] => 0.0,
182
+ [1.25, 2.5] => 2.5,
183
+ [103, 2.5] => 102.5,
184
+ [104, 2.5] => 105.0,
185
+ [105, 2.5] => 105.0,
186
+ [4.9, 2.5] => 5.0,
187
+ [Time.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-04:00"),
188
+ [Time.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-05:00"),
189
+ [Time.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-06:00"),
190
+ [Time.new(2014, 9, 5, 11, 59, 59, "-07:00"), 60*60*24] => Time.new(2014, 9, 5, 0, 0, 00, "-07:00"),
191
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), 60*60*24] => Time.new(2014, 9, 6, 0, 0, 00, "-08:00"),
192
+ [Time.new(2014, 9, 5, 12, 0, 01, "-09:00"), 60*60*24] => Time.new(2014, 9, 6, 0, 0, 00, "-09:00"),
193
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY*365] => Time.new(2014, 12, 21, 0, 0, 00, "-08:00"),
194
+ [Time.at(1409955065, 284499), 1.to_r/1000] => Time.at(1409955065, 284000),
195
+ [Time.at(1409955065, 284500), 1.to_r/1000] => Time.at(1409955065, 285000),
196
+ [Time.at(1409955065, 284501), 1.to_r/1000] => Time.at(1409955065, 285000),
197
+ [TIME_ZONE.local(2014, 9, 5, 18, 8, 30), 60] => TIME_ZONE.local(2014, 9, 5, 18, 9, 00),
198
+ [DateTime.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-04:00"),
199
+ [DateTime.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-05:00"),
200
+ [DateTime.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-06:00"),
201
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1] => DateTime.new(2014, 9, 5, 0, 0, 00, "-07:00"),
202
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1] => DateTime.new(2014, 9, 6, 0, 0, 00, "-08:00"),
203
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1] => DateTime.new(2014, 9, 6, 0, 0, 00, "-09:00"),
204
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1.day] => DateTime.new(2014, 9, 5, 0, 0, 00, "-07:00"),
205
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1.day] => DateTime.new(2014, 9, 6, 0, 0, 00, "-08:00"),
206
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1.day] => DateTime.new(2014, 9, 6, 0, 0, 00, "-09:00"),
207
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 365] => DateTime.new(2014, 6, 6, 0, 0, 00, "-08:00"), # rounds around Julian epoch: -4712-01-01 00:00:00
208
+ [DateTime.jd(106138433640660311.to_r/43200000000), 1.to_r/1000/ONE_DAY] => DateTime.jd(212276867281321.to_r/86400000), # fractional seconds test
209
+ }
210
+
211
+ TO_NEAREST_EXPECTATIONS.each do |(input, step), expected|
212
+ it_rounds_correctly(:round_to, input, step, expected)
213
+ end
214
+
215
+ it "allows an around offset to center the rounding" do
216
+ expect(4.round_to(2.5, 1)).to eq(3.5)
217
+ expect(4.5.round_to(2, 1)).to eq(5.0)
218
+ end
219
+
220
+ it "allows a time around offset to center the rounding" do
221
+ time = Time.new(2014, 9, 5, 12, 0, 00, "-06:00")
222
+ expect(time.round_to(ONE_WEEK, WEDNESDAY)).to eq(Time.new(2014, 9, 3, 0, 0, 0, "-06:00"))
223
+ end
224
+ end
225
+
226
+ describe "#floor_in_utc_to" do
227
+ FLOOR_IN_UTC_TO_EXPECTATIONS = {
228
+ [Time.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-04:00"),
229
+ [Time.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-05:00"),
230
+ [Time.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-06:00"),
231
+ [Time.new(2014, 9, 5, 4, 59, 59, "-07:00"), 60*60*24] => Time.new(2014, 9, 4, 17, 0, 00, "-07:00"),
232
+ [Time.new(2014, 9, 5, 4, 0, 00, "-08:00"), 60*60*24] => Time.new(2014, 9, 4, 16, 0, 00, "-08:00"),
233
+ [Time.new(2014, 9, 5, 3, 0, 01, "-09:00"), 60*60*24] => Time.new(2014, 9, 4, 15, 0, 00, "-09:00"),
234
+ [Time.at(1409955065, 284499), 1.to_r/1000] => Time.at(1409955065, 284000),
235
+ [Time.at(1409955065, 284500), 1.to_r/1000] => Time.at(1409955065, 284000),
236
+ [Time.at(1409955065, 284501), 1.to_r/1000] => Time.at(1409955065, 284000),
237
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY*365] => Time.new(2013, 12, 20, 16, 0, 00, "-08:00"),
238
+ [AST.local(2014, 9, 5, 18, 8, 30), 60*60*24] => AST.local(2014, 9, 5, 3, 0, 00),
239
+ [DateTime.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-04:00"),
240
+ [DateTime.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-05:00"),
241
+ [DateTime.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-06:00"),
242
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1] => DateTime.new(2014, 9, 4, 17, 0, 00, "-07:00"),
243
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1] => DateTime.new(2014, 9, 4, 16, 0, 00, "-08:00"),
244
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1] => DateTime.new(2014, 9, 4, 15, 0, 00, "-09:00"),
245
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1.day] => DateTime.new(2014, 9, 4, 17, 0, 00, "-07:00"),
246
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1.day] => DateTime.new(2014, 9, 4, 16, 0, 00, "-08:00"),
247
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1.day] => DateTime.new(2014, 9, 4, 15, 0, 00, "-09:00"),
248
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 365] => DateTime.new(2013, 12, 20, 16, 0, 00, "-08:00"), # rounds around UTC epoch: 1970-01-01 00:00:00
249
+ [DateTime.jd(106138433640660311.to_r/43200000000), 1.to_r/1000/ONE_DAY] => DateTime.jd(1768973894011.to_r/720000), # fractional seconds test
250
+ }
251
+
252
+ FLOOR_IN_UTC_TO_EXPECTATIONS.each do |(input, step), expected|
253
+ it_rounds_correctly(:floor_in_utc_to, input, step, expected)
254
+ end
255
+ end
256
+
257
+ describe "#ceil_in_utc_to" do
258
+ CEIL_IN_UTC_TO_EXPECTATIONS = {
259
+ [Time.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-04:00"),
260
+ [Time.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-05:00"),
261
+ [Time.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-06:00"),
262
+ [Time.new(2014, 9, 5, 4, 59, 59, "-07:00"), 60*60*24] => Time.new(2014, 9, 5, 17, 0, 00, "-07:00"),
263
+ [Time.new(2014, 9, 5, 4, 0, 00, "-08:00"), 60*60*24] => Time.new(2014, 9, 5, 16, 0, 00, "-08:00"),
264
+ [Time.new(2014, 9, 5, 3, 0, 01, "-09:00"), 60*60*24] => Time.new(2014, 9, 5, 15, 0, 00, "-09:00"),
265
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY*365] => Time.new(2014, 12, 20, 16, 0, 00, "-08:00"),
266
+ [Time.at(1409955065, 284499), 1.to_r/1000] => Time.at(1409955065, 285000),
267
+ [Time.at(1409955065, 284500), 1.to_r/1000] => Time.at(1409955065, 285000),
268
+ [Time.at(1409955065, 284501), 1.to_r/1000] => Time.at(1409955065, 285000),
269
+ [AST.local(2014, 9, 5, 18, 8, 30), 60*60*24] => AST.local(2014, 9, 6, 3, 0, 00),
270
+ [DateTime.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-04:00"),
271
+ [DateTime.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-05:00"),
272
+ [DateTime.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-06:00"),
273
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1] => DateTime.new(2014, 9, 5, 17, 0, 00, "-07:00"),
274
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1] => DateTime.new(2014, 9, 5, 16, 0, 00, "-08:00"),
275
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1] => DateTime.new(2014, 9, 5, 15, 0, 00, "-09:00"),
276
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1.day] => DateTime.new(2014, 9, 5, 17, 0, 00, "-07:00"),
277
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1.day] => DateTime.new(2014, 9, 5, 16, 0, 00, "-08:00"),
278
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1.day] => DateTime.new(2014, 9, 5, 15, 0, 00, "-09:00"),
279
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 365] => DateTime.new(2014, 12, 20, 16, 0, 00, "-08:00"), # rounds around UTC epoch: 1970-01-01 00:00:00
280
+ [DateTime.jd(106138433640660311.to_r/43200000000), 1.to_r/1000/ONE_DAY] => DateTime.jd(212276867281321.to_r/86400000), # fractional seconds test
281
+ }
282
+
283
+ CEIL_IN_UTC_TO_EXPECTATIONS.each do |(input, step), expected|
284
+ it_rounds_correctly(:ceil_in_utc_to, input, step, expected)
285
+ end
286
+ end
287
+
288
+ describe "#round_in_utc_to" do
289
+ TO_NEAREST_IN_UTC_EXPECTATIONS = {
290
+ [Time.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60] => Time.new(2014, 9, 5, 18, 8, 00, "-04:00"),
291
+ [Time.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-05:00"),
292
+ [Time.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60] => Time.new(2014, 9, 5, 18, 9, 00, "-06:00"),
293
+ [Time.new(2014, 9, 5, 4, 59, 59, "-07:00"), 60*60*24] => Time.new(2014, 9, 4, 17, 0, 00, "-07:00"),
294
+ [Time.new(2014, 9, 5, 4, 0, 00, "-08:00"), 60*60*24] => Time.new(2014, 9, 5, 16, 0, 00, "-08:00"),
295
+ [Time.new(2014, 9, 5, 3, 0, 01, "-09:00"), 60*60*24] => Time.new(2014, 9, 5, 15, 0, 00, "-09:00"),
296
+ [Time.new(2014, 9, 5, 12, 0, 00, "-08:00"), ONE_DAY*365] => Time.new(2014, 12, 20, 16, 0, 00, "-08:00"),
297
+ [Time.at(1409955065, 284499), 1.to_r/1000] => Time.at(1409955065, 284000),
298
+ [Time.at(1409955065, 284500), 1.to_r/1000] => Time.at(1409955065, 285000),
299
+ [Time.at(1409955065, 284501), 1.to_r/1000] => Time.at(1409955065, 285000),
300
+ [AST.local(2014, 9, 5, 18, 8, 30), 60*60*24] => AST.local(2014, 9, 6, 3, 0, 00),
301
+ [DateTime.new(2014, 9, 5, 18, 8, 29, "-04:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 8, 00, "-04:00"),
302
+ [DateTime.new(2014, 9, 5, 18, 8, 30, "-05:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-05:00"),
303
+ [DateTime.new(2014, 9, 5, 18, 8, 31, "-06:00"), 60.to_r/ONE_DAY] => DateTime.new(2014, 9, 5, 18, 9, 00, "-06:00"),
304
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1] => DateTime.new(2014, 9, 5, 17, 0, 00, "-07:00"),
305
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1] => DateTime.new(2014, 9, 5, 16, 0, 00, "-08:00"),
306
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1] => DateTime.new(2014, 9, 5, 15, 0, 00, "-09:00"),
307
+ [DateTime.new(2014, 9, 5, 11, 59, 59, "-07:00"), 1.day] => DateTime.new(2014, 9, 5, 17, 0, 00, "-07:00"),
308
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 1.day] => DateTime.new(2014, 9, 5, 16, 0, 00, "-08:00"),
309
+ [DateTime.new(2014, 9, 5, 12, 0, 01, "-09:00"), 1.day] => DateTime.new(2014, 9, 5, 15, 0, 00, "-09:00"),
310
+ [DateTime.new(2014, 9, 5, 12, 0, 00, "-08:00"), 365] => DateTime.new(2014, 12, 20, 16, 0, 00, "-08:00"), # rounds around UTC epoch: 1970-01-01 00:00:00
311
+ [DateTime.jd(106138433640660311.to_r/43200000000), 1.to_r/1000/ONE_DAY] => DateTime.jd(212276867281321.to_r/86400000), # fractional seconds test
312
+ }
313
+
314
+ TO_NEAREST_IN_UTC_EXPECTATIONS.each do |(input, step), expected|
315
+ it_rounds_correctly(:round_in_utc_to, input, step, expected)
316
+ end
317
+ end
318
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rounding
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Hempel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: rspec
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: activesupport
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: Floor/nearest/ceiling rounding by arbitrary steps for Integers, Floats,
70
+ Times, TimeWithZones, and DateTimes.
71
+ email:
72
+ - plasticchicken@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - lib/rounding.rb
85
+ - lib/rounding/active_support_ext/time_with_zone.rb
86
+ - lib/rounding/core_ext/date_time.rb
87
+ - lib/rounding/core_ext/numeric.rb
88
+ - lib/rounding/core_ext/time.rb
89
+ - lib/rounding/time_extensions.rb
90
+ - lib/rounding/version.rb
91
+ - rounding.gemspec
92
+ - spec/rounding_spec.rb
93
+ homepage: https://github.com/brianhempel/rounding
94
+ licenses:
95
+ - Public Domain
96
+ metadata: {}
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: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.2.2
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Floor/nearest/ceiling rounding by arbitrary steps for Integers, Floats, Times,
117
+ TimeWithZones, and DateTimes.
118
+ test_files:
119
+ - spec/rounding_spec.rb