{"id":13484240,"url":"https://github.com/olbrich/ruby-units","last_synced_at":"2025-03-27T16:30:35.625Z","repository":{"id":546027,"uuid":"176084","full_name":"olbrich/ruby-units","owner":"olbrich","description":"A unit handling library for ruby","archived":false,"fork":false,"pushed_at":"2025-01-01T19:22:50.000Z","size":1161,"stargazers_count":535,"open_issues_count":14,"forks_count":109,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-02-24T06:19:24.869Z","etag":null,"topics":["conversions","ruby","ruby-units","rubygems","temperature-units","unit-math"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/olbrich.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.txt","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2009-04-15T00:44:19.000Z","updated_at":"2025-02-23T14:19:22.000Z","dependencies_parsed_at":"2023-02-16T06:10:19.477Z","dependency_job_id":"f51d90e0-5d38-4871-9748-2c33b5bbb49c","html_url":"https://github.com/olbrich/ruby-units","commit_stats":{"total_commits":431,"total_committers":39,"mean_commits":"11.051282051282051","dds":0.3967517401392111,"last_synced_commit":"dcacf4a6fc5560cb70e31552b4d17c5c95b98ded"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olbrich%2Fruby-units","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olbrich%2Fruby-units/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olbrich%2Fruby-units/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olbrich%2Fruby-units/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/olbrich","download_url":"https://codeload.github.com/olbrich/ruby-units/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245383036,"owners_count":20606265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conversions","ruby","ruby-units","rubygems","temperature-units","unit-math"],"created_at":"2024-07-31T17:01:21.199Z","updated_at":"2025-03-27T16:30:35.164Z","avatar_url":"https://github.com/olbrich.png","language":"Ruby","funding_links":[],"categories":["Ruby","Measurements"],"sub_categories":[],"readme":"# Ruby Units\n\n[![Maintainability](https://api.codeclimate.com/v1/badges/4e858d14a07dd453f748/maintainability.svg)](https://codeclimate.com/github/olbrich/ruby-units/maintainability)\n[![CodeClimate Status](https://api.codeclimate.com/v1/badges/4e858d14a07dd453f748/test_coverage.svg)](https://codeclimate.com/github/olbrich/ruby-units/test_coverage)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Folbrich%2Fruby-units.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Folbrich%2Fruby-units?ref=badge_shield)\n\nKevin C. Olbrich, Ph.D.\n\nProject page:\n[http://github.com/olbrich/ruby-units](http://github.com/olbrich/ruby-units)\n\n## Introduction\n\nMany technical applications make use of specialized calculations at some point.\nFrequently, these calculations require unit conversions to ensure accurate\nresults. Needless to say, this is a pain to properly keep track of, and is prone\nto numerous errors.\n\n## Solution\n\nThe 'Ruby units' gem is designed to simplify the handling of units for\nscientific calculations. The units of each quantity are specified when a Unit\nobject is created and the Unit class will handle all subsequent conversions and\nmanipulations to ensure an accurate result.\n\n## Installation\n\nThis package may be installed using:\n\n```bash\ngem install ruby-units\n```\n\nor add this to your `Gemfile`\n\n```ruby\ngem 'ruby-units'\n```\n\n## Usage\n\n```ruby\nunit = Unit.new(\"1\")                 # constant only\nunit = Unit.new(\"mm\")                # unit only (defaults to a scalar of 1)\nunit = Unit.new(\"1 mm\")              # create a simple unit\nunit = Unit.new(\"1 mm/s\")            # a compound unit\nunit = Unit.new(\"1 mm s^-1\")         # in exponent notation\nunit = Unit.new(\"1 kg*m^2/s^2\")      # complex unit\nunit = Unit.new(\"1 kg m^2 s^-2\")     # complex unit\nunit = Unit.new(\"1 mm\")              # shorthand\nunit = \"1 mm\".to_unit                # convert string object\nunit = object.to_unit                # convert any object using object.to_s\nunit = Unit.new('1/4 cup')           # Rational number\nunit = Unit.new('1+1i mm')           # Complex Number\n```\n\n### Rules\n\n1. only 1 quantity per unit (with 2 exceptions... 6'5\" and '8 lbs 8 oz')\n2. use SI notation when possible\n3. spaces in units are allowed, but ones like '11/m' will be recognized as '11\n   1/m'.\n\n### Unit compatibility\n\nMany methods require that the units of two operands are compatible. Compatible\nunits are those that can be easily converted into each other, such as 'meters'\nand 'feet'.\n\n```ruby\nunit1 =~ unit2                  #=\u003e true if units are compatible\nunit1.compatible?(unit2)        #=\u003e true if units are compatible\n```\n\n### Unit Math\n\n```text\nUnit#+()      # Add. only works if units are compatible\nUnit#-()      # Subtract. only works if units are compatible\nUnit#*()      # Multiply.\nUnit#/()      # Divide.\nUnit#**()     # Exponentiate.  Exponent must be an integer, can be positive,  negative, or zero\nUnit#inverse  # Returns 1/unit\nUnit#abs      # Returns absolute value of the unit quantity.  Strips off the  units\nUnit#ceil     # rounds quantity to next highest integer\nUnit#floor    # rounds quantity down to next lower integer\nUnit#round    # rounds quantity to nearest integer\nUnit#to_int   # returns the quantity as an integer\n```\n\nUnit will coerce other objects into a Unit if used in a formula. This means...\n\n```ruby\nUnit.new(\"1 mm\") + \"2 mm\"  == Unit.new(\"3 mm\")\n```\n\nThis will work as expected so long as you start the formula with a `Unit`\nobject.\n\n### Conversions \u0026 Comparisons\n\nUnits can be converted to other units in a couple of ways.\n\n```ruby\nunit.convert_to('ft')             # convert\nunit1 = unit \u003e\u003e \"ft\"              # convert to 'feet'\nunit \u003e\u003e= \"ft\"                     # convert and overwrite original object\nunit3 = unit1 + unit2             # resulting object will have the units of unit1\nunit3 = unit1 - unit2             # resulting object will have the units of unit1\nunit1 \u003c=\u003e unit2                   # does comparison on quantities in base units, throws an exception if not compatible\nunit1 === unit2                   # true if units and quantity are the same, even if 'equivalent' by \u003c=\u003e\nunit1 + unit2 \u003e\u003e \"ft\"             # converts result of math to 'ft'\n(unit1 + unit2).convert_to('ft')  # converts result to 'ft'\n```\n\nAny object that defines a `to_unit` method will be automatically coerced to a\nunit during calculations.\n\n### Text Output\n\nUnits will display themselves nicely based on the display_name for the units and\nprefixes. Since `Unit` implements a `Unit#to_s`, all that is needed in most\ncases is:\n\n```ruby\n\"#{Unit.new('1 mm')}\"  #=\u003e \"1 mm\"\n```\n\nThe `to_s` also accepts some options.\n\n```ruby\nUnit.new('1.5 mm').to_s(\"%0.2f\")  # \"1.50 mm\".  Enter any valid format\n                                  #   string.  Also accepts strftime format\nUnit.new('10 mm').to_s(\"%0.2f in\")# \"0.39 in\". can also format and convert in\n                                  # the same time.\nUnit.new('1.5 mm').to_s(\"in\")     # converts to inches before printing\nUnit.new(\"2 m\").to_s(:ft)         # returns 6'7\"\nUnit.new(\"100 kg\").to_s(:lbs)     # returns 220 lbs, 7 oz\nUnit.new(\"100 kg\").to_s(:stone)   # returns 15 stone, 10 lb\n```\n\n### Time Helpers\n\n`Time`, `Date`, and `DateTime` objects can have time units added or subtracted.\n\n```ruby\nTime.now + Unit.new(\"10 min\")\n```\n\nSeveral helpers have also been defined. Note: If you include the 'Chronic' gem,\nyou can specify times in natural language.\n\n```ruby\nUnit.new('min').since(DateTime.parse('9/18/06 3:00pm'))\n```\n\nDurations may be entered as 'HH:MM:SS, usec' and will be returned in 'hours'.\n\n```ruby\nUnit.new('1:00')     #=\u003e 1 h\nUnit.new('0:30')     #=\u003e 0.5 h\nUnit.new('0:30:30')  #=\u003e 0.5 h + 30 sec\n```\n\nIf only one \":\" is present, it is interpreted as the separator between hours and\nminutes.\n\n### Ranges\n\n```ruby\n[Unit.new('0 h')..Unit.new('10 h')].each {|x| p x}\n```\n\nworks so long as the starting point has an integer scalar\n\n### Math functions\n\nAll Trig math functions (sin, cos, sinh, hypot...) can take a unit as their\nparameter. It will be converted to radians and then used if possible.\n\n### Temperatures\n\nRuby-units makes a distinction between a temperature (which technically is a\nproperty) and degrees of temperature (which temperatures are measured in).\n\nTemperature units (i.e., 'tempK') can be converted back and forth, and will take\ninto account the differences in the zero points of the various scales.\nDifferential temperature (e.g., Unit.new('100 degC')) units behave like most\nother units.\n\n```ruby\nUnit.new('37 tempC').convert_to('tempF')   #=\u003e 98.6 tempF\n```\n\nRuby-units will raise an exception if you attempt to create a temperature unit\nthat would fall below absolute zero.\n\nUnit math on temperatures is fairly limited.\n\n```ruby\nUnit.new('100 tempC') + Unit.new('10 degC')   # '110 tempC'.to_unit\nUnit.new('100 tempC') - Unit.new('10 degC')   # '90 tempC'.to_unit\nUnit.new('100 tempC') + Unit.new('50 tempC')  # exception (can't add two temperatures)\nUnit.new('100 tempC') - Unit.new('50 tempC')  # '50 degC'.to_unit (get the difference between two temperatures)\nUnit.new('50 tempC')  - Unit.new('100 tempC') # '-50 degC'.to_unit\nUnit.new('100 tempC') * scalar                # '100*scalar tempC'.to_unit\nUnit.new('100 tempC') / scalar                # '100/scalar tempC'.to_unit\nUnit.new('100 tempC') * unit                  # exception\nUnit.new('100 tempC') / unit                  # exception\nUnit.new('100 tempC') ** N                    # exception\n\nUnit.new('100 tempC').convert_to('degC')  #=\u003e Unit.new('100 degC')\n```\n\nThis conversion references the 0 point on the scale of the temperature unit\n\n```ruby\nUnit.new('100 degC').convert_to('tempC')  #=\u003e '-173 tempC'.to_unit\n```\n\nThese conversions are always interpreted as being relative to absolute zero.\nConversions are probably better done like this...\n\n```ruby\nUnit.new('0 tempC') + Unit.new('100 degC') #=\u003e Unit.new('100 tempC')\n```\n\n### Defining Units\n\nIt is possible to define new units or redefine existing ones.\n\n#### Define New Unit\n\nThe easiest approach is to define a unit in terms of other units.\n\n```ruby\nUnit.define(\"foobar\") do |foobar|\n  foobar.definition   = Unit.new(\"1 foo\") * Unit.new(\"1 bar\")   # anything that results in a Unit object\n  foobar.aliases      = %w{foobar fb}                   # array of synonyms for the unit\n  foobar.display_name = \"Foobar\"                        # How unit is displayed when output\nend\n```\n\n#### Redefine Existing Unit\n\nRedefining a unit allows the user to change a single aspect of a definition\nwithout having to re-create the entire definition. This is useful for changing\ndisplay names, adding aliases, etc.\n\n```ruby\nUnit.redefine!(\"cup\") do |cup|\n  cup.display_name  = \"cup\"\nend\n```\n\n### Useful methods\n\n1. `scalar` will return the numeric portion of the unit without the attached\n   units\n2. `base_scalar` will return the scalar in base units (SI)\n3. `units` will return the name of the units (without the scalar)\n4. `base` will return the unit converted to base units (SI)\n\n### Storing in a database\n\nUnits can be stored in a database as either the string representation or in two\nseparate columns defining the scalar and the units. Note that if sorting by\nunits is desired you will want to ensure that you are storing the scalars in a\nconsistent unit (i.e, the base units).\n\n### Namespaced Class\n\nSometimes the default class 'Unit' may conflict with other gems or applications.\nInternally ruby-units defines itself using the RubyUnits namespace. The actual\nclass of a unit is the RubyUnits::Unit. For simplicity and backwards\ncompatibility, the `::Unit` class is defined as an alias to `::RubyUnits::Unit`.\n\nTo load ruby-units without this alias...\n\n```ruby\nrequire 'ruby_units/namespaced'\n```\n\nWhen using bundler...\n\n```ruby\ngem 'ruby-units', require: 'ruby_units/namespaced'\n```\n\nNote: when using the namespaced version, the `Unit.new('unit string')` helper\nwill not be defined.\n\n### Configuration\n\nConfiguration options can be set like:\n\n```ruby\nRubyUnits.configure do |config|\n  config.format = :rational\n  config.separator = false\nend\n```\n\n| Option    | Description                                                                                                            | Valid Values              | Default     |\n|-----------|------------------------------------------------------------------------------------------------------------------------|---------------------------|-------------|\n| format    | Only used for output formatting. `:rational` is formatted like `3 m/s^2`. `:exponential` is formatted like `3 m*s^-2`. | `:rational, :exponential` | `:rational` |\n| separator | Use a space separator for output. `true` is formatted like `3 m/s`, `false` is like `3m/s`.                            | `true, false`             | `true`      |\n\n### NOTES\n\n#### Performance vs. Accuracy\n\nRuby units was originally intended to provide a robust and accurate way to do\narbitrary unit conversions. In some cases, these conversions can result in the\ncreation and garbage collection of a lot of intermediate objects during\ncalculations. This in turn can have a negative impact on performance. The design\nof ruby-units has emphasized accuracy over speed. YMMV if you are doing a lot of\nmath involving units.\n\n## Support Policy\n\nOnly currently maintained versions of ruby and jruby are supported.\n\n## License\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Folbrich%2Fruby-units.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Folbrich%2Fruby-units?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folbrich%2Fruby-units","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Folbrich%2Fruby-units","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folbrich%2Fruby-units/lists"}