├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.json
├── docs
├── css
│ └── index.css
├── index.html
└── js
│ ├── UnitMath.d.ts
│ ├── UnitMath.js
│ ├── UnitMath.min.js
│ └── demo.js
├── examples
└── decimal.js
├── index.js
├── jest.config.js
├── migrating-to-v1.md
├── package-lock.json
├── package.json
├── rollup.config.mjs
├── src
├── BuiltIns.ts
├── Parser.ts
├── Unit.ts
├── UnitStore.ts
├── types.ts
└── utils.ts
├── test
├── Unit.test-compiled.js
├── Unit.test.ts
├── UnitMath.test-bundle.js
└── approx.ts
├── tsconfig.json
└── types
├── BuiltIns.d.ts
├── Parser.d.ts
├── Unit.d.ts
├── Unit.js
├── UnitStore.d.ts
├── types.d.ts
└── utils.d.ts
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Workflow for Codecov example-javascript
2 | on: [push, pull_request]
3 | jobs:
4 | run:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Checkout
8 | uses: actions/checkout@v2
9 | - name: Set up Node 18
10 | uses: actions/setup-node@v3
11 | with:
12 | node-version: 18
13 | - name: Install dependencies
14 | run: npm install
15 | - name: Run tests and collect coverage
16 | run: npm run coverage
17 | - name: Upload coverage to Codecov
18 | uses: codecov/codecov-action@v3
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist/
3 | es/
4 | HOWTO.md
5 | .vscode/launch.json
6 | .nyc_output
7 | coverage
8 | *.bash
9 | call-tree
10 | .vscode/settings.json
11 | *.tgz
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - 12
5 | - 10
6 | - 8
7 |
8 | script:
9 | - npm run test:src
10 |
11 | jobs:
12 | include:
13 | - stage: other
14 | script: npm run lint
15 | name: Lint
16 | - script: npm run test:bundle
17 | name: Bundling Test
18 | - script: npm run coverage && npx codecov
19 | name: Coverage
20 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [1.1.1] - 2024-10-5
4 |
5 | - Fix package.json so that when using `import`, it imports the correct ES module. Thank you @fezproof!
6 |
7 | ## [1.1.0] - 2024-03-16
8 |
9 | - Add `applyBestPrefix` method to choose and apply the best prefix for a Unit. Thank you @adrfantini for the contribution.
10 |
11 | ## [1.0.2] - 2023-11-24
12 |
13 | - Set `exports` in `package.json`, which fixes imports in Node and Deno when using `require` or `import()`
14 |
15 | ## [1.0.1] - 2023-10-21
16 |
17 | _This is an attempt to correctly export types._
18 |
19 | ### Fixed
20 |
21 | - Set `module` entry point in package.json to `es/UnitMath.js`
22 | - Set `types` in package.json to `es/UnitMath.d.ts`
23 |
24 | ## [1.0.0] - 2023-02-20
25 |
26 | V1 is a major rewrite of UnitMath in TypeScript. While most of the API remains the same, V1 does introduce several breaking changes from v0.8.7. See [Migrating to v1](migrating-to-v1.md) for details.
27 |
28 | - `toString` no longer simplifies units. You must now explicitly call `simplify` for the unit to be simplified.
29 | - Removed `simplify` and `simplifyThreshold` options.
30 | - Removed `definitions.quantities` and `definitions.baseQuantities`.
31 | - Renaned `definitions.unitSystems` to `definitions.systems`
32 | - Renamed `definitions.prefixes` to `definitions.prefixGroups`
33 | - Each system defined in `definitions.systems` is now just a string array of units assigned to that system.
34 | - Removed `autoAddToSystem` option, since it is now much easier to add units to a system.
35 | - Customer formatters no longer accept additional user arguments.
36 |
37 | ## [1.0.0-rc.2] - 2023-02-19
38 | - `toString` no longer simplifies units. The user must now explicitly call `simplify` for the unit to be simplified.
39 | - Removed `simplifyThreshold` option, since units are now only simplified when calling `simplify`.
40 | - Many updates to the README.
41 | - Many tests had to be altered to reflect the changes to `toString` and `simplify`.
42 |
43 | ## [0.8.7] - 2021-09-28
44 | - Parse strings `NaN`, `Infinity`, and `-Infinity`
45 |
46 | ## [1.0.0-rc.1] - 2020-11-20
47 | - Convert to TypeScript
48 | - Removed concept of "quantities" and "base quantities"
49 | - Simplified how systems are defined and used in formatting
50 | - Simpler way to define units
51 | - Renamed many variables and API functions to make their meaning less ambiguous
52 | - Updated README.md
53 |
54 | ## [0.8.6] - 2020-07-13
55 | - Standardized on US customary fluid volumes
56 | - Corrected values for `teaspoon` and `fluidounce`
57 |
58 | ## [0.8.5] - 2019-11-23
59 | - `compare` now handles NaNs consistently
60 |
61 | ## [0.8.4] - 2019-08-05
62 | - Added `prefixesToChooseFrom` option
63 | - Bugfix when auto-prefixing negative numbers
64 |
65 | ## [0.8.3] - 2019-06-04
66 | - `split` now supports custom types
67 |
68 | ## [0.8.2] - 2019-06-01
69 | - Fixed unit complexity calculation for deciding whether to simplify units
70 | - Added undocumented second parameter to `conv` function, which could be removed at any time
71 |
72 | ## [0.8.1] - 2019-06-01
73 | - Format function can now be used with number or custom types
74 | - Now supports passing parameters to custom format function
75 |
76 | ## [0.8.0] - 2019-05-30
77 | - Added `getValue`, `getNormalizedValue`, and `setNormalizedValue`
78 | - Added format option for custom types
79 |
80 | ## [0.7.0] - 2019-05-28
81 | - Added compare
82 |
83 | ## [0.6.0] - 2019-05-28
84 | - Implement valueOf()
85 | - Added lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual
86 |
87 | ## [0.5.0] - 2019-05-27
88 | - Added setValue
89 | - Fixed bug with custom type formatting
90 | - Fixed candela unit definition
91 |
92 | ## [0.4.0] - 2019-05-26
93 | - Added split
94 | - Better support for parsing of custom types
95 |
96 | ## [0.3.0] - 2019-05-23
97 | - Added abs
98 | - Basic functionality with custom types (tested with Decimal.js, some features may not work)
99 |
100 | ## [0.2.1] - 2019-05-19
101 | - Added numerous tests to improve test coverage
102 | - Removed some unnecessary statements and branches
103 | - Minor bug fixes
104 | - Updated README
105 |
106 | ## [0.2.0] - 2019-05-18
107 | - Major refactoring of UnitStore.js to simplify the units definitions
108 | - Custom units now work with config options
109 | - Added code coverage (but doesn't seem to be instrumenting all the files yet)
110 |
111 | ## [0.1.1] - 2019-05-09
112 | - This patch actually includes the built files (I hope).
113 |
114 | ## [0.1.0] - 2019-05-08
115 |
116 | - First public release of UnitMath.
117 | - README is mostly up-to-date. Some of the API has not yet been implemented.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UnitMath
2 | UnitMath is a JavaScript library for unit conversion and arithmetic.
3 |
4 | [](https://travis-ci.org/ericman314/UnitMath)
5 | [](https://codecov.io/gh/ericman314/UnitMath)
6 |
7 |
8 |
9 | - [Install](#install)
10 | - [Getting Started](#getting-started)
11 | - [Creating Units](#creating-units)
12 | * [Parsing Rules](#parsing-rules)
13 | - [Unit Conversion](#unit-conversion)
14 | - [Arithmetic](#arithmetic)
15 | - [Simplify](#simplify)
16 | - [Formatting](#formatting)
17 | - [Configuring](#configuring)
18 | * [Querying the current configuration](#querying-the-current-configuration)
19 | - [Extending UnitMath](#extending-unitmath)
20 | * [User-Defined Units](#user-defined-units)
21 | * [Querying current unit definitions](#querying-current-unit-definitions)
22 | * [Custom Types](#custom-types)
23 | - [API Reference](#api-reference)
24 | * [Constructor](#constructor)
25 | * [Member Functions](#member-functions)
26 | * [Static Functions](#static-functions)
27 | - [Contributing](#contributing)
28 | - [Acknowledgements](#acknowledgements)
29 | * [Contributors](#contributors)
30 | - [License](#license)
31 |
32 |
33 |
34 | ## Demo
35 |
36 | https://ericman314.github.io/UnitMath/
37 |
38 | ## Install
39 |
40 | ```
41 | npm install unitmath
42 | ```
43 |
44 | ## Getting Started
45 |
46 | ```js
47 | const unit = require('unitmath')
48 |
49 | let a = unit('5 m').div('2 s') // 2.5 m / s
50 | let b = unit('40 km').to('mile') // 24.8548476894934 mile
51 | b.toString({ precision: 4 }) // "24.85 mile"
52 | ```
53 |
54 | ## Creating Units
55 |
56 | To create a unit, call `unit` with either a single string, or a number and a string:
57 |
58 | ```js
59 | // String
60 | let a = unit('40 mile')
61 | let b = unit('hour')
62 |
63 | // Number and string
64 | let g = unit(9.8, 'm/s^2')
65 | let h = unit(19.6, 'm')
66 | ```
67 |
68 | Units can be simple (`4 kg`) or compound (`8.314 J/mol K`). They may also be valueless (`hour`).
69 |
70 | ### Parsing Rules
71 |
72 | Parsing rules are different than typical JavaScript syntax. For instance:
73 | - The string may only contain one `"/"`. Units appearing before the `/` will be in the numerator of the resulting unit, and units appearing after the `/` will be in the denominator.
74 | - Parentheses `()` and asterisk `*` are ignored: multiplication is implicit.
75 | - Extra whitespace is allowed.
76 |
77 | The following all form valid units:
78 |
79 | ```js
80 | // These are valid:
81 | unit("2 in")
82 | unit("60/s")
83 | unit("8.314 * kg * m^2 / (s^2 * mol * K)")
84 | unit("6.022e-23 mol^-1")
85 | unit("kW / kg K")
86 | unit("3.1415926535897932384626433832795 rad")
87 |
88 | // These are invalid:
89 | unit("2 in + 3 in") // Unexpected "+" (Use .add() instead)
90 | unit("60 / s / s") // Unexpected additional "/"
91 | unit("0x123 kg") // Unit "x123" not found
92 | ```
93 |
94 | The exact syntax is as follows:
95 |
96 | ```
97 | [value][numerator][/denominator]
98 |
99 | numerator, denominator:
100 | atomicUnit [atomicUnit ...]
101 |
102 | atomicUnit:
103 | [prefix]unit[^power]
104 |
105 | value, power:
106 | Any floating-point number
107 |
108 | unit, prefix:
109 | Any built-in or user-defined unit or prefix
110 |
111 | ```
112 |
113 |
114 | ## Unit Conversion
115 |
116 | The `to` method converts from one unit to another. The two units must have the same dimension.
117 |
118 | ```js
119 | // Convert units
120 | unit('40 km').to('mile') // 24.8548476894934 mile
121 | unit('kg').to('lbm') // 2.20462262184878 lbm
122 | unit(5000, 'kg').to('N s') // Cannot convert 5000 kg to N s: dimensions do not match
123 | ```
124 |
125 | The `split` method will convert one unit into an array of units like so:
126 |
127 | ```js
128 | // Split a unit into parts
129 | unit('10 km').split([ 'mi', 'ft', 'in' ]) // [ 6 mi, 1128 ft, 4.78740157486361 in ]
130 | unit('51.4934 deg').split([ 'deg', 'arcmin', 'arcsec' ]) // [ 51 deg, 29 arcmin, 36.24 arcsec ]
131 | ```
132 |
133 | ## Arithmetic
134 |
135 | Use the methods `add`, `sub`, `mul`, `div`, `pow`, `sqrt`, and others to perform arithmetic on units. Multiple operations can be chained together:
136 |
137 | ```js
138 | // Chain operations together
139 | let g = unit(9.8, 'm/s^2')
140 | let h = unit(19.6, 'm')
141 | h.mul(2).div(g).sqrt() // 2 s
142 | ```
143 |
144 | Strings and numbers are implicitly converted to units within a chained expression. When chaining operators, they will execute in order from left to right. This may not be the usual, mathematical order of operations:
145 |
146 | ```js
147 | // Strings are implicitly converted to units
148 | unit('3 ft').add('6 in').mul(2) // 7 ft
149 | ```
150 |
151 | All of the operators are also available on the top-level `unit` object as static functions:
152 |
153 | ```js
154 | // Using static functions
155 | unit.mul(unit.add('3 ft', '6 in'), 2) // 7 ft
156 | ```
157 |
158 | Units are immutable, so every operation on a unit creates a new unit.
159 |
160 | ## Simplify
161 |
162 | UnitMath has a `simplify` method that will attempt to simplify a unit:
163 |
164 | ```js
165 | // Simplify units
166 | unit('10 / s').simplify() // 10 Hz
167 | unit('J / m').simplify() // N
168 | ```
169 |
170 | Because units are immutable, `simplify` always returns a *new* unit with the simplified units. It does not modify the original unit.
171 |
172 | In the `simplify` method, simplification is performed in two steps:
173 | 1. Attempting to simplify a compound unit into a single unit in the desired unit system
174 | 2. Choosing an appropriate prefix (if `options.autoPrefix` is true)
175 |
176 | *Note: To choose the best prefix without automatically simplifying the Unit, use the `applyBestPrefix` method.*
177 |
178 | Here are the options available for the `simplify` method:
179 |
180 |
188 |
189 | - `system` - *Default:* `'auto'`. The unit system to use when simplifying a `unit`. Available systems are `si`, `cgs`, `us`, and `auto`.
190 |
191 | ```js
192 | // Simplify units using a specific system
193 | unit('8 kg m / s^2').simplify({ system: 'si' }) // 8 N
194 | unit('8 kg m / s^2').simplify({ system: 'cgs' }) // 800 kdyn
195 | unit('8 kg m / s^2').simplify({ system: 'us' }) // 1.79847154479768 lbf
196 | ```
197 |
198 | When `system` is `'auto'` (the default), UnitMath will try to infer the unit system from the individual units that make up that `unit`. This is not guaranteed to succeed in all cases, so whenever possible, the system should be specified explicitly.
199 |
200 | ```js
201 | unit = unit.config({ system: 'auto' })
202 |
203 | // Automatically infer the unit system while simplifying
204 | unit('150 lbf').div('10 in^2').simplify() // 15 psi
205 | unit('400 N').div('10 cm^2').simplify() // 400 kPa
206 | ```
207 |
208 | Specifying a unit system other than `'auto'` will force UnitMath to use the specified system. Use the `config` function to apply the system everywhere, or pass a configuration object to `simplify` to apply to a single statement:
209 |
210 | ```js
211 | unit = unit.config({ system: 'us' })
212 |
213 | let a = unit('5 m').div('2 s')
214 | a.simplify() // 8.202099737532809 ft / s
215 |
216 | // Override the system for this statement
217 | a.simplify({ system: 'si'}) // 2.5 m / s
218 | ```
219 |
220 | - `autoPrefix` - *Default:* `true`. This option specifies whether `simplify` will try to choose an appropriate prefix in case of very small or very large quantities.
221 |
222 | ```js
223 | unit('1e-10 kg m / s^2').simplify() // 0.0001 uN
224 | unit('1e-10 kg m / s^2').simplify({ autoPrefix: false }) // 1e-10 N
225 | ```
226 |
227 | - `prefixMin` and `prefixMax` - *Defaults:* `0.1` and `1000`. Sets the threshold for choosing a different prefix when `autoPrefix` is true.
228 |
229 | ```js
230 | unit('0.005 m').simplify() // 0.5 cm
231 | unit('0.005 m').simplify({ prefixMin: 0.001 }) // 0.005 m
232 | ```
233 |
234 | - `formatPrefixDefault` - *Default:* `none`. By default, certain units are never assigned a new prefix (this is controlled by the `formatPrefixes` property of the unit definition.) By setting `formatPrefixDefault` to `"all"`, this behavior can be changed.
235 |
236 | ```js
237 | unit('1000001 lumen').simplify() // 1000001 lumen
238 | unit('1000001 lumen').simplify({ formatPrefixDefault: 'all' }) // 1.000001 megalumen
239 | ```
240 |
241 | ## Formatting
242 |
243 | Use `toString` to output a unit as a string:
244 |
245 | ```js
246 | unit('1 lb').to('kg').toString() // "0.45359237 kg"
247 | ```
248 |
249 | The `toString` method accepts a configuration object. The following options are available:
250 |
251 | - `precision` - *Default:* `15`. The number of significant figures to output when converting a unit to a string. Reducing this can help reduce the appearance of round-off errors. Setting a value of 0 will disable rounding.
252 |
253 | ```js
254 | // Output a unit with a specific precision
255 | unit('180 deg').to('rad').toString({ precision: 6 }) // 3.14159 rad
256 | unit('1 lb').to('kg').toString({ precision: 4 }) // "0.4536 kg"
257 | ```
258 |
259 | - `parentheses` - *Default:* `false`. When formatting a unit, group the numerator and/or denominator in parentheses if multiple units are present. This is useful when the resulting string will be used in a mathematical expression.
260 |
261 | ```js
262 | // Output a unit with parentheses
263 | unit('45 W / m K').toString({ parentheses: true }) // 45 W / (m K)
264 | ```
265 |
266 | - `formatter`. Define a custom formatter for the _numeric_ portion of the unit. The formatter will be passed the numeric value of the unit. For example:
267 |
268 | ```js
269 | let unit = require('unitmath')
270 |
271 | // Custom formatter
272 | let formatter = new Intl.NumberFormat('en-US', {
273 | style: 'currency',
274 | currency: 'USD',
275 | });
276 |
277 | // Specify formatter in argument to toString
278 | unit('25000 / ton').toString({ formatter: formatter.format }) // "$25,000.00 ton^-1"
279 |
280 | // Specify formatter in config
281 | let unitMoney = unit.config({
282 | formatter: formatter.format
283 | })
284 | unitMoney('25000 / ton').toString() // "$25,000.00 ton^-1"
285 | ```
286 |
287 | The `toString` method outputs a unit exactly as it is represented internally. It does _not_ automatically simplify a unit. This means you will usually want to call `simplify` before calling `toString`. How and when to simplify a unit is very subjective. UnitMath cannot anticipate all needs, so the user must explicitly call `simplify` when needed.
288 |
289 | ```js
290 | // toString outputs units "as-is".
291 | unit('10 / s').toString() // "10 s^-1"
292 | unit('10 / s').simplify().toString() // "10 Hz"
293 | ```
294 |
295 |
296 |
297 | ## Configuring
298 |
299 | UnitMath can be configured using `unit.config(options)`. The function returns a *new* instance of UnitMath with the specified configuration options.
300 |
301 | ```js
302 | // Set the default unit system to "us"
303 | const unit = require('unitmath').config({ system: 'us' })
304 | ```
305 |
306 | Available options are:
307 |
308 | - Any of the [simplify options](#simplify).
309 |
310 | - Any of the [formatting options](#formatting).
311 |
312 | - `type`. An object that allows UnitMath to work with custom numeric types. See [Custom Types](#custom-types) for complete details and examples.
313 |
314 | - `definitions`. An object that allows you to add to, modify, or remove the built-in units. See [User-Defined Units](#user-defined-units) for complete details.
315 |
316 | ```js
317 | // Create a new configuration
318 | unit = unit.config({
319 | definitions: {
320 | units: {
321 | furlong: { value: '220 yards' },
322 | fortnight: { value: '2 weeks' }
323 | }
324 | },
325 | precision: 6
326 | })
327 |
328 | unit('6 furlong/fortnight').to('m/s') // 0.000997857 m / s
329 | ```
330 |
331 |
332 |
333 | Because `unit.config(options)` returns a new instance of UnitMath, is is technically possible to perform operations between units created from different instances. The resulting behavior is undefined, however, so it is probably best to avoid doing this.
334 |
335 | **Important:** `unit.config(options)` returns a *new* instance of the factory function, so you must assign the return value of `unit.config(options)` to some variable, otherwise the new options won't take effect:
336 |
337 | ```js
338 | let unit = require('unitmath')
339 |
340 | // Incorrect, has no effect!
341 | unit.config(options)
342 |
343 | // Correct
344 | unit = unit.config(options)
345 | ```
346 |
347 | ### Querying the current configuration
348 |
349 | Call `unit.getConfig()` to return the current configuration.
350 |
351 | ```js
352 | // Get the current configuration
353 | unit.getConfig() // { system: 'si', ... }
354 | ```
355 |
356 | ## Extending UnitMath
357 |
358 | ### User-Defined Units
359 |
360 | To create a user-defined unit, pass an object with a `definitions` property to `unit.config()`:
361 |
362 | ```js
363 | // Create a new configuration adding a user-defined unit
364 | unit = unit.config({
365 | definitions: {
366 | units: {
367 | lightyear: { value: '9460730472580800 m' }
368 | }
369 | }
370 | })
371 |
372 | unit('1 lightyear').to('mile') // 5878625373183.61 mile
373 | ```
374 |
375 | The `definitions` object contains four properties which allow additional customization of the unit system: `units`, `prefixGroups`, `systems`, and `skipBuiltIns`.
376 |
377 | **definitions.units**
378 |
379 | This object contains the units that are made available by UnitMath. Each key in `definitions.units` becomes a new unit. The easiest way to define a unit is to provide a string representation in terms of other units:
380 |
381 | ```js
382 | // Define new units in terms of existing ones
383 | definitions: {
384 | units: {
385 | minute: { value: '60 seconds' },
386 | newton: { value: '1 kg m/s^2' }
387 | }
388 | }
389 | ```
390 |
391 | Here are all the options you can specify:
392 |
393 | - `value`: (Required) The value of the unit. It can be a string or an array containing two items:
394 |
395 | ```js
396 | // value can be a string...
397 | definitions: {
398 | units: {
399 | minute: { value: '60 seconds' },
400 | newton: { value: '1 kg m/s^2' }
401 | }
402 | }
403 |
404 | // ...or an array.
405 | definitions: {
406 | units: {
407 | minute: { value: [ 60, 'seconds' ] },
408 | newton: { value: [ 1, 'kg m/s^2' ] }
409 | }
410 | }
411 | ```
412 |
413 | - `quantity`: Specifying a `quantity` will create a new _base unit_. This is required for units that are not defined in terms of other units, such as `meter` and `second`. In this case, `value` will just be a number (or custom type):
414 |
415 | ```js
416 | // Specify `quantity` creates a new base unit
417 | definitions: {
418 | units: {
419 | seconds: { quantity: 'TIME', value: 1 }
420 | }
421 | }
422 | ```
423 |
424 | Only use `quantity` to define _base units_. Do **not** use `quantity` to define a derived unit:
425 |
426 | ```js
427 | // Incorrect
428 | definitions: {
429 | units: {
430 | meter: { quantity: 'LENGTH', value: 1 },
431 | squareMeter: { quantity: 'LENGTH^2', value: 1 }
432 | }
433 | }
434 |
435 | // Correct
436 | definitions: {
437 | units: {
438 | meter: { quantity: 'LENGTH', value: 1 },
439 | squareMeter: { value: '1 meter^2' }
440 | }
441 | }
442 | ```
443 |
444 | - `prefixGroup` - *Default:* `'NONE'`. Specifies which prefix group will be used when parsing and formatting the unit.
445 |
446 | ```js
447 | definitions: {
448 | units: {
449 | // Will parse 'nanometer', 'micrometer', 'millimeter', 'kilometer', 'megameter', etc.
450 | meter: { prefixGroup: 'LONG', ... },
451 |
452 | // Will parse 'nm', 'um', 'mm', 'km', 'Mm', etc.
453 | m: { prefixGroup: 'SHORT', ... }
454 | }
455 | }
456 | ```
457 |
458 | - `formatPrefixes`: A string array that specifies individual items of the unit's prefix group which will be used when formatting a unit. If this option is omitted, the global option `formatPrefixDefault` determines whether the unit will be formatted using all prefixes in the prefix group, or none at all.
459 |
460 | ```js
461 | definitions: {
462 | units: {
463 | L: {
464 | value: '1e-3 m^3'
465 | // Parse any prefix in the 'SHORT' prefix group
466 | prefixGroup: 'SHORT',
467 | // Format only as 'nL', 'uL', 'mL', and 'L'.
468 | formatPrefixes: ['n', 'u', 'm', ''],
469 | },
470 | lumen: {
471 | value: '1 cd sr'
472 | // Parse any prefix in the 'LONG' prefix group
473 | prefixGroup: 'LONG',
474 | // formatPrefixes is not given, so lumen will be formatted
475 | // only as "lumen" if formatPrefixDefault === false,
476 | // or formatted using any of the prefixes in the 'LONG'
477 | // prefix group if formatPrefixDefault === true.
478 | }
479 | }
480 | }
481 | ```
482 |
483 | - `basePrefix`: Optional. The prefix to use for a _base unit_, if the base unit has one. This is necessary for units such as kilogram, which is a base unit but has a prefix.
484 |
485 | ```js
486 | // Special case for base units with prefixes, such as kg
487 | definitions: {
488 | units: {
489 | g: {
490 | quantity: 'MASS',
491 | prefixGroup: 'SHORT',
492 | formatPrefixes: ['n', 'u', 'm', '', 'k'],
493 | value: 0.001,
494 | // Treat as if 'kg' is the base unit, not 'g'
495 | basePrefix: 'k'
496 | }
497 | }
498 | }
499 | ```
500 |
501 | - `aliases`: Shortcut to create additional units with identical definitions.
502 |
503 | ```js
504 | // Create aliases for a unit
505 | definitions: {
506 | units: {
507 | meter: { ... , aliases: [ 'meters' ] }
508 | }
509 | }
510 | ```
511 |
512 | - `offset` - *Default:* `0`: Used when the zero-value of this unit is different from the zero-value of the base unit.
513 |
514 | ```js
515 | // Special case for units with an offset from the base unit, like celsius
516 | definitions: {
517 | units: {
518 | celsius: {
519 | value: '1 K',
520 | offset: 273.15
521 | }
522 | }
523 | }
524 | ```
525 |
526 | **definitions.prefixGroups**
527 |
528 | The `definitions.prefixGroups` object is used to define strings and associated multipliers that are prefixed to units to change their value. For example, the `'k'` prefix in `km` multiplies the value of the `m` unit by 1000.
529 |
530 | For example:
531 |
532 | ```js
533 | // Define prefix groups
534 | definitions: {
535 | prefixGroups: {
536 | NONE: { '': 1 },
537 | SHORT: {
538 | m: 0.001,
539 | '': 1,
540 | k: 1000
541 | },
542 | LONG: {
543 | milli: 0.001,
544 | '': 1,
545 | kilo: 1000
546 | }
547 | }
548 | }
549 | ```
550 |
551 | **definitions.systems**
552 |
553 | This object assigns one or more units to a number of systems. Each key in `definitions.systems` becomes a system. For each system, list all the units that should be associated with that system in an array. The units may be single or compound (`m` or `m/s`) and may include prefixes.
554 |
555 | Example:
556 |
557 | ```js
558 | // Define unit systems
559 | definitions: {
560 | systems: {
561 | si: ['m', 'kg', 's', 'N', 'J', 'm^3', 'm/s'],
562 | cgs: ['cm', 'g', 's', 'dyn', 'erg', 'cm^3', 'cm/s'],
563 | us: ['ft', 'lbm', 's', 'lbf', 'btu', 'gal', 'ft/s']
564 | }
565 | }
566 | ```
567 |
568 | When UnitMath formats a unit, it will try to use one of the units from the specified system.
569 |
570 | **definitions.skipBuiltIns**
571 |
572 | A boolean value indicating whether to skip the built-in units. If `true`, only the user-defined units, prefix groups, and systems that are explicitly included in `definitions` will be created.
573 |
574 | ```js
575 | // Skip built-in units: only the user-defined units,
576 | // prefix groups, and systems will be created
577 | definitions: {
578 | skipBuiltIns: true
579 | }
580 | ```
581 |
582 | ### Querying current unit definitions ###
583 |
584 | You can view all the current definitions by calling `unit.definitions()`. This object contains all the units, prefix groups, and systems that you have configured, including the built-ins (unless `definitions.skipBuiltIns` is true).
585 |
586 | ```js
587 | unit.definitions()
588 | ```
589 |
590 | Below is an abbreviated sample output from `unit.definitions()`. It can serve as a starting point to create your own definitions.
591 |
592 | ```js
593 | // Sample `definitions` config
594 | {
595 | units: {
596 | '': { quantity: 'UNITLESS', value: 1 },
597 | meter: {
598 | quantity: 'LENGTH',
599 | prefixGroup: 'LONG',
600 | formatPrefixes: [ 'nano', 'micro', 'milli', 'centi', '', 'kilo' ],
601 | value: 1,
602 | aliases: [ 'meters' ]
603 | },
604 | m: {
605 | prefixGroup: 'SHORT',
606 | formatPrefixes: [ 'n', 'u', 'm', 'c', '', 'k' ],
607 | value: '1 meter'
608 | },
609 | inch: { value: '0.0254 meter', aliases: [ 'inches', 'in' ] },
610 | foot: { value: '12 inch', aliases: [ 'ft', 'feet' ] },
611 | yard: { value: '3 foot', aliases: [ 'yd', 'yards' ] },
612 | mile: { value: '5280 ft', aliases: [ 'mi', 'miles' ] },
613 | ...
614 | },
615 | prefixGroups: {
616 | NONE: { '': 1 },
617 | SHORT: {
618 | '': 1,
619 | da: 10,
620 | h: 100,
621 | k: 1000,
622 | ...
623 | d: 0.1,
624 | c: 0.01,
625 | m: 0.001,
626 | ...
627 | },
628 | },
629 | systems: {
630 | si: ['m', 'meter', 's', 'A', 'kg', ...],
631 | cgs: ['cm', 's', 'A', 'g', 'K', ...],
632 | us: ['ft', 's', 'A', 'lbm', 'degF', ...]
633 | }
634 | }
635 | ```
636 |
637 | ### Custom Types ###
638 |
639 | You can extend UnitMath to work with custom types. The `type` option is an object containing several properties, where each property value is a function that replaces the normal `+`, `-`, `*`, `/`, and other arithmetic operators used internally by UnitMath.
640 |
641 | Example using Decimal.js as the custom type:
642 |
643 | ```js
644 | // Configure UnitMath to use Decimal.js
645 | const Decimal = require('decimal.js')
646 | const unit = unit.config({
647 | type: {
648 | clone: (x) => new Decimal(x),
649 | conv: (x) => new Decimal(x),
650 | add: (a, b) => a.add(b),
651 | sub: (a, b) => a.sub(b),
652 | mul: (a, b) => a.mul(b),
653 | div: (a, b) => a.div(b),
654 | pow: (a, b) => a.pow(b),
655 | eq: (a, b) => a.eq(b),
656 | lt: (a, b) => a.lt(b),
657 | le: (a, b) => a.lte(b),
658 | gt: (a, b) => a.gt(b),
659 | ge: (a, b) => a.gte(b),
660 | abs: (a) => a.abs(),
661 | round: (a) => a.round(),
662 | trunc: (a) => Decimal.trunc(a)
663 | }
664 | })
665 |
666 | let u = unit2('2.74518864784926316174649567946 m')
667 | ```
668 |
669 | Below is a table of functions, their description, and when they are required:
670 |
671 | Function | Description | Required?
672 | ---------|-------------|------------
673 | `clone: (a: T) => T` | Create a new instance of the custom type. | Always
674 | `conv: (a: number \| string \| T) => T` | Convert a number or string into the custom type. | Always
675 | `add: (a: T, b: T) => T` | Add two custom types. | Always
676 | `sub: (a: T, b: T) => T` | Subtract two custom types. | Always
677 | `mul: (a: T, b: T) => T` | Multiply two custom types. | Always
678 | `div: (a: T, b: T) => T` | Divide two custom types. | Always
679 | `pow: (a: T, b: number) => T` | Raise a custom type to a power. | Always
680 | `abs: (a: T) => T` | Return the absolute value of a custom type. | For autoPrefix: true
681 | `lt: (a: T, b: T) => boolean` | Compare two custom types for less than. | For autoPrefix: true
682 | `le: (a: T, b: T) => boolean` | Compare two custom types for less than or equal. | For autoPrefix: true
683 | `gt: (a: T, b: T) => boolean` | Compare two custom types for greater than. | For autoPrefix: true
684 | `ge: (a: T, b: T) => boolean` | Compare two custom types for greater than or equal. | For autoPrefix: true
685 | `eq: (a: T, b: T) => boolean` | Compare two custom types for equality. | For the `equals` function
686 | `round: (a: T) => T` | Round a custom type to the nearest integer. | For the `split` function
687 | `trunc: (a: T) => T` | Truncate a custom type to the nearest integer. | For the `split` function
688 |
689 |
690 | The `add`, `sub`, `mul`, `div`, and `pow` functions replace `+`, `-`, `*`, `/`, and `Math.pow`, respectively. The `clone` function should return a clone of your custom type (same value, different object).
691 |
692 | The `conv` function must, at a minimum, be capable of converting both strings and numbers into your custom type. If given a custom type, it should return it unchanged, or return a clone. Among other things, the `conv` function is used by UnitMath to convert the values of the built-in units to your custom type during initialization.
693 |
694 | UnitMath will also use the `conv` function when constructing units from numbers and strings. If your custom type is representable using decimal or scientific notation (such as `6.022e+23`), you can include both the value and the units in a single string:
695 |
696 | ```js
697 | // Supply a single string, and the numeric portion will be parsed using type.conv
698 | unit('3.1415926535897932384626433832795 rad')
699 | ```
700 |
701 | If your custom type cannot be represented in decimal or scientific notation, such as is the case with complex numbers and fractions, you will have to pass your custom type and the unit string separately:
702 |
703 | ```js
704 | unit(Fraction(1, 2), 'kg')
705 | ```
706 |
707 | The functions `clone`, `conv`, `add`, `sub`, `mul`, `div`, and `pow` are always required. Omitting any of these will cause the `config` method to throw an error. The other functions are conditionally required, and you will receive an error if you attempt something that depends on a function you haven't provided.
708 |
709 | ## API Reference ##
710 |
711 | *In the function signatures below, the `T` type is the custom type you have provided, or `number` if you have not provided a custom type.*
712 | ### Constructor ###
713 |
714 | - `unit(value: T, unitString: string): unit`
715 | `unit(value: T): unit`
716 | `unit(valueAndUnitString: string): unit`
717 | `unit(): unit`
718 |
719 | Creates a unit with the specified value and unit string. If `valueAndUnitString` is supplied, it must specify both the numeric portion and the units portion of the unit.
720 |
721 | ```js
722 | const unit = require('unitmath')
723 | unit(60, 'mile/hour') // 60 mile / hour
724 | unit(60) // 60
725 | unit('60 mile/hour') // 60 mile / hour
726 | unit('mile/hour') // mile / hour
727 | unit() // Empty unit
728 | ```
729 |
730 | `unit()` will parse the special strings `"NaN"`, `"Infinity"`, and `"-Infinity"` as the corresponding numeric values:
731 |
732 | ```js
733 | const unit = require('unitmath')
734 | unit('Infinity kg') // Infinity kg
735 | ```
736 |
737 | The string used to specify the unit (`valueAndUnitString` or `unitString`) must be in the following format:
738 |
739 | ```
740 | [value][numerator][/denominator]
741 |
742 | numerator, denominator:
743 | atomicUnit [atomicUnit ...]
744 |
745 | atomicUnit:
746 | [prefix]unit[^power]
747 |
748 | value:
749 | Any floating-point number, or the strings "NaN", "Infinity", or "-Infinity" (without the quotes).
750 |
751 | power:
752 | Any floating-point number
753 |
754 | ```
755 |
756 | ### Member Functions ###
757 |
758 | - `add(other: unit | string | T) : unit`
759 |
760 | Adds another unit to this unit. If a string or number is supplied as an argument, it is converted to a unit. Both units must have values and have matching dimensions.
761 |
762 | ```js
763 | let a = unit('20 kW')
764 | let b = unit('300 W')
765 | let sum = a.add(b) // 20.3 kW
766 | ```
767 |
768 | - `sub(other: unit | string | T) : unit`
769 |
770 | Subtract another unit from this unit. If a string or number is supplied as an argument, it is converted to a unit. Both units must have values and have matching dimensions.
771 |
772 | ```js
773 | let a = unit('4 ft')
774 | let b = unit('1 yd')
775 | let difference = a.sub(b) // 1 ft
776 | ```
777 |
778 | - `mul(other: unit | string | T) : unit`
779 |
780 | Multiplies this unit by another unit. If a string or number is supplied as an argument, it is converted to a unit.
781 |
782 | ```js
783 | let a = unit('8 m')
784 | let b = unit('200 N')
785 | let product = a.mul(b).simplify() // 1.6 kJ
786 | ```
787 |
788 | - `div(other: unit | string | T) : unit`
789 |
790 | Divides this unit by another unit. If a string or number is supplied as an argument, it is converted to a unit.
791 |
792 | ```js
793 | let a = unit('64 kJ')
794 | let b = unit('16 s')
795 | let quotient = a.div(b).simplify() // 4 kW
796 | ```
797 |
798 | - `pow(p: number)`
799 |
800 | Raises this unit to the power `p` and returns a new unit.
801 |
802 | ```js
803 | let result = unit('10 m').pow(3) // 1000 m^3
804 | ```
805 |
806 | - `sqrt()`
807 |
808 | Returns the square root of this unit.
809 |
810 | ```js
811 | unit('1 hectare').sqrt().simplify() // 100 m
812 | ```
813 |
814 | - `abs()`
815 |
816 | Returns the absolute value of this unit. If this unit has an offset, such as `degC`, this is applied before taking the absolute value.
817 |
818 | ```js
819 | unit('-5 m / s').abs() // 5 m / s
820 | unit('-293.15 degC').abs() // -253.15 degC
821 | ```
822 |
823 | - `clone()`
824 |
825 | Clones this unit.
826 |
827 | ```js
828 | let unit = require('unitmath')
829 |
830 | let a = unit('40 m/s') // 40 m / s
831 | let b = a.clone() // 40 m / s
832 | ```
833 |
834 | - `to(target: unit | string)`
835 |
836 | Converts this unit to the specified target unit or string. The returned unit will be "fixed", so it will not be auto-simplified or auto-prefixed in `format()`.
837 |
838 | ```js
839 | let r = unit('10 kg m^2 / s^3 A^2')
840 | r.simplify().toString() // 10 ohm
841 | r.to('kohm').toString() // 0.01 kohm
842 | ```
843 |
844 | - `toBaseUnits()`
845 |
846 | Returns a new unit in the base representation.
847 |
848 | ```js
849 | unit('10 ft/s').toBaseUnits() // 3.048 m / s
850 | ```
851 |
852 | - `getValue()`
853 |
854 | Returns the value of this unit, or `null` if the unit is valueless.
855 |
856 | ```js
857 | unit('70 mile/hour').getValue() // 70
858 | unit('km / hour').getValue() // null
859 | ```
860 |
861 | - `setValue(x: number | string | custom)`
862 |
863 | Returns a copy of this unit but with its value replaced with the given value. Useful if you would like to perform your own operations on a unit's value. If supplied with no arguments, or `null`, will remove the value from the unit.
864 |
865 | ```js
866 | unit('10 m').setValue(20) // 20 m
867 | unit('m').setValue(20) // 20 m
868 | unit('10 ft').setValue(20) // 20 ft
869 | unit('10 ft').setValue() // ft
870 | ```
871 |
872 | - `getNormalizedValue()`
873 |
874 | Returns the value of this unit if it were to be converted to SI base units (or whatever base units that are defined). Returns `null` if the unit is valueless.
875 |
876 | ```js
877 | unit('10 ft/s').getNormalizedValue() // 3.048
878 | ```
879 |
880 | - `setNormalizedValue()`
881 |
882 | Returns a copy of this unit but with its value replaced with the given normalized value.
883 |
884 | ```js
885 | unit('ft / s').setNormalizedValue(3.048) // 10 ft / s
886 | ```
887 |
888 | - `simplify()`
889 |
890 | Attempts to simplify this unit, and returns the simplified unit (or a clone of the original if unsuccessful). `simplify()` is called when a unit is being formatted as a string whenever the config option `simplify` is `'auto'` or `'always'`.
891 |
892 | ```js
893 | unit('10 N m').simplify() // 10 J
894 | ```
895 |
896 | - `applyBestPrefix(PrefixOptions)`
897 |
898 | Chooses a prefix for this unit so that its value is between `prefixMin` and `prefixMax`, and returns a new unit with the prefix applied. If the value is already within the range, the unit is returned unchanged. The prefix is chosen from the unit's `formatPrefixes` property.
899 |
900 | ```js
901 | unit('0.0001 m').applyBestPrefix() // 0.1 mm
902 | unit('0.1 m').applyBestPrefix() // 10 cm
903 | unit('10000 m').applyBestPrefix() // 10 km
904 | ```
905 |
906 | - `split(Array(string | unit))`
907 |
908 | Returns an array of units that result from splitting this unit into the given units. The sum of the resulting units is equal to this unit, and each of the returned units is the result of truncating this unit to an integer, and then passing the remainder to the next unit, until the final unit, which takes up all the remainder.
909 |
910 | ```js
911 | unit('51.4934 deg').split([ 'deg', 'arcmin', 'arcsec' ]) // [ 51 deg, 29 arcmin, 36.24 arcsec ]
912 | ```
913 |
914 | - `getUnits()`
915 |
916 | Returns a clone of this unit with the value removed. Equivalent to `unit.setValue(null)`.
917 |
918 | ```js
919 | unit('8.314 J / mol K').getUnits() // J / mol K
920 | ```
921 |
922 | - `isCompound()`
923 |
924 | Returns true if this unit's unit list contains two or more units, or one unit with a power not equal to 1.
925 |
926 | ```js
927 | unit('34 kg').isCompound() // false
928 | unit('34 kg/s').isCompound() // true
929 | unit('34 kg^2').isCompound() // true
930 | unit('34 N').isCompound() // false
931 | unit('34 kg m / s^2').isCompound() // true
932 | ```
933 |
934 | - `isBase()`
935 |
936 | Returns true if this unit's unit list contains exactly one unit with a power equal to 1, and which is the of same dimension as one of the base dimensions length, time, mass, etc., or a user-defined base dimension.
937 |
938 | ```js
939 |
940 | unit = unit.config({
941 | definitions: {
942 | units: {
943 | myUnit: { quantity: 'MY_NEW_BASE', value: 1 },
944 | anotherUnit: { value: '4 myUnit' }
945 | }
946 | }
947 | })
948 |
949 | unit('34 kg').isBase() // true
950 | unit('34 kg/s').isBase() // false
951 | unit('34 kg^2').isBase() // false
952 | unit('34 N').isBase() // false
953 | unit('34 myUnit').isBase() // true
954 | unit('34 anotherUnit').isBase() // true
955 | ```
956 |
957 | - `getInferredSystem()`
958 |
959 | Examines this unit's unitList to determine the most likely system this unit is expressed in.
960 |
961 | ```js
962 | unit('10 N m').getInferredSystem() // 'si'
963 | unit('10 J / m').getInferredSystem() // 'si'
964 | unit('10 m^3 Pa').getInferredSystem() // 'si'
965 | unit('10 dyne/cm').getInferredSystem() // 'cgs'
966 | unit('10 ft/s').getInferredSystem() // 'us'
967 | unit('10').getInferredSystem() // null
968 | ```
969 |
970 | - `equalsQuantity(other: unit | string)`
971 |
972 | Returns true if this unit and another unit have equal quantities or dimensions.
973 |
974 | ```js
975 | unit('5 m/s^2').equalsQuantity('4 ft/s^2') // true
976 | ```
977 |
978 | - `equals(other: unit | string)`
979 |
980 | Returns true if the two units represent the same values.
981 |
982 | ```js
983 | unit('3 ft').equals('1 yard') // true
984 | ```
985 |
986 | - `compare(other: unit | string)`
987 |
988 | Returns a value indicating whether this unit is less than (-1), greater than (1), or equal to (0), another unit.
989 |
990 | ```js
991 | unit('30 min').compare('1 hour') // -1
992 | unit('60 min').compare('1 hour') // 0
993 | unit('90 min').compare('1 hour') // 1
994 | ```
995 |
996 | - `lessThan(other: unit | string)`
997 |
998 | Compares this and another unit and returns true if this unit is less than the other.
999 |
1000 | ```js
1001 | unit('80 cm').lessThan('1 m') // true
1002 | unit('100 cm').lessThan('1 m') // false
1003 | unit('120 cm').lessThan('1 m') // false
1004 | ```
1005 |
1006 | - `lessThanOrEqual(other: unit | string)`
1007 |
1008 | Compares this and another unit and returns true if this unit is less than or equal to the other.
1009 |
1010 | ```js
1011 | unit('80 cm').lessThanOrEqual('1 m') // true
1012 | unit('100 cm').lessThanOrEqual('1 m') // true
1013 | unit('120 cm').lessThanOrEqual('1 m') // false
1014 | ```
1015 |
1016 | - `greaterThan(other: unit | string)`
1017 |
1018 | Compares this and another unit and returns true if this unit is greater than the other.
1019 |
1020 | ```js
1021 | unit('80 cm').greaterThan('1 m') // false
1022 | unit('100 cm').greaterThan('1 m') // false
1023 | unit('120 cm').greaterThan('1 m') // true
1024 | ```
1025 |
1026 | - `greaterThanOrEqual(other: unit | string)`
1027 |
1028 | Compares this and another unit and returns true if this unit is greater than or equal to the other.
1029 |
1030 | ```js
1031 | unit('80 cm').greaterThanOrEqual('1 m') // false
1032 | unit('100 cm').greaterThanOrEqual('1 m') // true
1033 | unit('120 cm').greaterThanOrEqual('1 m') // true
1034 | ```
1035 |
1036 | - `toString(options)`
1037 |
1038 | Formats this unit as a string. Formatting options can be supplied which will override the configured options. See [Formatting](#formatting) for a list of all options and their effects.
1039 |
1040 | ### Static Functions ###
1041 |
1042 | - `add(a: unit | string | T, b: unit | string | T) : unit`
1043 |
1044 | Adds two units. If a string or number is supplied as an argument, it is converted to a unit. Both units must have values and have matching dimensions.
1045 |
1046 | ```js
1047 | let sum = unit.add('20 kW', '300 W') // 20.3 kW
1048 | ```
1049 |
1050 | - `sub(a: unit | string | T, b: unit | string | T) : unit`
1051 |
1052 | Subtract two units. If a string or number is supplied as an argument, it is converted to a unit. Both units must have values and have matching dimensions.
1053 |
1054 | ```js
1055 | let difference = unit.sub('4 ft', '1 yd') // 1 ft
1056 | ```
1057 |
1058 | - `mul(a: unit | string | T, b: unit | string | T) : unit`
1059 |
1060 | Multiplies two units. If a string or number is supplied as an argument, it is converted to a unit.
1061 |
1062 | ```js
1063 | let product = unit.mul('8 m/s', '200 N').simplify() // 1.6 kW
1064 | ```
1065 |
1066 | - `div(a: unit | string | T, b: unit | string | T) : unit`
1067 |
1068 | Divides two units. If a string or number is supplied as an argument, it is converted to a unit.
1069 |
1070 | ```js
1071 | let quotient = unit.div('64 kJ', '16 s').simplify() // 4 kW
1072 | ```
1073 |
1074 | - `pow(a: unit | string | T, p: number) : unit`
1075 |
1076 | Raises a unit to the power `p` and returns a new unit.
1077 |
1078 | ```js
1079 | let result = unit.pow('10 m', 3) // 1000 m^3
1080 | ```
1081 |
1082 | - `sqrt(a: unit | string | T) : unit`
1083 |
1084 | Returns the square root of a unit.
1085 |
1086 | ```js
1087 | unit.sqrt('1 hectare').simplify() // 100 m
1088 | ```
1089 |
1090 | - `abs(a: unit | string | T) : unit`
1091 |
1092 | Returns the absolute value of a unit. If the unit has an offset, such as `degC`, this is applied before taking the absolute value.
1093 |
1094 | ```js
1095 | unit.abs('-5 m / s') // 5 m / s
1096 | unit.abs('300 degC') // -246.3 degC
1097 | ```
1098 |
1099 | - `to(a: unit | string | number, b: unit | string)`
1100 |
1101 | Converts a unit to the specified target unit or string. The returned unit will be "fixed", so it will not be auto-simplified or auto-prefixed in `format()`.
1102 |
1103 | ```js
1104 | unit.to('10 kg m^2 / s^3 A^2', 'kohm') // 0.01 kohm
1105 | ```
1106 |
1107 | - `config(options:object)`
1108 |
1109 | Configure a new unit namespace with the given options (see [Configuring](#configuring))
1110 |
1111 | ```js
1112 | const unit = require('unitmath').config({ option1, option2, ... })
1113 | ```
1114 |
1115 | - `getConfig()`
1116 |
1117 | Returns the current configuration.
1118 |
1119 | ```js
1120 | const unit = require('unitmath')
1121 | unit.getConfig()
1122 | ```
1123 |
1124 | - `exists(singleUnitString:string)`
1125 |
1126 | Tests if the given unit, optionally with a prefix, exists.
1127 |
1128 | ```js
1129 | const unit = require('unitmath')
1130 | unit.exists('km') // true
1131 | ```
1132 |
1133 | - `definitions()`
1134 |
1135 | Return the current unit definitions in effect. (User's own definitions can be queried through `unit.getConfig().definitions`.)
1136 |
1137 | ## Contributing
1138 |
1139 | This is a community-supported project; all contributions are welcome. Please open an issue or submit a pull request.
1140 |
1141 | ## Acknowledgements
1142 |
1143 | Many thanks to Jos de Jong (@josdejong), the original author of `Unit.js`, who suggested the idea of splitting the file off from [Math.js](https://mathjs.org/) and into its own library.
1144 |
1145 | ### Contributors
1146 |
1147 | - Harry Sarson (https://github.com/harrysarson)
1148 | - Nick Ewing (https://github.com/nickewing)
1149 | - Michal Grňo (https://github.com/m93a)
1150 | - Adriano Fantini (https://github.com/adrfantini)
1151 | - Ben Chidlow (https://github.com/fezproof)
1152 |
1153 | ## License
1154 |
1155 | UnitMath is released under the Apache-2.0 license.
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "node": 10
8 | }
9 | }
10 | ]
11 | ]
12 | }
--------------------------------------------------------------------------------
/docs/css/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family:Arial, Helvetica, sans-serif;
3 | }
4 |
5 | .container{
6 | max-width: 800px;
7 | margin: 0 auto;
8 | }
9 |
10 | div.thingies{
11 | height:30px;
12 | }
13 |
14 | .field {
15 | font-size:120%;
16 | margin-bottom:1em;
17 | max-width:400px;
18 | }
19 |
20 | .field label {
21 | display:block;
22 | }
23 |
24 | .field input {
25 | width:100%;
26 | font-size: 1em;
27 | padding:8px;
28 | border:1px solid #ccc;
29 | border-radius:4px;
30 | }
31 |
32 | code {
33 | background:#eee;
34 | padding:4px;
35 | border-radius:4px;
36 | }
37 |
38 | .buttonWrapper{
39 | display:flex;
40 | }
41 |
42 | .buttonWrapper button {
43 | font-size: 24px;
44 | display:inline-block;
45 | width: 40px;
46 | height: 40px;
47 | }
48 |
49 | ul li {
50 | line-height: 1.8;
51 | }
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This calculator cannot parse complicated grammar. It is just to highlight some of the capabilities of the
62 | UnitMath
63 | library. For a fully-featured math library with a parser that supports unit conversion and arithmetic, try Math.js.