lib/ruby-units.rb in ruby-units-0.3.3 vs lib/ruby-units.rb in ruby-units-0.3.4

- old
+ new

@@ -195,11 +195,12 @@ return end case options[0] - when String: parse(options[0]) + when "": raise ArgumentError, "No Unit Specified" + when String: parse(options[0]) when Hash: @scalar = options[0][:scalar] || 1 @numerator = options[0][:numerator] || UNITY_ARRAY @denominator = options[0][:denominator] || UNITY_ARRAY @signature = options[0][:signature] @@ -221,13 +222,13 @@ raise ArgumentError, "Invalid Unit Format" end self.update_base_scalar self.replace_temperature - unary_unit = self.units + unary_unit = self.units || "" opt_units = options[0].scan(NUMBER_REGEX)[0][1] if String === options[0] - unless @@cached_units.keys.include?(opt_units) || (opt_units =~ /(temp|deg)(C|K|R|F)/) + unless @@cached_units.keys.include?(opt_units) || (opt_units =~ /(temp|deg(C|K|R|F))|(pounds|lbs[ ,]\d+ ounces|oz)|('\d+")|(ft|feet[ ,]\d+ in|inch|inches)|%/) @@cached_units[opt_units] = (self.scalar == 1 ? self : opt_units.unit) if opt_units && !opt_units.empty? end unless @@cached_units.keys.include?(unary_unit) || (unary_unit =~ /(temp|deg)(C|K|R|F)/) then @@cached_units[unary_unit] = (self.scalar == 1 ? self : unary_unit.unit) end @@ -781,10 +782,18 @@ def succ raise ArgumentError, "Non Integer Scalar" unless @scalar == @scalar.to_i q = @scalar.to_i.succ Unit.new(q, @numerator, @denominator) end + + def coerce(other) + case other + when Unit : [other, self] + else + [Unit.new(other), self] + end + end # Protected and Private Functions that should only be called from this class protected @@ -799,17 +808,10 @@ @signature = base.signature end end - def coerce(other) - case other - when Unit : [other, self] - else - [Unit.new(other), self] - end - end # calculates the unit signature vector used by unit_signature def unit_signature_vector return self.to_base.unit_signature_vector unless self.is_base? @@ -925,17 +927,16 @@ # "1" -- creates a unitless constant with value 1 # "GPa" -- creates a unit with scalar 1 with units 'GPa' # 6'4" -- recognized as 6 feet + 4 inches # 8 lbs 8 oz -- recognized as 8 lbs + 8 ounces def parse(passed_unit_string="0") - unit_string = passed_unit_string.dup if unit_string =~ /\$\s*(#{NUMBER_REGEX})/ unit_string = "#{$1} USD" end - if unit_string =~ /(#{SCI_NUMBER})\s*%/ - unit_string = "#{$1} percent" + if unit_string =~ /(.+)%/ + unit_string = "#{$1.to_f * 0.01}" end unit_string =~ NUMBER_REGEX unit = @@cached_units[$2] mult = ($1.empty? ? 1.0 : $1.to_f) rescue 1.0 @@ -945,27 +946,31 @@ @base_scalar *= mult return self end unit_string.gsub!(/[<>]/,"") - + # Special processing for unusual unit strings # feet -- 6'5" feet, inches = unit_string.scan(FEET_INCH_REGEX)[0] if (feet && inches) result = Unit.new("#{feet} ft") + Unit.new("#{inches} inches") copy(result) - return self + return #self end # weight -- 8 lbs 12 oz pounds, oz = unit_string.scan(LBS_OZ_REGEX)[0] if (pounds && oz) result = Unit.new("#{pounds} lbs") + Unit.new("#{oz} oz") copy(result) - return self + return #self end + + raise( ArgumentError, "'#{passed_unit_string}' Unit not recognized") if unit_string.count('/') > 1 + raise( ArgumentError, "'#{passed_unit_string}' Unit not recognized") if unit_string.scan(/\s\d+\S*/).size > 0 + @scalar, top, bottom = unit_string.scan(UNIT_STRING_REGEX)[0] #parse the string into parts top.scan(TOP_REGEX).each do |item| n = item[1].to_i x = "#{item[0]} " @@ -981,11 +986,12 @@ @numerator ||= UNITY_ARRAY @denominator ||= UNITY_ARRAY @numerator = top.scan(@@UNIT_MATCH_REGEX).delete_if {|x| x.empty?}.compact if top @denominator = bottom.scan(@@UNIT_MATCH_REGEX).delete_if {|x| x.empty?}.compact if bottom us = "#{(top || '' + bottom || '')}".to_s.gsub(@@UNIT_MATCH_REGEX,'').gsub(/[\d\*, "'_^\/\$]/,'') - raise( ArgumentError, "'#{passed_unit_string}' Unit not recognized (#{us})") unless us.empty? + + raise( ArgumentError, "'#{passed_unit_string}' Unit not recognized") unless us.empty? @numerator = @numerator.map do |item| @@PREFIX_MAP[item[0]] ? [@@PREFIX_MAP[item[0]], @@UNIT_MAP[item[1]]] : [@@UNIT_MAP[item[1]]] end.flatten.compact.delete_if {|x| x.empty?} @@ -1040,10 +1046,14 @@ def inspect(raw = false) return self.units_datetime_inspect if raw self.to_s end + def to_date + Date.civil(self.year, self.month, self.day) + end + end class Object def Unit(*other) other.to_unit @@ -1197,11 +1207,17 @@ Date.civil(1970,1,1)+(self.to_f+self.gmt_offset)/86400 end def +(other) case other - when Unit: unit_add(other.to('s').scalar) + when Unit: + other = other.to('d').round.to('s') if ['y', 'decade', 'century'].include? other.units + begin + unit_add(other.to('s').scalar) + rescue RangeError + self.to_datetime + other + end when DateTime: unit_add(other.to_time) else unit_add(other) end end @@ -1212,10 +1228,17 @@ end alias :unit_sub :- def -(other) case other - when Unit: unit_sub(other.to('s').scalar) + when Unit: + other = other.to('d').round.to('s') if ['y', 'decade', 'century'].include? other.units + begin + unit_sub(other.to('s').scalar) + rescue RangeError + self.to_datetime - other + end + when DateTime: unit_sub(other.to_time) else unit_sub(other) end end