ruby-units 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +4 -0
- data/README.txt +34 -2
- data/lib/ruby_units/ruby-units.rb +90 -51
- data/lib/ruby_units/units.rb +9 -9
- data/test/test_ruby-units.rb +34 -53
- metadata +3 -3
data/CHANGELOG.txt
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
Change Log for Ruby-units
|
2
2
|
=========================
|
3
|
+
2007-01-28 1.1.0 * completely revamped the temperature handling system (see README)
|
4
|
+
* fixed some spelling errors in some units
|
5
|
+
* fixed to_datetime and to_date to convert durations to datetimes and dates'
|
6
|
+
|
3
7
|
2007-01-24 1.0.2 * Minor changes in the way powers are calculated to support Uncertain
|
4
8
|
numbers better.
|
5
9
|
* Fixed parsing bug with Uncertain Numbers
|
data/README.txt
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
=Ruby Units
|
2
2
|
|
3
|
-
Version: 1.0.1
|
4
|
-
|
5
3
|
Kevin C. Olbrich, Ph.D.
|
6
4
|
kevin.olbrich@gmail.com
|
7
5
|
|
@@ -139,3 +137,37 @@ works so long as the starting point has an integer scalar
|
|
139
137
|
All Trig math functions (sin, cos, sinh, hypot...) can take a unit as their parameter.
|
140
138
|
It will be converted to radians and then used if possible.
|
141
139
|
|
140
|
+
==Temperatures
|
141
|
+
Ruby-units makes a distinction between a temperature (which technically is a property) and
|
142
|
+
degrees of temperature (which temperatures are measured in).
|
143
|
+
|
144
|
+
Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account
|
145
|
+
the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC'.unit)
|
146
|
+
units behave like most other units.
|
147
|
+
|
148
|
+
'37 tempC'.unit >> 'tempF' #=> 98.6 tempF
|
149
|
+
|
150
|
+
Ruby-units will raise an exception if you attempt to create a temperature unit that would
|
151
|
+
fall below absolute zero.
|
152
|
+
|
153
|
+
Unit math on temperatures is fairly limited.
|
154
|
+
|
155
|
+
'100 tempC'.unit + '10 degC'.unit #=> '110 tempC'.unit
|
156
|
+
'100 tempC'.unit - '10 degC'.unit #=> '90 tempC'.unit
|
157
|
+
'100 tempC'.unit + '50 tempC'.unit #=> exception
|
158
|
+
'100 tempC'.unit - '50 tempC'.unit #=> '50 degC'.unit
|
159
|
+
'50 tempC'.unit - '100 tempC'.unit #=> '-50 degC'.unit
|
160
|
+
'100 tempC'.unit * [scalar] #=> '100*scalar tempC'.unit
|
161
|
+
'100 tempC'.unit / [scalar] #=> '100/scalar tempC'.unit
|
162
|
+
'100 tempC'.unit * [unit] #=> exception
|
163
|
+
'100 tempC'.unit / [unit] #=> exception
|
164
|
+
'100 tempC'.unit ** N #=> exception
|
165
|
+
|
166
|
+
'100 tempC'.unit >> 'degC' #=> '100 degC'.unit
|
167
|
+
This conversion references the 0 point on the scale of the temperature unit
|
168
|
+
|
169
|
+
'100 degC'.unit >> 'tempC' #=> '-173 tempC'.unit
|
170
|
+
These conversions are always interpreted as being relative to absolute zero.
|
171
|
+
Conversions are probably better done like this...
|
172
|
+
'0 tempC'.unit + '100 degC'.unit #=> '100 tempC'.unit
|
173
|
+
|
@@ -3,18 +3,6 @@ require 'rational'
|
|
3
3
|
require 'date'
|
4
4
|
require 'parsedate'
|
5
5
|
|
6
|
-
|
7
|
-
=begin
|
8
|
-
require 'math'
|
9
|
-
|
10
|
-
require 'object_class'
|
11
|
-
require 'array_class'
|
12
|
-
require 'string_class'
|
13
|
-
require 'date_class'
|
14
|
-
require 'time_class'
|
15
|
-
require 'numeric_class'
|
16
|
-
=end
|
17
|
-
|
18
6
|
# = Ruby Units
|
19
7
|
#
|
20
8
|
# Copyright 2006 by Kevin C. Olbrich, Ph.D.
|
@@ -52,14 +40,14 @@ require 'numeric_class'
|
|
52
40
|
# Unit.setup
|
53
41
|
class Unit < Numeric
|
54
42
|
# pre-generate hashes from unit definitions for performance.
|
55
|
-
VERSION = '1.0
|
43
|
+
VERSION = '1.1.0'
|
56
44
|
@@USER_DEFINITIONS = {}
|
57
45
|
@@PREFIX_VALUES = {}
|
58
46
|
@@PREFIX_MAP = {}
|
59
47
|
@@UNIT_MAP = {}
|
60
48
|
@@UNIT_VALUES = {}
|
61
49
|
@@OUTPUT_MAP = {}
|
62
|
-
@@BASE_UNITS = ['<meter>','<kilogram>','<second>','<mole>', '<farad>', '<ampere>','<radian>','<kelvin>','<byte>','<dollar>','<candela>','<each>','<steradian>','<decibel>']
|
50
|
+
@@BASE_UNITS = ['<meter>','<kilogram>','<second>','<mole>', '<farad>', '<ampere>','<radian>','<kelvin>','<temp-K>','<byte>','<dollar>','<candela>','<each>','<steradian>','<decibel>']
|
63
51
|
UNITY = '<1>'
|
64
52
|
UNITY_ARRAY= [UNITY]
|
65
53
|
FEET_INCH_REGEX = /(\d+)\s*(?:'|ft|feet)\s*(\d+)\s*(?:"|in|inches)/
|
@@ -76,9 +64,9 @@ class Unit < Numeric
|
|
76
64
|
COMPLEX_REGEX = /#{COMPLEX_NUMBER}\s?(.+)?/
|
77
65
|
RATIONAL_REGEX = /#{RATIONAL_NUMBER}\s?(.+)?/
|
78
66
|
KELVIN = ['<kelvin>']
|
79
|
-
|
67
|
+
FAHRENHEIT = ['<fahrenheit>']
|
80
68
|
RANKINE = ['<rankine>']
|
81
|
-
|
69
|
+
CELSIUS = ['<celsius>']
|
82
70
|
|
83
71
|
SIGNATURE_VECTOR = [:length, :time, :temperature, :mass, :current, :substance, :luminosity, :currency, :memory, :angle, :capacitance]
|
84
72
|
@@KINDS = {
|
@@ -224,7 +212,6 @@ class Unit < Numeric
|
|
224
212
|
return
|
225
213
|
end
|
226
214
|
|
227
|
-
|
228
215
|
case options[0]
|
229
216
|
when Hash:
|
230
217
|
@scalar = options[0][:scalar] || 1
|
@@ -251,7 +238,8 @@ class Unit < Numeric
|
|
251
238
|
raise ArgumentError, "Invalid Unit Format"
|
252
239
|
end
|
253
240
|
self.update_base_scalar
|
254
|
-
self.
|
241
|
+
raise ArgumentError, "Temperature out of range" if self.is_temperature? && self.base_scalar < 0
|
242
|
+
|
255
243
|
|
256
244
|
unary_unit = self.units || ""
|
257
245
|
opt_units = options[0].scan(NUMBER_REGEX)[0][1] if String === options[0]
|
@@ -290,7 +278,7 @@ class Unit < Numeric
|
|
290
278
|
# Returns 'true' if the Unit is represented in base units
|
291
279
|
def is_base?
|
292
280
|
return @is_base if defined? @is_base
|
293
|
-
return @is_base=true if @signature == 400 &&
|
281
|
+
return @is_base=true if @signature == 400 && self.numerator.size == 1 && self.denominator == UNITY_ARRAY && self.units =~ /(deg|temp)K/
|
294
282
|
n = @numerator + @denominator
|
295
283
|
for x in n.compact do
|
296
284
|
return @is_base=false unless x == UNITY || (@@BASE_UNITS.include?((x)))
|
@@ -302,9 +290,18 @@ class Unit < Numeric
|
|
302
290
|
# results of the conversion are cached so subsequent calls to this will be fast
|
303
291
|
def to_base
|
304
292
|
return self if self.is_base?
|
305
|
-
|
293
|
+
if self.units =~ /\A(deg|temp)(C|F|K|C)\Z/
|
294
|
+
@signature = 400
|
295
|
+
base = case self.units
|
296
|
+
when /temp/ : self.to('tempK')
|
297
|
+
when /deg/ : self.to('degK')
|
298
|
+
end
|
299
|
+
return base
|
300
|
+
end
|
301
|
+
|
302
|
+
cached = ((@@base_unit_cache[self.units] * self.scalar) rescue nil)
|
306
303
|
return cached if cached
|
307
|
-
|
304
|
+
|
308
305
|
num = []
|
309
306
|
den = []
|
310
307
|
q = 1
|
@@ -385,6 +382,16 @@ class Unit < Numeric
|
|
385
382
|
self.to_s
|
386
383
|
end
|
387
384
|
|
385
|
+
def is_temperature?
|
386
|
+
return true if self.signature == 400 && self.units =~ /temp/
|
387
|
+
end
|
388
|
+
|
389
|
+
def temperature_scale
|
390
|
+
return nil unless self.is_temperature?
|
391
|
+
self.units =~ /temp(C|F|R|K)/
|
392
|
+
"deg#{$1}"
|
393
|
+
end
|
394
|
+
|
388
395
|
# returns true if no associated units
|
389
396
|
# false, even if the units are "unitless" like 'radians, each, etc'
|
390
397
|
def unitless?
|
@@ -449,8 +456,18 @@ class Unit < Numeric
|
|
449
456
|
case
|
450
457
|
when self.zero? : other.dup
|
451
458
|
when self =~ other :
|
452
|
-
|
453
|
-
|
459
|
+
raise ArgumentError, "Cannot add two temperatures" if (self.is_temperature? && other.is_temperature?)
|
460
|
+
if [self, other].any? {|x| x.is_temperature?}
|
461
|
+
case self.is_temperature?
|
462
|
+
when true:
|
463
|
+
Unit.new(:scalar => (self.scalar + other.to(self.temperature_scale).scalar), :numerator => @numerator, :denominator=>@denominator, :signature => @signature)
|
464
|
+
else
|
465
|
+
Unit.new(:scalar => (other.scalar + self.to(other.temperature_scale).scalar), :numerator => other.numerator, :denominator=>other.denominator, :signature => other.signature)
|
466
|
+
end
|
467
|
+
else
|
468
|
+
@q ||= ((@@cached_units[self.units].scalar / @@cached_units[self.units].base_scalar) rescue (self.units.unit.to_base.scalar))
|
469
|
+
Unit.new(:scalar=>(self.base_scalar + other.base_scalar)*@q, :numerator=>@numerator, :denominator=>@denominator, :signature => @signature)
|
470
|
+
end
|
454
471
|
else
|
455
472
|
raise ArgumentError, "Incompatible Units ('#{self}' not compatible with '#{other}')"
|
456
473
|
end
|
@@ -469,8 +486,17 @@ class Unit < Numeric
|
|
469
486
|
case
|
470
487
|
when self.zero? : -other.dup
|
471
488
|
when self =~ other :
|
472
|
-
|
473
|
-
|
489
|
+
case
|
490
|
+
when [self, other].all? {|x| x.is_temperature?} :
|
491
|
+
Unit.new(:scalar => (self.base_scalar - other.base_scalar), :numerator => KELVIN, :denominator => UNITY_ARRAY, :signature => @signature).to(self.temperature_scale)
|
492
|
+
when self.is_temperature? :
|
493
|
+
Unit.new(:scalar => (self.base_scalar - other.base_scalar), :numerator => ['<temp-K>'], :denominator => UNITY_ARRAY, :signature => @signature).to(self)
|
494
|
+
when other.is_temperature? :
|
495
|
+
raise ArgumentError, "Cannot subtract a temperature from a differential unit"
|
496
|
+
else
|
497
|
+
@q ||= ((@@cached_units[self.units].scalar / @@cached_units[self.units].base_scalar) rescue (self.units.unit.scalar/self.units.unit.to_base.scalar))
|
498
|
+
Unit.new(:scalar=>(self.base_scalar - other.base_scalar)*@q, :numerator=>@numerator, :denominator=>@denominator, :signature=>@signature)
|
499
|
+
end
|
474
500
|
else
|
475
501
|
raise ArgumentError, "Incompatible Units ('#{self}' not compatible with '#{other}')"
|
476
502
|
end
|
@@ -486,6 +512,7 @@ class Unit < Numeric
|
|
486
512
|
def *(other)
|
487
513
|
case other
|
488
514
|
when Unit
|
515
|
+
raise ArgumentError, "Cannot multiply by temperatures" if [other,self].any? {|x| x.is_temperature?}
|
489
516
|
opts = Unit.eliminate_terms(@scalar*other.scalar, @numerator + other.numerator ,@denominator + other.denominator)
|
490
517
|
opts.merge!(:signature => @signature + other.signature)
|
491
518
|
Unit.new(opts)
|
@@ -503,6 +530,7 @@ class Unit < Numeric
|
|
503
530
|
case other
|
504
531
|
when Unit
|
505
532
|
raise ZeroDivisionError if other.zero?
|
533
|
+
raise ArgumentError, "Cannot divide with temperatures" if [other,self].any? {|x| x.is_temperature?}
|
506
534
|
opts = Unit.eliminate_terms(@scalar/other.scalar, @numerator + other.denominator ,@denominator + other.numerator)
|
507
535
|
opts.merge!(:signature=> @signature - other.signature)
|
508
536
|
Unit.new(opts)
|
@@ -524,6 +552,7 @@ class Unit < Numeric
|
|
524
552
|
#
|
525
553
|
# For now, if a rational is passed in, it will be used, otherwise we are stuck with integers and certain floats < 1
|
526
554
|
def **(other)
|
555
|
+
raise ArgumentError, "Cannot exponentiate a temperature" if self.is_temperature?
|
527
556
|
if Numeric === other
|
528
557
|
return Unit("1") if other.zero?
|
529
558
|
return self if other == 1
|
@@ -546,6 +575,7 @@ class Unit < Numeric
|
|
546
575
|
|
547
576
|
# returns the unit raised to the n-th power. Integers only
|
548
577
|
def power(n)
|
578
|
+
raise ArgumentError, "Cannot raise a temperature to a power" if self.is_temperature?
|
549
579
|
raise ArgumentError, "Can only use Integer exponenents" unless Integer === n
|
550
580
|
return self if n == 1
|
551
581
|
return Unit("1") if n == 0
|
@@ -560,6 +590,7 @@ class Unit < Numeric
|
|
560
590
|
# Calculates the n-th root of a unit, where n = (1..9)
|
561
591
|
# if n < 0, returns 1/unit^(1/n)
|
562
592
|
def root(n)
|
593
|
+
raise ArgumentError, "Cannot take the root of a temperature" if self.is_temperature?
|
563
594
|
raise ArgumentError, "Exponent must an Integer" unless Integer === n
|
564
595
|
raise ArgumentError, "0th root undefined" if n == 0
|
565
596
|
return self if n == 1
|
@@ -602,7 +633,7 @@ class Unit < Numeric
|
|
602
633
|
#
|
603
634
|
# Special handling for temperature conversions is supported. If the Unit object is converted
|
604
635
|
# from one temperature unit to another, the proper temperature offsets will be used.
|
605
|
-
# Supports Kelvin, Celcius,
|
636
|
+
# Supports Kelvin, Celcius, fahrenheit, and Rankine scales.
|
606
637
|
#
|
607
638
|
# Note that if temperature is part of a compound unit, the temperature will be treated as a differential
|
608
639
|
# and the units will be scaled appropriately.
|
@@ -610,45 +641,63 @@ class Unit < Numeric
|
|
610
641
|
return self if other.nil?
|
611
642
|
return self if TrueClass === other
|
612
643
|
return self if FalseClass === other
|
613
|
-
if (Unit === other && other.
|
614
|
-
raise ArgumentError, "Receiver is not a temperature unit" unless self.signature==400
|
644
|
+
if (Unit === other && other.is_temperature?) || (String === other && other =~ /temp(K|C|R|F)/)
|
645
|
+
raise ArgumentError, "Receiver is not a temperature unit" unless self.signature == 400
|
615
646
|
start_unit = self.units
|
616
647
|
target_unit = other.units rescue other
|
648
|
+
unless @base_scalar
|
649
|
+
@base_scalar = case start_unit
|
650
|
+
when 'tempC' : @scalar + 273.15
|
651
|
+
when 'tempK' : @scalar
|
652
|
+
when 'tempF' : (@scalar+459.67)*(5.0/9.0)
|
653
|
+
when 'tempR' : @scalar*(5.0/9.0)
|
654
|
+
end
|
655
|
+
end
|
656
|
+
q= case target_unit
|
657
|
+
when 'tempC' : @base_scalar - 273.15
|
658
|
+
when 'tempK' : @base_scalar
|
659
|
+
when 'tempF' : @base_scalar * (9.0/5.0) - 459.67
|
660
|
+
when 'tempR' : @base_scalar * (9.0/5.0)
|
661
|
+
end
|
662
|
+
|
663
|
+
=begin
|
617
664
|
q=case start_unit
|
618
|
-
when
|
665
|
+
when /\A(temp|deg)C\Z/:
|
619
666
|
case target_unit
|
620
667
|
when 'tempC' : @scalar
|
621
668
|
when 'tempK' : @scalar + 273.15
|
622
669
|
when 'tempF' : @scalar * (9.0/5.0) + 32.0
|
623
670
|
when 'tempR' : @scalar * (9.0/5.0) + 491.67
|
624
671
|
end
|
625
|
-
when
|
672
|
+
when /\A(temp|deg)K\Z/:
|
626
673
|
case target_unit
|
627
674
|
when 'tempC' : @scalar - 273.15
|
628
675
|
when 'tempK' : @scalar
|
629
676
|
when 'tempF' : @scalar * (9.0/5.0) - 459.67
|
630
677
|
when 'tempR' : @scalar * (9.0/5.0)
|
631
678
|
end
|
632
|
-
when
|
679
|
+
when /\A(temp|deg)F\Z/:
|
633
680
|
case target_unit
|
634
681
|
when 'tempC' : (@scalar-32)*(5.0/9.0)
|
635
682
|
when 'tempK' : (@scalar+459.67)*(5.0/9.0)
|
636
683
|
when 'tempF' : @scalar
|
637
684
|
when 'tempR' : @scalar + 459.67
|
638
685
|
end
|
639
|
-
when
|
686
|
+
when /\A(temp|deg)R\Z/:
|
640
687
|
case target_unit
|
641
688
|
when 'tempC' : @scalar*(5.0/9.0) -273.15
|
642
689
|
when 'tempK' : @scalar*(5.0/9.0)
|
643
690
|
when 'tempF' : @scalar - 459.67
|
644
691
|
when 'tempR' : @scalar
|
645
692
|
end
|
693
|
+
|
646
694
|
else
|
647
695
|
return self.to_base.to(other) unless self.is_base?
|
648
696
|
#raise ArgumentError, "Unknown temperature conversion requested #{self.numerator}"
|
649
697
|
end
|
650
|
-
|
651
|
-
|
698
|
+
=end
|
699
|
+
#target_unit =~ /temp(C|K|F|R)/
|
700
|
+
Unit.new("#{q} #{target_unit}")
|
652
701
|
else
|
653
702
|
case other
|
654
703
|
when Unit:
|
@@ -726,9 +775,9 @@ class Unit < Numeric
|
|
726
775
|
|
727
776
|
# negates the scalar of the Unit
|
728
777
|
def -@
|
778
|
+
#raise ArgumentError, "Cannot negate an absolute temperature" if self.is_temperature? && ['degK','degR'].include?(self.temperature_scale)
|
729
779
|
return -@scalar if self.unitless?
|
730
|
-
|
731
|
-
-1 * self.dup
|
780
|
+
self.dup * -1
|
732
781
|
end
|
733
782
|
|
734
783
|
# returns abs of scalar, without the units
|
@@ -767,7 +816,11 @@ class Unit < Numeric
|
|
767
816
|
# convert a duration to a DateTime. This will work so long as the duration is the duration from the zero date
|
768
817
|
# defined by DateTime
|
769
818
|
def to_datetime
|
770
|
-
DateTime.
|
819
|
+
DateTime.new0(self.to('d').scalar)
|
820
|
+
end
|
821
|
+
|
822
|
+
def to_date
|
823
|
+
Date.new0(self.to('d').scalar)
|
771
824
|
end
|
772
825
|
|
773
826
|
def round
|
@@ -892,20 +945,6 @@ class Unit < Numeric
|
|
892
945
|
end
|
893
946
|
vector
|
894
947
|
end
|
895
|
-
|
896
|
-
def replace_temperature
|
897
|
-
return self unless self.kind == :temperature && self.units =~ /temp(R|K|F|C)/
|
898
|
-
un = $1
|
899
|
-
@numerator = case un
|
900
|
-
when 'R' : RANKINE
|
901
|
-
when 'C' : CELCIUS
|
902
|
-
when 'F' : FARENHEIT
|
903
|
-
when 'K' : KELVIN
|
904
|
-
end
|
905
|
-
@unit_name = nil
|
906
|
-
r= self.to("tempK")
|
907
|
-
copy(r)
|
908
|
-
end
|
909
948
|
|
910
949
|
private
|
911
950
|
|
data/lib/ruby_units/units.rb
CHANGED
@@ -39,7 +39,7 @@ UNIT_DEFINITIONS = {
|
|
39
39
|
'<inch>' => [%w{in inch inches "}, 0.0254, :length, %w{<meter>}],
|
40
40
|
'<foot>' => [%w{ft foot feet '}, 0.3048, :length, %w{<meter>}],
|
41
41
|
'<yard>' => [%w{yd yard yards}, 0.9144, :length, %w{<meter>}],
|
42
|
-
'<mile>' => [%w{mi mile miles
|
42
|
+
'<mile>' => [%w{mi mile miles}, 1609.344, :length, %w{<meter>}],
|
43
43
|
'<naut-mile>' => [%w{nmi}, 1852, :length, %w{<meter>}],
|
44
44
|
'<league>'=> [%w{league leagues}, 4828, :length, %w{<meter>}],
|
45
45
|
'<furlong>'=> [%w{furlong furlongs}, 201.2, :length, %w{<meter>}],
|
@@ -93,14 +93,14 @@ UNIT_DEFINITIONS = {
|
|
93
93
|
'<gee>' => [%w{gee}, 9.80655, :acceleration, %w{<meter>}, %w{<second> <second>}],
|
94
94
|
|
95
95
|
#temperature_difference
|
96
|
-
'<kelvin>' => [%w{degK kelvin
|
97
|
-
'<
|
98
|
-
'<
|
99
|
-
'<rankine>' => [%w{degR rankine
|
100
|
-
'<temp-K>' => [%w{tempK}, 1.0, :temperature, %w{<
|
101
|
-
'<temp-C>' => [%w{tempC}, 1.0, :temperature, %w{<
|
102
|
-
'<temp-F>' => [%w{tempF}, 1.
|
103
|
-
'<temp-R>' => [%w{tempR}, 1.
|
96
|
+
'<kelvin>' => [%w{degK kelvin}, 1.0, :temperature, %w{<kelvin>}],
|
97
|
+
'<celsius>' => [%w{degC celsius celsius centigrade}, 1.0, :temperature, %w{<kelvin>}],
|
98
|
+
'<fahrenheit>' => [%w{degF fahrenheit}, 1/1.8, :temperature, %w{<kelvin>}],
|
99
|
+
'<rankine>' => [%w{degR rankine}, 1/1.8, :temperature, %w{<kelvin>}],
|
100
|
+
'<temp-K>' => [%w{tempK}, 1.0, :temperature, %w{<temp-K>}],
|
101
|
+
'<temp-C>' => [%w{tempC}, 1.0, :temperature, %w{<temp-K>}],
|
102
|
+
'<temp-F>' => [%w{tempF}, 1/1.8, :temperature, %w{<temp-K>}],
|
103
|
+
'<temp-R>' => [%w{tempR}, 1/1.8, :temperature, %w{<temp-K>}],
|
104
104
|
|
105
105
|
#time
|
106
106
|
'<second>'=> [%w{s sec second seconds}, 1.0, :time, %w{<second>}],
|
data/test/test_ruby-units.rb
CHANGED
@@ -9,7 +9,7 @@ require 'chronic'
|
|
9
9
|
|
10
10
|
class Unit < Numeric
|
11
11
|
@@USER_DEFINITIONS = {'<inchworm>' => [%w{inworm inchworm}, 0.0254, :length, %w{<meter>} ],
|
12
|
-
'<habenero>' => [%{degH}, 100, :temperature, %w{<
|
12
|
+
'<habenero>' => [%{degH}, 100, :temperature, %w{<celsius>}]}
|
13
13
|
Unit.setup
|
14
14
|
end
|
15
15
|
|
@@ -106,6 +106,7 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
106
106
|
assert_equal @april_fools.unit.to_time, @april_fools
|
107
107
|
assert_equal Time.in('1 day'), @april_fools + 86400
|
108
108
|
assert_equal @april_fools_datetime.inspect, "2006-04-01T12:00:00Z"
|
109
|
+
assert_equal '2453826.5 days'.unit.to_datetime.to_s, "2006-04-01T00:00:00Z"
|
109
110
|
end
|
110
111
|
|
111
112
|
def test_string_helpers
|
@@ -565,60 +566,40 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
565
566
|
end
|
566
567
|
|
567
568
|
def test_temperature_conversions
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
unit1 = Unit.new("37 degC")
|
574
|
-
unit2 = unit1 >> "tempF"
|
575
|
-
assert_in_delta 98.6, unit2.scalar, 0.1
|
576
|
-
unit2 = unit1 >> "tempK"
|
577
|
-
assert_in_delta 310.15, unit2.scalar, 0.01
|
578
|
-
unit2 = unit1 >> "tempR"
|
579
|
-
assert_in_delta 558.27, unit2.scalar, 0.01
|
580
|
-
unit3 = Unit.new("1 J/degC")
|
581
|
-
assert_in_delta 1, (unit3 >> "J/degK").scalar, 0.01
|
582
|
-
|
583
|
-
unit1 = Unit.new("98.6 degF")
|
584
|
-
unit2 = unit1 >> "tempC"
|
585
|
-
assert_in_delta 37, unit2.scalar, 0.1
|
586
|
-
unit2 = unit1 >> "tempK"
|
587
|
-
assert_in_delta 310.15, unit2.scalar, 0.01
|
588
|
-
unit2 = unit1 >> "tempR"
|
589
|
-
assert_in_delta 558.27, unit2.scalar, 0.01
|
590
|
-
unit3 = Unit.new("1 J/degC")
|
591
|
-
assert_in_delta 1, (unit3 >> "J/degK").scalar, 0.01
|
569
|
+
assert_raises(ArgumentError) { '-1 tempK'.unit}
|
570
|
+
assert_raises(ArgumentError) { '-1 tempR'.unit}
|
571
|
+
assert_raises(ArgumentError) { '-1000 tempC'.unit}
|
572
|
+
assert_raises(ArgumentError) { '-1000 tempF'.unit}
|
592
573
|
|
593
|
-
|
594
|
-
|
595
|
-
assert_in_delta
|
596
|
-
unit2 = unit1 >> "tempC"
|
597
|
-
assert_in_delta 37, unit2.scalar, 0.01
|
598
|
-
unit2 = unit1 >> "tempR"
|
599
|
-
assert_in_delta 558.27, unit2.scalar, 0.01
|
600
|
-
unit3 = Unit.new("1 J/degC")
|
601
|
-
assert_in_delta 1, (unit3 >> "J/degK").scalar, 0.01
|
574
|
+
assert_equal '0 tempC'.unit, '32 tempF'.unit
|
575
|
+
assert_equal '0 tempC'.unit, '273.15 tempK'.unit
|
576
|
+
assert_in_delta '0 tempC'.unit.base_scalar, '491.67 tempR'.unit.base_scalar, 0.01
|
602
577
|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
unit2 = unit1 >> "tempF"
|
609
|
-
assert_in_delta 98.6, unit2.scalar, 0.01
|
610
|
-
assert_in_delta 558.27, unit1.to("tempR").scalar, 0.01
|
611
|
-
unit3 = Unit.new("1 J/degC")
|
612
|
-
assert_in_delta 1, (unit3 >> "J/degK").scalar, 0.01
|
578
|
+
a = '10 degC'.unit
|
579
|
+
assert_equal a >> 'tempC', '-263.15 tempC'.unit
|
580
|
+
assert_equal a >> 'tempK', '10 tempK'.unit
|
581
|
+
assert_equal a >> 'tempR', '18 tempR'.unit
|
582
|
+
assert_equal a >> 'tempF', '-441.67 tempF'.unit
|
613
583
|
|
614
|
-
|
615
|
-
unit1 = Unit "37 degC"
|
616
|
-
unit2 = unit1 >> "degF" >> 'degK' >> 'degR' >> 'degC'
|
617
|
-
assert_equal unit2, unit1
|
618
|
-
|
619
|
-
unit1 = Unit "37 degC"
|
584
|
+
unit1 = '37 tempC'.unit
|
620
585
|
unit2 = unit1 >> "tempF" >> 'tempK' >> 'tempR' >> 'tempC'
|
621
|
-
assert_equal
|
586
|
+
assert_equal unit1 >> 'tempF' >> 'tempK' >> 'tempR' >> 'tempC', unit1
|
587
|
+
|
588
|
+
a = '100 tempF'.unit
|
589
|
+
b = '10 degC'.unit
|
590
|
+
c = '50 tempF'.unit
|
591
|
+
d = '18 degF'.unit
|
592
|
+
assert_equal a+b, '118 tempF'.unit
|
593
|
+
assert_equal b+a, '118 tempF'.unit
|
594
|
+
assert_equal a-b, '82 tempF'.unit
|
595
|
+
assert_in_delta (a-c).scalar, '50 degF'.unit.scalar, 0.01
|
596
|
+
assert_equal b+d, '20 degC'.unit
|
597
|
+
|
598
|
+
assert_raises(ArgumentError) { a * b }
|
599
|
+
assert_raises(ArgumentError) { a / b }
|
600
|
+
assert_raises(ArgumentError) { a ** 2 }
|
601
|
+
assert_raises(ArgumentError) { c - '400 degK'.unit}
|
602
|
+
assert_equal a, a.to('tempF')
|
622
603
|
end
|
623
604
|
|
624
605
|
def test_feet
|
@@ -702,8 +683,8 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
702
683
|
v = Unit "1 m^3"
|
703
684
|
n = Unit "1 mole"
|
704
685
|
r = Unit "8.31451 J/mol*degK"
|
705
|
-
t = ((p*v)/(n*r)).to(
|
706
|
-
assert_in_delta
|
686
|
+
t = ((p*v)/(n*r)).to('tempK')
|
687
|
+
assert_in_delta 12027.16,t.base_scalar, 0.1
|
707
688
|
end
|
708
689
|
|
709
690
|
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.1
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-units
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0
|
7
|
-
date: 2007-01-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2007-01-28 00:00:00 -05:00
|
8
8
|
summary: A model that performs unit conversions and unit math
|
9
9
|
require_paths:
|
10
10
|
- lib
|