ruby-units 1.4.1 → 1.4.2

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.
data/CHANGELOG.txt CHANGED
@@ -1,5 +1,9 @@
1
1
  Change Log for Ruby-units
2
2
  =========================
3
+ 2012-09-16 1.4.2 * Fix issue #54 -- pluralization of fluid-ounces
4
+ * Fix issue #53, 51 -- incorrect definition for gee
5
+ * Fix issue #52 -- add support for degree symbol
6
+ * Fix issue #50 -- fix conversion to json
3
7
  2012-05-13 1.4.1 * Fix issue #40 -- Unit parsing truncates invalid portions of the unit
4
8
  * Fix issue #41 -- initializing with a nil gives unexpected result
5
9
  2012-02-01 * Fix issue #34 -- Time.at takes more than one parameter
data/RakeFile CHANGED
@@ -57,7 +57,7 @@ begin
57
57
  desc "Run specs"
58
58
  RSpec::Core::RakeTask.new do |spec|
59
59
  puts
60
- puts %x{rvm current}
60
+ # puts %x{rvm current}
61
61
  puts
62
62
  end
63
63
 
@@ -88,4 +88,4 @@ end
88
88
  desc "Run specs against several ruby versions, requires rvm"
89
89
  task "spec:all" => rubies.keys.map {|name| "spec:#{name}"}
90
90
 
91
- task :default => :spec
91
+ task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.1
1
+ 1.4.2
@@ -21,7 +21,7 @@ end
21
21
  # in the United States. If your favorite units are not listed here, file an issue on github.
22
22
  #
23
23
  # To add or override a unit definition, add a code block like this..
24
- # @example Define a new unit
24
+ # @example Define a new unit
25
25
  # Unit.define("foobar") do |unit|
26
26
  # unit.aliases = %w{foo fb foo-bar}
27
27
  # unit.definition = Unit("1 baz")
@@ -59,8 +59,7 @@ class Unit < Numeric
59
59
  FAHRENHEIT = ['<fahrenheit>']
60
60
  RANKINE = ['<rankine>']
61
61
  CELSIUS = ['<celsius>']
62
- TEMP_REGEX = /(?:temp|deg)[CFRK]/
63
-
62
+ @@TEMP_REGEX = nil
64
63
  SIGNATURE_VECTOR = [
65
64
  :length,
66
65
  :time,
@@ -141,19 +140,19 @@ class Unit < Numeric
141
140
  @@definitions.each do |name, definition|
142
141
  self.use_definition(definition)
143
142
  end
144
-
143
+
145
144
  Unit.new(1)
146
145
  return true
147
146
  end
148
-
149
-
147
+
148
+
150
149
  # determine if a unit is already defined
151
150
  # @param [String] unit
152
151
  # @return [Boolean]
153
152
  def self.defined?(unit)
154
153
  return @@UNIT_VALUES.keys.include?("<#{unit}>")
155
154
  end
156
-
155
+
157
156
  # return the unit definition for a unit
158
157
  # @param [String] unit
159
158
  # @return [Unit::Definition, nil]
@@ -161,13 +160,13 @@ class Unit < Numeric
161
160
  unit = (_unit =~ /^<.+>$/) ? _unit : "<#{_unit}>"
162
161
  return @@definitions[unit]
163
162
  end
164
-
163
+
165
164
  # return a list of all defined units
166
165
  # @return [Array]
167
166
  def self.definitions
168
167
  return @@definitions
169
168
  end
170
-
169
+
171
170
  # @param [Unit::Definition|String] unit_definition
172
171
  # @param [Block] block
173
172
  # @return [Unit::Definition]
@@ -191,7 +190,7 @@ class Unit < Numeric
191
190
  Unit.use_definition(unit_definition)
192
191
  return unit_definition
193
192
  end
194
-
193
+
195
194
  # @param [String] name Name of unit to redefine
196
195
  # @param [Block] block
197
196
  # @raise [ArgumentError] if a block is not given
@@ -204,7 +203,7 @@ class Unit < Numeric
204
203
  yield unit_definition
205
204
  self.define(unit_definition)
206
205
  end
207
-
206
+
208
207
  # @param [String] name of unit to undefine
209
208
  # @return (see Unit.setup)
210
209
  # Undefine a unit. Will not raise an exception for unknown units.
@@ -212,12 +211,12 @@ class Unit < Numeric
212
211
  @@definitions.delete("<#{unit}>")
213
212
  Unit.setup
214
213
  end
215
-
214
+
216
215
  include Comparable
217
216
 
218
217
  # @return [Numeric]
219
218
  attr_accessor :scalar
220
-
219
+
221
220
  # @return [Array]
222
221
  attr_accessor :numerator
223
222
 
@@ -225,20 +224,20 @@ class Unit < Numeric
225
224
  attr_accessor :denominator
226
225
 
227
226
  # @return [Integer]
228
- attr_accessor :signature
227
+ attr_accessor :signature
229
228
 
230
229
  # @return [Numeric]
231
230
  attr_accessor :base_scalar
232
-
231
+
233
232
  # @return [Array]
234
233
  attr_accessor :base_numerator
235
-
234
+
236
235
  # @return [Array]
237
236
  attr_accessor :base_denominator
238
-
237
+
239
238
  # @return [String]
240
239
  attr_accessor :output
241
-
240
+
242
241
  # @return [String]
243
242
  attr_accessor :unit_name
244
243
 
@@ -265,7 +264,7 @@ class Unit < Numeric
265
264
 
266
265
  if RUBY_VERSION < "1.9"
267
266
  # :nocov_19:
268
-
267
+
269
268
  # a list of properties to emit to yaml
270
269
  # @return [Array]
271
270
  def to_yaml_properties
@@ -370,11 +369,11 @@ class Unit < Numeric
370
369
  unary_unit = self.units || ""
371
370
  if options.first.instance_of?(String)
372
371
  opt_scalar, opt_units = Unit.parse_into_numbers_and_units(options[0])
373
- unless @@cached_units.keys.include?(opt_units) || (opt_units =~ /(#{TEMP_REGEX})|(pounds|lbs[ ,]\d+ ounces|oz)|('\d+")|(ft|feet[ ,]\d+ in|inch|inches)|%|(#{TIME_REGEX})|i\s?(.+)?|&plusmn;|\+\/-/)
372
+ unless @@cached_units.keys.include?(opt_units) || (opt_units =~ /(#{Unit.temp_regex})|(pounds|lbs[ ,]\d+ ounces|oz)|('\d+")|(ft|feet[ ,]\d+ in|inch|inches)|%|(#{TIME_REGEX})|i\s?(.+)?|&plusmn;|\+\/-/)
374
373
  @@cached_units[opt_units] = (self.scalar == 1 ? self : opt_units.unit) if opt_units && !opt_units.empty?
375
374
  end
376
375
  end
377
- unless @@cached_units.keys.include?(unary_unit) || (unary_unit =~ /#{TEMP_REGEX}/) then
376
+ unless @@cached_units.keys.include?(unary_unit) || (unary_unit =~ /#{Unit.temp_regex}/) then
378
377
  @@cached_units[unary_unit] = (self.scalar == 1 ? self : unary_unit.unit)
379
378
  end
380
379
  [@scalar, @numerator, @denominator, @base_scalar, @signature, @is_base].each {|x| x.freeze}
@@ -441,7 +440,7 @@ class Unit < Numeric
441
440
  # @todo this is brittle as it depends on the display_name of a unit, which can be changed
442
441
  def to_base
443
442
  return self if self.is_base?
444
- if self.units =~ /\A(?:temp|deg)[CRF]\Z/
443
+ if @@UNIT_MAP[self.units] =~ /\A<(?:temp|deg)[CRF]>\Z/
445
444
  if RUBY_VERSION < "1.9"
446
445
  # :nocov_19:
447
446
  @signature = @@KINDS.index(:temperature)
@@ -563,7 +562,7 @@ class Unit < Numeric
563
562
  # @return [Boolean]
564
563
  # @todo use unit definition to determine if it's a temperature instead of a regex
565
564
  def is_temperature?
566
- return self.is_degree? && (!(self.units =~ /temp[CFRK]/).nil?)
565
+ return self.is_degree? && (!(@@UNIT_MAP[self.units] =~ /temp[CFRK]/).nil?)
567
566
  end
568
567
  alias :temperature? :is_temperature?
569
568
 
@@ -579,7 +578,7 @@ class Unit < Numeric
579
578
  # @return [String] possible values: degC, degF, degR, or degK
580
579
  def temperature_scale
581
580
  return nil unless self.is_temperature?
582
- return "deg#{self.units[/temp([CFRK])/,1]}"
581
+ return "deg#{@@UNIT_MAP[self.units][/temp([CFRK])/,1]}"
583
582
  end
584
583
 
585
584
  # returns true if no associated units
@@ -946,25 +945,25 @@ class Unit < Numeric
946
945
  start_unit = self.units
947
946
  target_unit = other.units rescue other
948
947
  unless @base_scalar
949
- @base_scalar = case start_unit
950
- when 'tempC'
948
+ @base_scalar = case @@UNIT_MAP[start_unit]
949
+ when '<tempC>'
951
950
  @scalar + 273.15
952
- when 'tempK'
951
+ when '<tempK>'
953
952
  @scalar
954
- when 'tempF'
953
+ when '<tempF>'
955
954
  (@scalar+459.67)*Rational(5,9)
956
- when 'tempR'
955
+ when '<tempR>'
957
956
  @scalar*Rational(5,9)
958
957
  end
959
958
  end
960
- q= case target_unit
961
- when 'tempC'
959
+ q= case @@UNIT_MAP[target_unit]
960
+ when '<tempC>'
962
961
  @base_scalar - 273.15
963
- when 'tempK'
962
+ when '<tempK>'
964
963
  @base_scalar
965
- when 'tempF'
964
+ when '<tempF>'
966
965
  @base_scalar * Rational(9,5) - 459.67
967
- when 'tempR'
966
+ when '<tempR>'
968
967
  @base_scalar * Rational(9,5)
969
968
  end
970
969
  return Unit.new("#{q} #{target_unit}")
@@ -1025,6 +1024,12 @@ class Unit < Numeric
1025
1024
  raise RuntimeError, "Cannot convert '#{self.to_s}' to Rational unless unitless. Use Unit#scalar"
1026
1025
  end
1027
1026
 
1027
+ # Returns string formatted for json
1028
+ # @return [String]
1029
+ def as_json(*args)
1030
+ to_s
1031
+ end
1032
+
1028
1033
  # returns the 'unit' part of the Unit object without the scalar
1029
1034
  # @return [String]
1030
1035
  def units
@@ -1034,7 +1039,7 @@ class Unit < Numeric
1034
1039
  output_denominator = []
1035
1040
  num = @numerator.clone.compact
1036
1041
  den = @denominator.clone.compact
1037
-
1042
+
1038
1043
  if @numerator == UNITY_ARRAY
1039
1044
  output_numerator << "1"
1040
1045
  else
@@ -1042,11 +1047,11 @@ class Unit < Numeric
1042
1047
  if defn && defn.prefix?
1043
1048
  output_numerator << defn.display_name + Unit.definition(num.shift).display_name
1044
1049
  else
1045
- output_numerator << defn.display_name
1050
+ output_numerator << defn.display_name
1046
1051
  end
1047
1052
  end
1048
1053
  end
1049
-
1054
+
1050
1055
  if @denominator == UNITY_ARRAY
1051
1056
  output_denominator = []
1052
1057
  else
@@ -1054,11 +1059,11 @@ class Unit < Numeric
1054
1059
  if defn && defn.prefix?
1055
1060
  output_denominator << defn.display_name + Unit.definition(den.shift).display_name
1056
1061
  else
1057
- output_denominator << defn.display_name
1062
+ output_denominator << defn.display_name
1058
1063
  end
1059
1064
  end
1060
1065
  end
1061
-
1066
+
1062
1067
  on = output_numerator.uniq.
1063
1068
  map {|x| [x, output_numerator.count(x)]}.
1064
1069
  map {|element, power| ("#{element}".strip + (power > 1 ? "^#{power}" : ''))}
@@ -1098,9 +1103,9 @@ class Unit < Numeric
1098
1103
  end
1099
1104
 
1100
1105
  # @return [Numeric,Unit]
1101
- def round
1102
- return @scalar.round if self.unitless?
1103
- return Unit.new(@scalar.round, @numerator, @denominator)
1106
+ def round(ndigits = 0)
1107
+ return @scalar.round(ndigits) if self.unitless?
1108
+ return Unit.new(@scalar.round(ndigits), @numerator, @denominator)
1104
1109
  end
1105
1110
 
1106
1111
  # @return [Numeric, Unit]
@@ -1362,6 +1367,9 @@ class Unit < Numeric
1362
1367
  if unit_string =~ /\$\s*(#{NUMBER_REGEX})/
1363
1368
  unit_string = "#{$1} USD"
1364
1369
  end
1370
+
1371
+ unit_string.gsub!("\xC2\xB0".force_encoding('utf-8'), 'deg') unless RUBY_VERSION < '1.9'
1372
+
1365
1373
  unit_string.gsub!(/%/,'percent')
1366
1374
  unit_string.gsub!(/'/,'feet')
1367
1375
  unit_string.gsub!(/"/,'inch')
@@ -1474,7 +1482,7 @@ class Unit < Numeric
1474
1482
  @denominator = UNITY_ARRAY if @denominator.empty?
1475
1483
  return self
1476
1484
  end
1477
-
1485
+
1478
1486
  # return an array of base units
1479
1487
  # @return [Array]
1480
1488
  def self.base_units
@@ -1496,7 +1504,7 @@ class Unit < Numeric
1496
1504
  complex = %r{#{sci}{2,2}i}
1497
1505
  anynumber = %r{(?:(#{complex}|#{rational}|#{sci})\b)?\s?([\D].*)?}
1498
1506
  num, unit = string.scan(anynumber).first
1499
-
1507
+
1500
1508
  return [case num
1501
1509
  when NilClass
1502
1510
  1
@@ -1514,7 +1522,7 @@ class Unit < Numeric
1514
1522
  num.to_f
1515
1523
  end, unit.to_s.strip]
1516
1524
  end
1517
-
1525
+
1518
1526
  # return a fragment of a regex to be used for matching units or reconstruct it if hasn't been used yet.
1519
1527
  # Unit names are reverse sorted by length so the regexp matcher will prefer longer and more specific names
1520
1528
  # @return [String]
@@ -1522,7 +1530,7 @@ class Unit < Numeric
1522
1530
  def self.unit_regex
1523
1531
  @@UNIT_REGEX ||= @@UNIT_MAP.keys.sort_by {|unit_name| [unit_name.length, unit_name]}.reverse.join('|')
1524
1532
  end
1525
-
1533
+
1526
1534
  # return a regex used to match units
1527
1535
  # @return [RegExp]
1528
1536
  # @private
@@ -1536,11 +1544,21 @@ class Unit < Numeric
1536
1544
  def self.prefix_regex
1537
1545
  return @@PREFIX_REGEX ||= @@PREFIX_MAP.keys.sort_by {|prefix| [prefix.length, prefix]}.reverse.join('|')
1538
1546
  end
1539
-
1547
+
1548
+ def self.temp_regex
1549
+ @@TEMP_REGEX ||= Regexp.new "(?:#{
1550
+ temp_units=%w(tempK tempC tempF tempR degK degC degF degR)
1551
+ aliases=temp_units.map{|unit| d=Unit.definition(unit); d && d.aliases}.flatten.compact
1552
+ regex_str= aliases.empty? ? '(?!x)x' : aliases.join('|')
1553
+ regex_str
1554
+ })"
1555
+ end
1556
+
1540
1557
  # inject a definition into the internal array and set it up for use
1541
1558
  # @private
1542
1559
  def self.use_definition(definition)
1543
1560
  @@UNIT_MATCH_REGEX = nil #invalidate the unit match regex
1561
+ @@TEMP_REGEX = nil #invalidate the temp regex
1544
1562
  if definition.prefix?
1545
1563
  @@PREFIX_VALUES[definition.name] = definition.scalar
1546
1564
  definition.aliases.each {|_alias| @@PREFIX_MAP[_alias] = definition.name }
@@ -237,7 +237,7 @@ end
237
237
 
238
238
  Unit.define('fluid-ounce') do |floz|
239
239
  floz.definition = Unit('1/128 gal')
240
- floz.aliases = %w{floz fluid-ounce}
240
+ floz.aliases = %w{floz fluid-ounce fluid-ounces}
241
241
  end
242
242
 
243
243
  Unit.define('tablespoon') do |tbsp|
@@ -278,7 +278,7 @@ end
278
278
 
279
279
  Unit.define('gee') do |gee|
280
280
  # approximated as a rational number to minimize round-off errors
281
- gee.definition = Unit(Rational(196131,20000), 'm/s^2') # equivalent to 9.80655 m/s^2
281
+ gee.definition = Unit(Rational(196133,20000), 'm/s^2') # equivalent to 9.80665 m/s^2
282
282
  gee.aliases = %w{gee standard-gravitation}
283
283
  end
284
284
 
@@ -702,4 +702,4 @@ end
702
702
 
703
703
  Unit.define('ppb') do |ppb|
704
704
  ppb.definition = Unit(1) / 1_000_000_000
705
- end
705
+ end
data/ruby-units.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "ruby-units"
8
- s.version = "1.4.1"
8
+ s.version = "1.4.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kevin Olbrich, Ph.D."]
12
- s.date = "2012-05-13"
12
+ s.date = "2012-09-16"
13
13
  s.description = "Provides classes and methods to perform unit math and conversions"
14
14
  s.email = ["kevin.olbrich+ruby_units@gmail.com"]
15
15
  s.extra_rdoc_files = [
@@ -62,8 +62,6 @@ Gem::Specification.new do |s|
62
62
  s.add_development_dependency(%q<jeweler>, [">= 0"])
63
63
  s.add_development_dependency(%q<rspec>, ["~> 2.5"])
64
64
  s.add_development_dependency(%q<autotest>, [">= 0"])
65
- s.add_development_dependency(%q<autotest-growl>, [">= 0"])
66
- s.add_development_dependency(%q<autotest-fsevent>, [">= 0"])
67
65
  else
68
66
  s.add_dependency(%q<bundler>, ["~> 1.0"])
69
67
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -72,8 +70,6 @@ Gem::Specification.new do |s|
72
70
  s.add_dependency(%q<jeweler>, [">= 0"])
73
71
  s.add_dependency(%q<rspec>, ["~> 2.5"])
74
72
  s.add_dependency(%q<autotest>, [">= 0"])
75
- s.add_dependency(%q<autotest-growl>, [">= 0"])
76
- s.add_dependency(%q<autotest-fsevent>, [">= 0"])
77
73
  end
78
74
  else
79
75
  s.add_dependency(%q<bundler>, ["~> 1.0"])
@@ -83,8 +79,6 @@ Gem::Specification.new do |s|
83
79
  s.add_dependency(%q<jeweler>, [">= 0"])
84
80
  s.add_dependency(%q<rspec>, ["~> 2.5"])
85
81
  s.add_dependency(%q<autotest>, [">= 0"])
86
- s.add_dependency(%q<autotest-growl>, [">= 0"])
87
- s.add_dependency(%q<autotest-fsevent>, [">= 0"])
88
82
  end
89
83
  end
90
84
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-units
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
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: 2012-05-13 00:00:00.000000000 Z
12
+ date: 2012-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -123,38 +123,6 @@ dependencies:
123
123
  - - ! '>='
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: autotest-growl
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ! '>='
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ! '>='
140
- - !ruby/object:Gem::Version
141
- version: '0'
142
- - !ruby/object:Gem::Dependency
143
- name: autotest-fsevent
144
- requirement: !ruby/object:Gem::Requirement
145
- none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
150
- type: :development
151
- prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ! '>='
156
- - !ruby/object:Gem::Version
157
- version: '0'
158
126
  description: Provides classes and methods to perform unit math and conversions
159
127
  email:
160
128
  - kevin.olbrich+ruby_units@gmail.com
@@ -240,6 +208,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
240
208
  - - ! '>='
241
209
  - !ruby/object:Gem::Version
242
210
  version: '0'
211
+ segments:
212
+ - 0
213
+ hash: -3013548990298419513
243
214
  required_rubygems_version: !ruby/object:Gem::Requirement
244
215
  none: false
245
216
  requirements: