time_math2 0.0.5 → 0.0.6

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: 8fe3eec624d634487ddc4b74d08a3d39ec3f34d5
4
- data.tar.gz: 87c691b0990e5e4a03f7bad4602e8bf100d1d526
3
+ metadata.gz: 51045d4f122c5237a82ef69caa42a16680a61e53
4
+ data.tar.gz: 3efbc480f4aa87b64b07219746f647101b706372
5
5
  SHA512:
6
- metadata.gz: 8a7e17f5d2f9768c734649768b95c8ad63f168ca3c8686f2d52440caa952f8c7a20bc1af223cb5238eacfdec7e5924e814c0d8385887e83a5623da0024d15a55
7
- data.tar.gz: a39344389ba42191d780257d97e4c53e6e2e84a5512e7deac17ba731a543e5decab9e01e833b266dc6f93efbbdec1d11135deff8cb78110071535ef382c713a7
6
+ metadata.gz: 3a607d28b91d01cb76d1764564cd7e4cb04a57f994ed4931402b1d6625348ce4042e75fb60c9dd9043f0b5bda5a2b81a15149c9d6668d68be7ed97724d136acc
7
+ data.tar.gz: e6f66d0e085b1dd0ac4bb1fc57e94dd949a403a6f09a6242da4444285af99eefd158f0229a03d26e3b31714b208c65dfc11e59ee1a89d46012dbdad03fa9c9d3
@@ -1,7 +1,15 @@
1
1
  # TimeMath Changelog
2
2
 
3
+ # 0.0.6 (2016-12-14)
4
+
5
+ * Fix approach to timezone info preservation (previously, it was clear bug, emerging from
6
+ false believing of how `Time.mktime` works). Thanks, @wojtha, for pointing to the problem.
7
+ * Add `#each` and `Enumerable` to `Sequence` (no idea why it wasn't done from the very
8
+ beginning). Again: thanks, @wojtha!
9
+
3
10
  # 0.0.5 (2016-06-25)
4
11
 
12
+ * Add support for `Date`;
5
13
  * Add optional second argument to rounding functions (`floor`, `ceil` and
6
14
  so on), for "floor to 3-hour mark";
7
15
  * Allow this argument, as well as in `advance`/`decrease`, to be non-integer;
data/README.md CHANGED
@@ -35,7 +35,7 @@ Rails or without it, for any purpose.
35
35
  * No monkey-patching of core classes (now **strict**; previously existing opt-in
36
36
  core ext removed in 0.0.5);
37
37
  * Works with Time, Date and DateTime;
38
- * Accurately preserves timezone info;
38
+ * Accurately preserves timezone offset;
39
39
  * Simple arithmetics: floor/ceil/round to any time unit (second, hour, year
40
40
  or whatnot), advance/decrease by any unit;
41
41
  * Chainable [operations](#set-of-operations-as-a-value-object), including
@@ -306,12 +306,7 @@ it means:
306
306
 
307
307
  ## Compatibility notes
308
308
 
309
- TimeMath is known to work on MRI Ruby >= 1.9.
310
-
311
- On JRuby it works, too, though there could be _slightly_ unexpected results,
312
- when JRuby fails to create time by timezone name (see [bug](https://github.com/jruby/jruby/issues/3978)).
313
- TimeMath in this case fallbacks to the same solution that used for `DateTime`,
314
- and at least preserves utc offset.
309
+ TimeMath is known to work on MRI Ruby >= 2.0 and JRuby >= 9.0.0.0.
315
310
 
316
311
  On Rubinius, some of tests fail and I haven't time to investigate it. If
317
312
  somebody still uses Rubinius and wants TimeMath to be working properly
@@ -62,7 +62,7 @@ module TimeMath
62
62
 
63
63
  sequence.ranges.map do |r|
64
64
  values = @hash.select { |k, _| r.cover?(k) }.map(&:last)
65
- values = block.call(values) if block # rubocop:disable Performance/RedundantBlockCall
65
+ values = block.call(values) if block
66
66
  [r.begin, values]
67
67
  end.to_h
68
68
  end
@@ -230,26 +230,25 @@ module TimeMath
230
230
  end
231
231
  end
232
232
 
233
- # Creates an array of time unit starts between from and to. They will
234
- # have same granularity as from (e.g. if unit is day and from is
235
- # 2016-05-01 13:30, each of return values will be next day at 13:30),
236
- # unless sequence is not set to floor values.
233
+ # Enumerates time unit between `from` and `to`. They will have same granularity as from
234
+ # (e.g. if `unit` is day and from is 2016-05-01 13:30, each of return values will be next
235
+ # day at 13:30), unless sequence is not set to floor values.
237
236
  #
238
- # @return [Array<Time or DateTime>]
239
- def to_a
240
- seq = []
237
+ # @return [Enumerator<Time, or Date, or DateTime>]
238
+ def each
239
+ return to_enum(:each) unless block_given?
241
240
 
242
241
  iter = from
243
242
  while iter < to
244
- seq << iter
243
+ yield(op.call(iter))
245
244
 
246
245
  iter = unit.advance(iter)
247
246
  end
248
- seq << to unless exclude_end?
249
-
250
- op.call(seq)
247
+ yield(op.call(to)) unless exclude_end?
251
248
  end
252
249
 
250
+ include Enumerable
251
+
253
252
  # Creates an array of pairs (time unit start, time unit end) between
254
253
  # from and to.
255
254
  #
@@ -46,8 +46,8 @@ module TimeMath
46
46
  # @param tm [Time,Date,DateTime] time value to floor.
47
47
  # @param span [Numeric] how many units to floor to. For units
48
48
  # less than week supports float/rational values.
49
- # @return [Time,Date,DateTime] floored time value; class and timezone
50
- # info of origin would be preserved.
49
+ # @return [Time,Date,DateTime] floored time value; class and timezone offset of origin
50
+ # would be preserved.
51
51
  def floor(tm, span = 1)
52
52
  int_floor = advance(floor_1(tm), (tm.send(name) / span.to_f).floor * span - tm.send(name))
53
53
  float_fix(tm, int_floor, span % 1)
@@ -61,7 +61,7 @@ module TimeMath
61
61
  # @param tm [Time,Date,DateTime] time value to ceil.
62
62
  # @param span [Numeric] how many units to ceil to. For units
63
63
  # less than week supports float/rational values.
64
- # @return [Time,Date,DateTime] ceiled time value; class and timezone info
64
+ # @return [Time,Date,DateTime] ceiled time value; class and timezone offset
65
65
  # of origin would be preserved.
66
66
  def ceil(tm, span = 1)
67
67
  f = floor(tm, span)
@@ -78,7 +78,7 @@ module TimeMath
78
78
  # @param tm [Time,Date,DateTime] time value to round.
79
79
  # @param span [Numeric] how many units to round to. For units
80
80
  # less than week supports float/rational values.
81
- # @return [Time,Date,DateTime] rounded time value; class and timezone info
81
+ # @return [Time,Date,DateTime] rounded time value; class and timezone offset
82
82
  # of origin would be preserved.
83
83
  def round(tm, span = 1)
84
84
  f, c = floor(tm, span), ceil(tm, span)
@@ -95,7 +95,7 @@ module TimeMath
95
95
  # @param tm [Time,Date,DateTime] time value to calculate prev on.
96
96
  # @param span [Numeric] how many units to floor to. For units
97
97
  # less than week supports float/rational values.
98
- # @return [Time,Date,DateTime] prev time value; class and timezone info
98
+ # @return [Time,Date,DateTime] prev time value; class and timezone offset
99
99
  # of origin would be preserved.
100
100
  def prev(tm, span = 1)
101
101
  f = floor(tm, span)
@@ -111,7 +111,7 @@ module TimeMath
111
111
  # @param tm [Time,Date,DateTime] time value to calculate next on.
112
112
  # @param span [Numeric] how many units to ceil to. For units
113
113
  # less than week supports float/rational values.
114
- # @return [Time,Date,DateTime] next time value; class and timezone info
114
+ # @return [Time,Date,DateTime] next time value; class and timezone offset
115
115
  # of origin would be preserved.
116
116
  def next(tm, span = 1)
117
117
  c = ceil(tm, span)
@@ -134,7 +134,7 @@ module TimeMath
134
134
  # @param amount [Numeric] how many units forward to go. For units
135
135
  # less than week supports float/rational values.
136
136
  #
137
- # @return [Time,Date,DateTime] advanced time value; class and timezone info
137
+ # @return [Time,Date,DateTime] advanced time value; class and timezone offset
138
138
  # of origin would be preserved.
139
139
  def advance(tm, amount = 1)
140
140
  return decrease(tm, -amount) if amount < 0
@@ -147,7 +147,7 @@ module TimeMath
147
147
  # @param amount [Integer] how many units forward to go. For units
148
148
  # less than week supports float/rational values.
149
149
  #
150
- # @return [Time,Date,DateTime] decrease time value; class and timezone info
150
+ # @return [Time,Date,DateTime] decrease time value; class and timezone offset
151
151
  # of origin would be preserved.
152
152
  def decrease(tm, amount = 1)
153
153
  return advance(tm, -amount) if amount < 0
@@ -300,59 +300,16 @@ module TimeMath
300
300
  "#<#{self.class}>"
301
301
  end
302
302
 
303
- protected
304
-
305
- # all except :week
306
- NATURAL_UNITS = [:year, :month, :day, :hour, :min, :sec].freeze
307
- EMPTY_VALUES = [nil, 1, 1, 0, 0, 0].freeze
303
+ private
308
304
 
309
305
  def index
310
- NATURAL_UNITS.index(name) or
306
+ Util::NATURAL_UNITS.index(name) or
311
307
  raise NotImplementedError, "Can not be used for #{name}"
312
308
  end
313
309
 
314
- def generate(tm, replacements = {})
315
- hash_to_tm(tm, tm_to_hash(tm).merge(replacements))
316
- end
317
-
318
- def tm_to_hash(tm)
319
- Hash[*NATURAL_UNITS.flat_map { |s| [s, tm.send(s)] }]
320
- end
321
-
322
- def hash_to_tm(origin, hash)
323
- components = NATURAL_UNITS.map { |s| hash[s] || 0 }
324
- new_from_components(origin, *components)
325
- end
326
-
327
- def new_from_components(origin, *components)
328
- components = EMPTY_VALUES.zip(components).map { |d, c| c || d }
329
- case origin
330
- when Time
331
- res = Time.mktime(*components.reverse, nil, nil, nil, origin.zone)
332
- fix_no_zone(res, origin, *components)
333
- when DateTime
334
- DateTime.new(*components, origin.zone)
335
- when Date
336
- Date.new(*components.first(3))
337
- else
338
- raise ArgumentError, "Expected Time, Date or DateTime, got #{origin.class}"
339
- end
340
- end
341
-
342
- def to_components(tm)
343
- case tm
344
- when Time, DateTime
345
- [tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec]
346
- when Date
347
- [tm.year, tm.month, tm.day]
348
- else
349
- raise ArgumentError, "Expected Time, Date or DateTime, got #{tm.class}"
350
- end
351
- end
352
-
353
310
  def floor_1(tm)
354
- components = to_components(tm).first(index + 1)
355
- new_from_components(tm, *components)
311
+ components = Util.tm_to_array(tm).first(index + 1)
312
+ Util.array_to_tm(tm, *components)
356
313
  end
357
314
 
358
315
  def float_fix(tm, floored, float_span_part)
@@ -363,16 +320,6 @@ module TimeMath
363
320
  float_floored > tm ? floored : float_floored
364
321
  end
365
322
  end
366
-
367
- def fix_no_zone(tm, origin, *components)
368
- if origin.zone != 'UTC' && tm.zone == 'UTC'
369
- # Fixes things like this one: https://github.com/jruby/jruby/issues/3978
370
- # ...by falling back to use of UTC offset instead of timezone abbr
371
- Time.new(*components, origin.utc_offset)
372
- else
373
- tm
374
- end
375
- end
376
323
  end
377
324
  end
378
325
  end
@@ -17,16 +17,16 @@ module TimeMath
17
17
  protected
18
18
 
19
19
  def _succ(tm)
20
- return generate(tm, year: tm.year + 1, month: 1) if tm.month == 12
20
+ return Util.merge(tm, year: tm.year + 1, month: 1) if tm.month == 12
21
21
 
22
- t = generate(tm, month: tm.month + 1)
22
+ t = Util.merge(tm, month: tm.month + 1)
23
23
  fix_month(t, t.month + 1)
24
24
  end
25
25
 
26
26
  def _prev(tm)
27
- return generate(tm, year: tm.year - 1, month: 12) if tm.month == 1
27
+ return Util.merge(tm, year: tm.year - 1, month: 12) if tm.month == 1
28
28
 
29
- t = generate(tm, month: tm.month - 1)
29
+ t = Util.merge(tm, month: tm.month - 1)
30
30
  fix_month(t, t.month - 1)
31
31
  end
32
32
 
@@ -11,7 +11,7 @@ module TimeMath
11
11
  raise NotImplementedError, 'For now, week only can floor to one'
12
12
 
13
13
  f = TimeMath.day.floor(tm)
14
- extra_days = tm.wday == 0 ? 6 : tm.wday - 1
14
+ extra_days = tm.wday.zero? ? 6 : tm.wday - 1
15
15
  TimeMath.day.decrease(f, extra_days)
16
16
  end
17
17
 
@@ -7,7 +7,7 @@ module TimeMath
7
7
  end
8
8
 
9
9
  def measure(from, to)
10
- if generate(from, year: to.year) < to
10
+ if Util.merge(from, year: to.year) < to
11
11
  to.year - from.year
12
12
  else
13
13
  to.year - from.year - 1
@@ -17,11 +17,11 @@ module TimeMath
17
17
  protected
18
18
 
19
19
  def _advance(tm, steps)
20
- generate(tm, year: tm.year + steps.to_i)
20
+ Util.merge(tm, year: tm.year + steps.to_i)
21
21
  end
22
22
 
23
23
  def _decrease(tm, steps)
24
- generate(tm, year: tm.year - steps.to_i)
24
+ Util.merge(tm, year: tm.year - steps.to_i)
25
25
  end
26
26
  end
27
27
  end
@@ -1,10 +1,53 @@
1
1
  module TimeMath
2
2
  # @private
3
3
  module Util
4
+ # all except :week
5
+ NATURAL_UNITS = [:year, :month, :day, :hour, :min, :sec].freeze
6
+ EMPTY_VALUES = [nil, 1, 1, 0, 0, 0].freeze
7
+
4
8
  module_function
5
9
 
6
10
  def timey?(val)
7
11
  [Time, DateTime, Date].any? { |cls| val.is_a?(cls) }
8
12
  end
13
+
14
+ def merge(tm, attrs = {})
15
+ hash_to_tm(tm, tm_to_hash(tm).merge(attrs))
16
+ end
17
+
18
+ def array_to_tm(origin, *components)
19
+ components = EMPTY_VALUES.zip(components).map { |d, c| c || d }
20
+
21
+ case origin
22
+ when Time
23
+ Time.new(*components, origin.utc_offset)
24
+ when DateTime
25
+ DateTime.new(*components, origin.zone)
26
+ when Date
27
+ Date.new(*components.first(3))
28
+ else
29
+ raise ArgumentError, "Expected Time, Date or DateTime, got #{origin.class}"
30
+ end
31
+ end
32
+
33
+ def tm_to_array(tm)
34
+ case tm
35
+ when Time, DateTime
36
+ [tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec]
37
+ when Date
38
+ [tm.year, tm.month, tm.day]
39
+ else
40
+ raise ArgumentError, "Expected Time, Date or DateTime, got #{tm.class}"
41
+ end
42
+ end
43
+
44
+ def tm_to_hash(tm)
45
+ Hash[*NATURAL_UNITS.flat_map { |s| [s, tm.send(s)] }]
46
+ end
47
+
48
+ def hash_to_tm(origin, hash)
49
+ components = NATURAL_UNITS.map { |s| hash[s] || 0 }
50
+ array_to_tm(origin, *components)
51
+ end
9
52
  end
10
53
  end
@@ -1,4 +1,4 @@
1
1
  module TimeMath
2
2
  # @private
3
- VERSION = '0.0.5'.freeze
3
+ VERSION = '0.0.6'.freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_math2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-25 00:00:00.000000000 Z
11
+ date: 2016-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -158,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
158
  version: '0'
159
159
  requirements: []
160
160
  rubyforge_project:
161
- rubygems_version: 2.4.8
161
+ rubygems_version: 2.5.2
162
162
  signing_key:
163
163
  specification_version: 4
164
164
  summary: Easy time math