as-duration 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: efd76209348cb343f2ef4b2d5039cb1dd033640c
4
- data.tar.gz: 3110aaa5b289824b2d18291a2acf675c1b8cffa0
3
+ metadata.gz: 0f6bacd1545efa2a36143899ac06d0aac39e0b88
4
+ data.tar.gz: f1df67155ed5e3a1214f8b21809bd4b72d2964b4
5
5
  SHA512:
6
- metadata.gz: bc6cf946e1a327453b91a30b3282a0478085039b909a538bb0bd9aecfcda44e9aa2a5e8cf06121668fc3867f3a9bd418c40a021d22d65938acfd8899ef764f82
7
- data.tar.gz: 6f38f2966c070df139baca861f030c62d1456331a5cd5538190fbf63e1fe43c91c0bc421f261a490be168ec81f40e41ec1803ede3c9dcd6e66ec527746ad68ea
6
+ metadata.gz: d899e350fd9c36bb7487d9a403a240cba3a7acacc3db2cf9706bad718c0f164225f7c14aa59ce6ae49b538b4cb5427fbfaad061a52d10eef621dac2f4e50210d
7
+ data.tar.gz: 583fef2d66ea1db4c79eb7d57f57ae7ca75fe36c0a586b5ded2d147a05a545b2859eb5fad2ba00f2e366e07621e7c943ae4eb2b53cd7e318b598e7bd731092cb
data/README.md CHANGED
@@ -30,7 +30,7 @@ gem 'as-duration'
30
30
 
31
31
  ## Features
32
32
 
33
- *DISCLAIMER: In most cases `as-duration` should work exactly like
33
+ *NOTE: In most cases `as-duration` should work exactly like
34
34
  `ActiveSupport::Duration`. However, there are a few modifications made, mostly
35
35
  removing some of the magic, see [Modifications](#modifications-to-activesupportduration).*
36
36
 
data/lib/as/duration.rb CHANGED
@@ -5,48 +5,24 @@ module AS
5
5
  class Duration
6
6
  include Comparable
7
7
 
8
- attr_reader :parts
8
+ attr_accessor :value, :parts
9
9
 
10
- def initialize(parts)
11
- parts = parts.dup
12
-
13
- # Remove partial weeks and days for accurate date behaviour
14
- if Float === parts[:weeks]
15
- parts[:weeks], partial_weeks = parts[:weeks].divmod(1)
16
- parts[:days] = parts.fetch(:days, 0) + 7 * partial_weeks
17
- end
18
- if Float === parts[:days]
19
- parts[:days], partial_days = parts[:days].divmod(1)
20
- parts[:hours] = parts.fetch(:hours, 0) + 24 * partial_days
21
- end
22
-
23
- @parts = parts.freeze
10
+ def initialize(value, parts)
11
+ @value, @parts = value, parts
24
12
  end
25
13
 
26
14
  def to_i
27
- @parts.inject(0) do |sum, (type, value)|
28
- case type
29
- when :seconds then sum + value
30
- when :minutes then sum + value * 60
31
- when :hours then sum + value * 60 * 60
32
- when :days then sum + value * 60 * 60 * 24
33
- when :weeks then sum + value * 60 * 60 * 24 * 7
34
- when :fortnights then sum + value * 60 * 60 * 24 * 14
35
- when :months then sum + value * 60 * 60 * 24 * 30
36
- when :years then sum + value * 60 * 60 * 24 * 365
37
- end
38
- end
15
+ @value
39
16
  end
40
17
 
41
18
  def <=>(other)
42
19
  return nil if not Duration === other
43
- self.to_i <=> other.to_i
20
+ self.value <=> other.value
44
21
  end
45
22
 
46
23
  def +(other)
47
24
  raise TypeError, "can only add Duration objects" if not Duration === other
48
- added_parts = parts.merge(other.parts) { |key, old, new| old + new }
49
- Duration.new(added_parts)
25
+ Duration.new(value + other.value, parts + other.parts)
50
26
  end
51
27
 
52
28
  def -(other)
@@ -55,8 +31,7 @@ module AS
55
31
  end
56
32
 
57
33
  def -@
58
- negated_parts = parts.inject({}) { |h, (k, v)| h.update(k => -v) }
59
- Duration.new(negated_parts)
34
+ Duration.new(-value, parts.map { |type, number| [type, -number] })
60
35
  end
61
36
 
62
37
  def from(time)
@@ -82,52 +57,80 @@ module AS
82
57
  protected
83
58
 
84
59
  def advance(time)
85
- case time
86
- when Time then advance_time(time)
87
- when Date then advance_date(time)
88
- else
89
- raise ArgumentError, "expected Time or Date, got #{time.inspect}"
90
- end
60
+ Calculator.new(parts).advance(time)
91
61
  end
92
62
 
93
- def advance_time(time)
94
- date = advance_date_part(time.to_date)
63
+ class Calculator
64
+ def initialize(parts)
65
+ options = parts.inject({}) do |options, (type, number)|
66
+ options.update(type => number) { |key, old, new| old + new }
67
+ end
68
+
69
+ # Remove partial weeks and days for accurate date behaviour
70
+ if Float === options[:weeks]
71
+ options[:weeks], partial_weeks = options[:weeks].divmod(1)
72
+ options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
73
+ end
74
+ if Float === options[:days]
75
+ options[:days], partial_days = options[:days].divmod(1)
76
+ options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
77
+ end
95
78
 
96
- time_advanced_by_date_args =
97
- if time.utc?
98
- Time.utc(date.year, date.month, date.day, time.hour, time.min, time.sec)
99
- elsif time.zone
100
- Time.local(date.year, date.month, date.day, time.hour, time.min, time.sec)
79
+ @options = options
80
+ end
81
+
82
+ def advance(time)
83
+ case time
84
+ when Time then advance_time(time)
85
+ when Date then advance_date(time)
101
86
  else
102
- Time.new(date.year, date.month, date.day, time.hour, time.min, time.sec, time.utc_offset)
87
+ raise ArgumentError, "expected Time or Date, got #{time.inspect}"
103
88
  end
89
+ end
104
90
 
105
- time_advanced_by_date_args + seconds_to_advance
106
- end
91
+ private
107
92
 
108
- def advance_date(date)
109
- date = advance_date_part(date)
93
+ attr_reader :options
110
94
 
111
- if seconds_to_advance == 0
112
- date
113
- else
114
- date.to_time + seconds_to_advance
95
+ def advance_time(time)
96
+ date = advance_date_part(time.to_date)
97
+
98
+ time_advanced_by_date_args =
99
+ if time.utc?
100
+ Time.utc(date.year, date.month, date.day, time.hour, time.min, time.sec)
101
+ elsif time.zone
102
+ Time.local(date.year, date.month, date.day, time.hour, time.min, time.sec)
103
+ else
104
+ Time.new(date.year, date.month, date.day, time.hour, time.min, time.sec, time.utc_offset)
105
+ end
106
+
107
+ time_advanced_by_date_args + seconds_to_advance
115
108
  end
116
- end
117
109
 
118
- def advance_date_part(date)
119
- date = date >> parts.fetch(:years, 0) * 12
120
- date = date >> parts.fetch(:months, 0)
121
- date = date + parts.fetch(:weeks, 0) * 7
122
- date = date + parts.fetch(:days, 0)
123
- date = date.gregorian if date.julian?
124
- date
125
- end
110
+ def advance_date(date)
111
+ date = advance_date_part(date)
112
+
113
+ if seconds_to_advance == 0
114
+ date
115
+ else
116
+ date.to_time + seconds_to_advance
117
+ end
118
+ end
126
119
 
127
- def seconds_to_advance
128
- parts.fetch(:seconds, 0) +
129
- parts.fetch(:minutes, 0) * 60 +
130
- parts.fetch(:hours, 0) * 3600
120
+ def advance_date_part(date)
121
+ date = date >> options.fetch(:years, 0) * 12
122
+ date = date >> options.fetch(:months, 0)
123
+ date = date + options.fetch(:weeks, 0) * 7
124
+ date = date + options.fetch(:days, 0)
125
+ date = date.gregorian if date.julian?
126
+ date
127
+ end
128
+
129
+ def seconds_to_advance
130
+ options.fetch(:seconds, 0) +
131
+ options.fetch(:minutes, 0) * 60 +
132
+ options.fetch(:hours, 0) * 3600
133
+ end
131
134
  end
132
135
  end
133
136
  end
@@ -1,11 +1,11 @@
1
1
  class Integer
2
2
  def months
3
- AS::Duration.new(months: self)
3
+ AS::Duration.new(self * 30*24*60*60, [[:months, self]])
4
4
  end
5
5
  alias month months
6
6
 
7
7
  def years
8
- AS::Duration.new(years: self)
8
+ AS::Duration.new(self * 365*24*60*60, [[:years, self]])
9
9
  end
10
10
  alias year years
11
11
  end
@@ -1,31 +1,31 @@
1
1
  class Numeric
2
2
  def seconds
3
- AS::Duration.new(seconds: self)
3
+ AS::Duration.new(self, [[:seconds, self]])
4
4
  end
5
5
  alias second seconds
6
6
 
7
7
  def minutes
8
- AS::Duration.new(minutes: self)
8
+ AS::Duration.new(self * 60, [[:minutes, self]])
9
9
  end
10
10
  alias minute minutes
11
11
 
12
12
  def hours
13
- AS::Duration.new(hours: self)
13
+ AS::Duration.new(self * 60*60, [[:hours, self]])
14
14
  end
15
15
  alias hour hours
16
16
 
17
17
  def days
18
- AS::Duration.new(days: self)
18
+ AS::Duration.new(self * 24*60*60, [[:days, self]])
19
19
  end
20
20
  alias day days
21
21
 
22
22
  def weeks
23
- AS::Duration.new(weeks: self)
23
+ AS::Duration.new(self * 7*24*60*60, [[:weeks, self]])
24
24
  end
25
25
  alias week weeks
26
26
 
27
27
  def fortnights
28
- AS::Duration.new(weeks: self * 2)
28
+ AS::Duration.new(self * 14*24*60*60, [[:weeks, self * 2]])
29
29
  end
30
30
  alias fortnight fortnights
31
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: as-duration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-27 00:00:00.000000000 Z
11
+ date: 2015-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest