as-duration 0.0.2 → 0.1.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 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