Everyone have written their share of trivial conversions - or less obvious ones where you need to Google that magic constant.
Stop littering your code with unnecessary calculations, Units.NET gives you all the common units of measurement and the conversions between them. It is lightweight and thoroughly tested.
See Upgrading from 3.x to 4.x.
- .NET Standard 2.0
- .NET 4.0
- Windows Runtime Component for UWP apps (JavaScript, C++ or C#)
- 90 quantities with 800+ units generated from JSON by Powershell scripts
- 2500+ unit tests on conversions and localizations
- Conforms to Microsoft's open-source library guidance, in particular:
- SourceLink to step into source code of NuGet package while debugging
- Strong naming to make the library available to all developers
- Immutable structs that implement
IEquatable
,IComparable
- Statically typed quantities and units to avoid mistakes and communicate intent
- Operator overloads for arithmetic on quantities
- Parse and ToString() supports cultures and localization
- Dynamically parsing and converting quantities and units
- Example: Creating a unit converter app
- Example: WPF app using IValueConverter to parse quantities from input
- Precision and accuracy
- Serializable with JSON.NET
- Extensible with custom units
- Contribute if you are missing some units
- Continuous integration posts status reports to pull requests and commits
- Who are using this?
Run the following command in the Package Manager Console or go to the NuGet site for the complete relase history.
// Construct
Length meter = Length.FromMeters(1);
Length twoMeters = new Length(2, LengthUnit.Meter);
// Convert
double cm = meter.Centimeters; // 100
double yards = meter.Yards; // 1.09361
double feet = meter.Feet; // 3.28084
double inches = meter.Inches; // 39.3701
// Pass quantity types instead of values to avoid conversion mistakes and communicate intent
string PrintPersonWeight(Mass weight)
{
// No such thing! Weight in this context is Mass, not Force.
double weightNewtons = weight.Newtons;
// Convert to the unit of choice - when you need it
return $"You weigh {weight.Kilograms:F1} kg.";
}
// Arithmetic
Length l1 = 2 * Length.FromMeters(1);
Length l2 = Length.FromMeters(1) / 2;
Length l3 = l1 + l2;
// Construct between units
Length distance = Speed.FromKilometersPerHour(80) * TimeSpan.FromMinutes(30);
Acceleration a1 = Speed.FromKilometersPerHour(80) / TimeSpan.FromSeconds(2);
Acceleration a2 = Force.FromNewtons(100) / Mass.FromKilograms(20);
RotationalSpeed r = Angle.FromDegrees(90) / TimeSpan.FromSeconds(2);
The culture for abbreviations defaults to Thread.CurrentUICulture and falls back to US English if not defined. Thread.CurrentCulture affects number formatting unless a custom culture is specified. The relevant methods are:
- ToString()
- GetAbbreviation()
- Parse/TryParse()
- ParseUnit/TryParseUnit()
var usEnglish = new CultureInfo("en-US");
var russian = new CultureInfo("ru-RU");
var oneKg = Mass.FromKilograms(1);
// ToString() uses CurrentUICulture for abbreviation language and CurrentCulture for number formatting
Thread.CurrentThread.CurrentUICulture = russian;
string kgRu = oneKg.ToString(); // "1 кг"
// ToString() with specific culture and custom string format pattern
string mgUs = oneKg.ToUnit(MassUnit.Milligram).ToString(usEnglish, "unit: {1}, value: {0:F2}"); // "unit: mg, value: 1.00"
string mgRu = oneKg.ToUnit(MassUnit.Milligram).ToString(russian, "unit: {1}, value: {0:F2}"); // "unit: мг, value: 1,00"
// Parse measurement from string
Mass kg = Mass.Parse("1.0 kg", usEnglish);
// Parse unit from string, a unit can have multiple abbreviations
RotationalSpeedUnit rpm1 = RotationalSpeed.ParseUnit("rpm"); // RotationalSpeedUnit.RevolutionPerMinute
RotationalSpeedUnit rpm2 = RotationalSpeed.ParseUnit("r/min"); // RotationalSpeedUnit.RevolutionPerMinute
// Get default abbreviation for a unit, the first if more than one is defined in Length.json for Kilogram unit
string kgAbbreviation = Mass.GetAbbreviation(MassUnit.Kilogram); // "kg"
Some units of a quantity have the same abbreviation, which means .Parse()
is not able to know what unit you wanted.
Unfortunately there is no built-in way to avoid this, either you need to ensure you don't pass in input that cannot be parsed or you need to write your own parser that has more knowledge of preferred units or maybe only a subset of the units.
Example:
Length.Parse("1 pt")
throws AmbiguousUnitParseException
with message Cannot parse "pt" since it could be either of these: DtpPoint, PrinterPoint
.
Sometimes you need to work with quantities and units at runtime, such as parsing user input. There are three classes to help with this:
- UnitParser for parsing unit abbreviation strings like
cm
toLengthUnit.Centimeter
- UnitAbbreviationsCache for looking up unit abbreviations like
cm
given typeLengthUnit
and value1
(Centimeter
) - UnitConverter for converting values given a quantity name
Length
, a value1
and from/to unit namesCentimeter
andMeter
// This type was perhaps selected by the user in GUI from a list of units
Type lengthUnitType = typeof(LengthUnit); // Selected by user in GUI from a list of units
// Parse units dynamically
UnitParser parser = UnitParser.Default;
int fromUnitValue = (int)parser.Parse("cm", lengthUnitType); // LengthUnit.Centimeter == 1
// Get unit abbreviations dynamically
var cache = UnitAbbreviationsCache.Default;
string fromUnitAbbreviation = cache.GetDefaultAbbreviation(lengthUnitType, 1); // "cm"
double centimeters = UnitConverter.ConvertByName(1, "Length", "Meter", "Centimeter"); // 100
For more examples on dynamic parsing and conversion, see the unit conversion applications below.
Source code for Samples/UnitConverter.Wpf
Download (release 2018-11-09 for Windows)
This example shows how you can create a dynamic unit converter, where the user selects the quantity to convert, such as Length
or Mass
, then selects to convert from Meter
to Centimeter
and types in a value for how many meters.
NOTE: There are still some limitations in the library that requires reflection to enumerate units for quantity and getting the abbreviation for a unit, when we want to dynamically enumerate and convert between units.
If you can live with hard coding what quantities to convert between, then the following code snippet shows you one way to go about it:
// Get quantities for populating quantity UI selector
QuantityType[] quantityTypes = Enum.GetValues(typeof(QuantityType)).Cast<QuantityType>().ToArray();
// If Length is selected, get length units for populating from/to UI selectors
LengthUnit[] lengthUnits = Length.Units;
// Perform conversion using input value and selected from/to units
double inputValue; // Obtain from textbox
LengthUnit fromUnit, toUnit; // Obtain from ListBox selections
double resultValue = Length.From(inputValue, fromUnit).As(toUnit);
The purpose of this app is to show how to create an IValueConverter
in order to bind XAML to quantities.
NOTE: A lot of reflection and complexity were introduced due to not having a base type. See #371 for discussion on adding base types.
A base unit is chosen for each unit class, represented by a double value (64-bit), and all conversions go via this unit. This means that there will always be a small error in both representing other units than the base unit as well as converting between units.
Units.NET was intended for convenience and ease of use, not highly accurate conversions, but I am open to suggestions for improvements.
The tests accept an error up to 1E-5 for most units added so far. Exceptions include units like Teaspoon, where the base unit cubic meter is a lot bigger. In many usecases this is sufficient, but for others this may be a showstopper and something you need to be aware of.
For more details, see Precision.
Important! We cannot guarantee backwards compatibility, although we will strive to do that on a "best effort" basis and bumping the major nuget version when a change is necessary.
The base unit of any unit should be treated as volatile as we have changed this several times in the history of this library already. Either to reduce precision errors of common units or to simplify code generation. An example is Mass, where the base unit was first Kilogram as this is the SI unit of mass, but in order to use powershell scripts to generate milligrams, nanograms etc. it was easier to choose Gram as the base unit of Mass.
This project is still early and many units and conversions are not yet covered. If you are missing something, please help by contributing or ask for it by creating an issue.
Please read the wiki on Adding a New Unit.
Generally adding a unit involves adding or modifying UnitsNet\UnitDefinitions\*.json
files and running generate-code.bat
to regenerate the source code and test code stubs, then manually implementing the new unit conversion constants in the test code.
- Fork the repo
- Do work on branches such as feature/add-myunit and fix/34
- Create a pull request
AppVeyor performs the following:
- Build and test all branches
- Build and test pull requests, notifies on success or error
- Deploy nugets on master branch, if nuspec versions changed
It would be awesome to know who are using this library. If you would like your project listed here, create an issue or edit the README.md and send a pull request. Max logo size is 300x35 pixels
and should be in .png
, .gif
or .jpg
formats.
Sports performance applications for Windows and iOS, that combine high-speed video with sensor data to bring facts into your training and visualize the invisible forces at work
Units.NET started here in 2007 when reading strain gauge measurements from force plates and has been very useful in integrating a number of different sensor types into our software and presenting the data in the user's preferred culture and units.
https://www.swingcatalyst.com (for golf)
https://www.motioncatalyst.com (everything else)
- Andreas Gullberg Larsen, CTO (andreas@motioncatalyst.com)
Award-winning performers and composers put everything they’ve got into their music. PK Sound makes sure their fans will hear it all – brilliantly, precisely, consistently.
PK Sound uses UnitsNet in Kontrol - the remote control counterpart to Trinity, the world's only robotic line array solution.
http://www.pksound.ca/pk-sound/announcing-the-official-release-of-kontrol/ (for an idea of what the Kontrol project is)
http://www.pksound.ca/trinity/ (the speakers that Kontrol currently controls)
http://www.pksound.ca/ (everything else)
- Jules LaPrairie, Kontrol software team member
Microsoft.IoT.Devices extends Windows IoT Core and makes it easier to support devices like sensors and displays. It provides event-driven access for many digital and analog devices and even provides specialized wrappers for devices like joystick, rotary encoder and graphics display.
http://aka.ms/iotdevices (home page including docs)
http://www.nuget.org/packages/Microsoft.IoT.Devices (NuGet package)
Software for creating printable hex maps for use in pen and paper RPGs. Both a user-friendly app and a high-level library for generating labelled hexmaps.
https://bitbucket.org/MartinEden/Crawlspace
- Martin Eden, project maintainer