A Crystal lang library for unit measurement conversion and math.
Add this to your application's shard.yml
:
dependencies:
crunits:
github: spider-gazelle/crunits
For an over the top example, consider a car (2800 lb) completing the quarter mile in 10 seconds (with uniform acceleration).
require "crunits"
distance = Units::Measurement.new(0.25, "mile", :name) # => #<Units::Measurement value=0.25 unit=[mi_i] (mile)>
time = Units::Measurement.new(10, "second", :name) # => #<Units::Measurement value=10 unit=s (second)>
mass = Units::Measurement.new(2800, "pound", :name) # => #<Units::Measurement value=2800 unit=kg (kilogram)>
acceleration = distance * 2 / (time ** 2)
# => #<Units::Measurement value=0.005 unit=[mi_i]/s2 (mile/second2)>
force = (mass * acceleration).convert_to("lbf", :symbol)
# => #<Units::Measurement value=2297.50383668 unit=[lbf_av] (pound force)>
power = (force * distance / time).convert_to("horsepower", :name)
# => #<Units::Measurement value=551.40092080 unit=[HP] (horsepower)>
It has the ability to compare measurements with the same or different units.
Units::Measurement.new(12, "inch", :name) == Units::Measurement.new(1, "foot", :name)
Units::Measurement.new(1, "meter", :name) > Units::Measurement.new(1, "yard", :name) # => true
Again, you have to compare compatible units. For example, comparing two temperatures will work, comparing a mass to a length would fail.
You can use shorthand for SI units.
Units::Measurement.new(1000, "m") == Units::Measurement.new(1, "km") # => true
Units::Measurement.new(1, "ml") == Units::Measurement.new(0.001, "l") # => true
Units can be combined to make more complex ones. There is nothing special about them -- they can still be converted, compared, or operated on.
speed = Units::Measurement.new(60, "mile/hour", :name)
# => #<Units::Measurement value=60 unit=[mi_i]/h (mile/hour)>
speed.convert_to("m/s")
# => #<Units::Measurement value=26.8224 unit=m/s (meter/second)>
You can add or subtract compatible measurements.
Units::Measurement.new(2.0, "meter", :name) + Units::Measurement.new(3.0, "inch", :name) - Units::Measurement.new(1.0, "yard", :name)
# => #<Units::Measurement value=1.1618 unit=m (meter)>
You can multiply or divide measurements and numbers.
Units::Measurement.new(110, "volt", :name) * 2
# => #<Units::Measurement value=220 unit=V (volt)>
You can multiply or divide measurements with measurements.
Units::Measurement.new(20, "mg") / Units::Measurement.new(1, "l")
# => #<Units::Measurement value=20 unit=mg/l (milligram/liter)>
Exponentiation is also supported.
(Units::Measurement.new(10, "cm") ** 3).convert_to("liter", :name)
# => #<Units::Measurement value=1 unit=l (liter)>
inspired by Unitwise Ruby gem