Giter Site home page Giter Site logo

angularsen / unitsnet Goto Github PK

View Code? Open in Web Editor NEW
2.1K 34.0 359.0 64.22 MB

Makes life working with units of measurement just a little bit better.

Home Page: https://www.nuget.org/packages/UnitsNet/

License: MIT No Attribution

PowerShell 1.85% C# 94.07% Batchfile 0.39% Shell 3.69%
conversion units-of-measure units powershell csharp quantities unit-converter abbreviations parse quantity

unitsnet's Introduction

Build Status codecov StandWithUkraine

Units.NET

Add strongly typed quantities to your code and get merrily on with your life.

No more magic constants found on Stack Overflow, no more second-guessing the unit of parameters and variables.

Upgrading from 4.x to 5.x
Upgrading from 5.x to 6.x (still in prerelease and may yet change)

Overview

Installing via NuGet

Add it via CLI

dotnet add package UnitsNet

or go to NuGet Gallery | UnitsNet for detailed instructions.

Build Targets

Static Typing

// 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)
{
    // Compile error! Newtons belong to Force, not Mass. A common source of confusion.
    double weightNewtons = weight.Newtons;

    // Convert to the unit of choice - when you need it
    return $"You weigh {weight.Kilograms:F1} kg.";
}

Operator Overloads

// 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);

Culture and Localization

The culture for abbreviations defaults to Thread.CurrentCulture 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 CurrentCulture for abbreviation language number formatting. This is consistent with the behavior of the .NET Framework,
// where DateTime.ToString() uses CurrentCulture for the whole string, likely because mixing an english date format with a russian month name might be confusing.
Thread.CurrentThread.CurrentCulture = 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"

Gotcha: AmbiguousUnitParseException

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.

Dynamically Parse Quantities and Convert to Units

Sometimes you need to work with quantities and units at runtime, such as parsing user input.

There are a handful of classes to help with this:

  • Quantity for parsing and constructing quantities as well as looking up units, names and quantity information dynamically
  • UnitConverter for converting values to a different unit, with only strings or enum values
  • UnitParser for parsing unit abbreviation strings, such as "cm" to LengthUnit.Centimeter

Quantity - Enumerate quantities and units at runtime

Use Quantity class for looking up QuantityInfo and UnitInfo at runtime.

string[] names = Quantity.Names;     // ["Length", "Mass", ...]
QuantityInfo[] qis = Quantity.Infos; // All quantities and their units, types, values.

// Look up quantity by name.
QuantityInfo lengthInfo = Quantity.ByName["Length"];
UnitInfo[] lengthUnits = lengthInfo.UnitInfos;

// Look up unit by enum value (note: for extensibility, will instead look up by name in the future)
UnitInfo cmInfo = Quantity.GetUnitInfo(LengthUnit.Centimeter);

QuantityInfo - Information about a quantity

QuantityInfo makes it easy to get names, units, types and values for a quantity. This is useful for populating lists of quantities and units for the user to choose.

// Different ways to look up the quantity info.
QuantityInfo lengthInfo = Quantity.ByName["Length"];
lengthInfo = Length.Info;
lengthInfo = Length.FromMeters(1).QuantityInfo;

// The quantity information.
lengthInfo.Name;            // "Length"
lengthInfo.UnitInfos;       // UnitInfo[] for its units Centimeter, Meter, etc.
lengthInfo.BaseUnitInfo;    // UnitInfo for LengthUnit.Meter
lengthInfo.BaseDimensions;  // {"Length": 1, "Mass": 0, ...}
lengthInfo.UnitType;        // typeof(LengthUnit)
lengthInfo.ValueType;       // typeof(Length)
lengthInfo.Zero;            // Length.Zero

UnitInfo - Information about a unit

UnitInfo describes a unit, such as its enum value, names and its representation in SI base units.

// Different ways to look up the unit info.
var cm = Quantity.GetUnitInfo(LengthUnit.Centimeter);

if (Quantity.TryGetUnitInfo(LengthUnit.Centimeter, out UnitInfo tryGetCm)) {
    cm = tryGetCm;
}

// The unit information.
cm.Value;       // Enum value: LengthUnit.Centimeter
cm.Name;        // "Centimeter"
cm.PluralName;  // "Centimeters"
cm.BaseUnits;   // {"Length": Centimeter, "Mass": null, "Time": null, ...}

Construct quantity

All you need is the value and the unit enum value.

IQuantity quantity = Quantity.From(3, LengthUnit.Centimeter); // Length

if (Quantity.TryFrom(3, LengthUnit.Centimeter, out IQuantity quantity2))
{
}

You can also construct from strings, such as mapping between DTO types in an API:

IQuantity quantity = Quantity.From(value: 3, quantityName: "Length", unitName: "Centimeter");

if (Quantity.TryFrom(value: 3, quantityName: "Length", unitName: "Centimeter", out IQuantity? quantity2))
{
}

Or create by just the unit abbreviation, as long as there is exactly one unit with this abbreviation.

// Length with unit LengthUnit.Centimeter
IQuantity quantity = Quantity.FromUnitAbbreviation(3, "cm");

if (Quantity.TryFromUnitAbbreviation(3, "cm", out IQuantity? quantity2))
{
}

Parse quantity

Parse any string to a quantity instance of the given the quantity type.

IQuantity quantity = Quantity.Parse(typeof(Length), "3 cm"); // Length

if (Quantity.TryParse(typeof(Length), "3cm", out IQuantity quantity2)
{
}

Parse unit

UnitParser parses unit abbreviation strings to unit enum values.

Enum unit = UnitParser.Default.Parse("cm", typeof(LengthUnit)); // LengthUnit.Centimeter

if (UnitParser.Default.TryParse("cm", typeof(LengthUnit), out Enum unit2))
{
    // Use unit2 as LengthUnit.Centimeter
}

Convert quantity to unit - IQuantity and Enum

Convert any IQuantity instance to a different unit by providing a target unit enum value.

// Assume these are passed in at runtime, we don't know their values or type
Enum userSelectedUnit = LengthUnit.Millimeter;
IQuantity quantity = Length.FromCentimeters(3);

// Later we convert to a unit
quantity.ToUnit(userSelectedUnit).Value;      // 30
quantity.ToUnit(userSelectedUnit).Unit;       // LengthUnit.Millimeter
quantity.ToUnit(userSelectedUnit).ToString(); // "30 mm"
quantity.ToUnit(PressureUnit.Pascal);         // Throws exception, not compatible
quantity.As(userSelectedUnit);                // 30

Convert quantity to unit - From/To Enums

Useful when populating lists with unit enum values for the user to choose.

UnitConverter.Convert(1, LengthUnit.Centimeter, LengthUnit.Millimeter); // 10 mm

Convert quantity to unit - Names or abbreviation strings

Sometimes you only have strings to work with, that works too!

UnitConverter.ConvertByName(1, "Length", "Centimeter", "Millimeter"); // 10 mm
UnitConverter.ConvertByAbbreviation(1, "Length", "cm", "mm"); // 10 mm

Custom units

Units.NET allows you to add your own units and quantities at runtime, to represent as IQuantity and reusing Units.NET for parsing and converting between units.

Read more at Extending-with-Custom-Units.

Map between unit enum values and unit abbreviations

// Map unit enum values to unit abbreviations
UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(HowMuchUnit.Some, "sm");
UnitAbbreviationsCache.Default.GetDefaultAbbreviation(HowMuchUnit.Some); // "sm"
UnitParser.Default.Parse<HowMuchUnit>("sm");  // HowMuchUnit.Some

Convert between units of custom quantity

var unitConverter = UnitConverter.Default;
unitConverter.SetConversionFunction<HowMuch>(HowMuchUnit.Lots, HowMuchUnit.Some, x => new HowMuch(x.Value * 2, HowMuchUnit.Some));
unitConverter.SetConversionFunction<HowMuch>(HowMuchUnit.Tons, HowMuchUnit.Lots, x => new HowMuch(x.Value * 10, HowMuchUnit.Lots));
unitConverter.SetConversionFunction<HowMuch>(HowMuchUnit.Tons, HowMuchUnit.Some, x => new HowMuch(x.Value * 20, HowMuchUnit.Some));

var from = new HowMuch(10, HowMuchUnit.Tons);
IQuantity Convert(HowMuchUnit toUnit) => unitConverter.GetConversionFunction<HowMuch>(from.Unit, toUnit)(from);

Console.WriteLine($"Convert 10 tons to:");
Console.WriteLine(Convert(HowMuchUnit.Some)); // 200 sm
Console.WriteLine(Convert(HowMuchUnit.Lots)); // 100 lts
Console.WriteLine(Convert(HowMuchUnit.Tons)); // 10 tns

Parse custom quantity

QuantityParser parses quantity strings to IQuantity by providing a UnitAbbreviationsCache with custom units and unit abbreviations.

// Alternatively, manipulate the global UnitAbbreviationsCache.Default.
var unitAbbreviationsCache = new UnitAbbreviationsCache();
unitAbbreviationsCache.MapUnitToAbbreviation(HowMuchUnit.Some, "sm");
unitAbbreviationsCache.MapUnitToAbbreviation(HowMuchUnit.ATon, "tn");

var quantityParser = new QuantityParser(unitAbbreviationsCache);

// 1 Some
HowMuch q = quantityParser.Parse<HowMuch, HowMuchUnit>(
    str: "1 sm",
    formatProvider: null,
    fromDelegate: (value, unit) => new HowMuch((double) value, unit));

Example: Unit converter app

Source code for Samples/UnitConverter.Wpf
Download (release 2018-11-09 for Windows)

image

This example shows how you can create a dynamic unit converter, where the user selects the quantity to convert, such as Temperature, then selects to convert from DegreeCelsius to DegreeFahrenheit and types in a numeric value for how many degrees Celsius to convert. The quantity list box contains quantity names, such as "Length". The two unit list boxes contain Enum values, such as LengthUnit.Meter.

Populate quantity selector

Use Quantity to enumerate all quantity names, such as "Length" and "Mass".

this.Quantities = Quantity.Names; // string[]

// or
this.Quantities = Quantity.Infos.Select(i => i.Name).ToList();

Update unit lists when selecting new quantity

So user can only choose from/to units compatible with the quantity type.

QuantityInfo quantityInfo = Quantity.ByName[quantityName];

_units.Clear();
foreach (Enum unitValue in quantityInfo.UnitInfos.Select(ui => ui.Value))
{
    _units.Add(new UnitListItem(unitValue));
}

Update calculation on unit selection changed

Using UnitConverter to convert by unit enum values as given by the list selection "Length" and unit names like "Centimeter" and "Meter".

double convertedValue = UnitConverter.Convert(
    FromValue,                      // numeric value
    SelectedFromUnit.UnitEnumValue, // Enum, such as LengthUnit.Meter
    SelectedToUnit.UnitEnumValue);  // Enum, such as LengthUnit.Centimeter

Example: WPF app using IValueConverter to parse input

Src: Samples/MvvmSample.Wpf

wpfmvvmsample_219w

The purpose of this app is to show how to create an IValueConverter in order to bind XAML to quantities.

Precision and Accuracy

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.

Serialize to JSON, XML and more

Read the wiki on Serializing to JSON, XML and more.

Want To Contribute?

Continuous Integration

Azure DevOps 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

Who are Using This?

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.

Motion Catalyst logo

Swing Catalyst and Motion Catalyst, Norway

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 ([email protected])

PK Sound logo

PK Sound, Canada

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

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)

Crawlspace

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

ANSYS, Inc. Logo

ANSYS, Inc. (ANSYS Discovery Live)

ANSYS Discovery Live provides instantaneous 3D simulation, tightly coupled with direct geometry modeling, to enable interactive design exploration and rapid product innovation. It is an interactive experience in which you can manipulate geometry, material types or physics inputs, then instantaneously see changes in performance.

https://www.ansys.com https://www.ansys.com/products/3d-design/ansys-discovery-live

- Tristan Milnthorp, Principal Software Architect ([email protected])

Primoris Sigma Stargen

Stargen is a decades old software to create realistic planets and satellites from a given Star. It's based on work from various scientists and been used for years. Primoris Sigma Stargen is a C# port of the utility that makes it a Framework to extend it with new algorithms for planetary formation and physics equations.

https://github.com/ebfortin/primoris.universe.stargen

Harrington Hoists, Inc. (A Subsidiary of KITO Americas, Inc.)

Harrington Hoists, Inc. is located in Manheim, PA, Elizabethtown, PA, South Holland, IL and Corona, CA. Harrington is a leading manufacturer of manual, electric and air chain hoists as well as wire rope hoists and crane products serving the North American material handling industry.

Harrington uses UnitsNet in their internal software to perform many different calculations related to crane dimensioning, girder strength, electrical safety verification, etc.

https://www.harringtonhoists.com
https://kito.com

- Luke Westfall, Design Automation Engineer

Structural Analysis Format - SDK project

The Structural Analysis Format (SAF) has been created to allow structural engineering applications to exchange data using a straight forward and simple to understand format. While inspired by IFC, SAF has its benefits that it's easily modifyable by the end-user (it's an xlsx file), well documented and easy to understand. UnitsNet is used by the SDK provided by SCIA to facilitate import / export between metric & imperial systems

https://www.saf.guide https://github.com/StructuralAnalysisFormat/StructuralAnalysisFormat-SDK

- Dirk Schuermans, Software Engineer for SCIA nv

Units.NET on other platforms

Get the same strongly typed units on other platforms, based on the same unit definitions.

Language Name Package Repository Maintainers
JavaScript /
TypeScript
unitsnet-js npm github @haimkastner
Python unitsnet-py pypi github @haimkastner

unitsnet's People

Contributors

angularsen avatar baxcoders avatar bplubell avatar bretthysuik avatar dschuermans avatar ebfortin avatar eriove avatar gojanpaolo avatar haimkastner avatar heytherefred avatar jentechsystems avatar jksnd avatar jnyrup avatar josesimoes avatar lipchev avatar lwestfall avatar maherkassim avatar mathiasvda avatar mludlum avatar mperdeck avatar neutmute avatar nfbot avatar ngeslin avatar rohahn avatar supermihi avatar tmilnthorp avatar trb5016 avatar trevorvonseggern avatar ulflind avatar vitasimek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unitsnet's Issues

Use T4 templates to generate unit code

This has been on my wishlist for some time. Started a T4 branch today and got a lot of good stuff done.

It's quite a big task and refactoring, but it will greatly simplify adding and managing the units and constants. I've currently got Force, Length and Mass working, the rest should come soon. I expect to be ready to merge into master this week.

Abbreviation for CubicFootPerSecond is wrong

in UnitsNet/GeneratedCode/UnitSystem.Default.g.cs
lines 453-457:
new CulturesForEnumValue((int) FlowUnit.CubicFootPerSecond,
new[]
{
new AbbreviationsForCulture("en-US", "ft³/h"),
}),

The abbreviation should be "ft³/s"

Serializing/deserializing nullable types fails in certain situations

The following scenarios result in incorrectly serialized data or failures when deserializing:

  • Serializing a non-null nullable value, but only when nested within another object
  • Deserializing a non-null nullable value as a nullable value

I know this is quite confusing so here are some unit tests that fail:

// Serialization
[Test]
public void NonNullNullableValueNestedInObject_ExpectJsonUnaffected()
{
    var testObj = new TestObj()
        {
            NullableFrequency = Frequency.FromHertz(10),
            NonNullableFrequency = Frequency.FromHertz(10)
        };
    string expectedJson = "{\r\n  \"NullableFrequency\": {\r\n  \"Unit\": \"FrequencyUnit.Hertz\",\r\n  \"Value\": 10.0\r\r}," +
                            "{\r\n  \"NonNullableFrequency\": {\r\n  \"Unit\": \"FrequencyUnit.Hertz\",\r\n  \"Value\": 10.0\r\r}\r\n}";

    string json = SerializeObject(testObj);

    Assert.That(json, Is.EqualTo(expectedJson));
}

internal class TestObj
{
    public Frequency? NullableFrequency { get; set; }
    public Frequency NonNullableFrequency { get; set; }
}


// Deserialization
[Test]
public void NonNullNullableValue_ExpectValueDeserializedCorrectly()
{
    Mass? nullableMass = Mass.FromKilograms(10);
    string json = SerializeObject(nullableMass);

    var deserializedNullableMass = DeserializeObject<Mass?>(json);

    // Fails because the corresponding scenario on the serializer side fails
    Assert.That(deserializedNullableMass.Value, Is.EqualTo(nullableMass.Value));
}

[Test]
public void NonNullNullableValueNestedInObject_ExpectValueDeserializedCorrectly()
{
    var testObj = new TestObj()
        {
            NullableFrequency = Frequency.FromHertz(10),
            NonNullableFrequency = Frequency.FromHertz(10)
        };
    string json = SerializeObject(testObj);

    var deserializedTestObj = DeserializeObject<TestObj>(json);

    Assert.That(deserializedTestObj.NullableFrequency, Is.EqualTo(testObj.NullableFrequency));
}

ApostropheDigitGroupingCultureFormatting test not passing

@bretthysuik Hey I just noticed a test is not passing on my computer. I just can't figure it out, because the code looks good. I even tried with LinqPad, and "fr-CH" culture simply does not output apostrophes. Is it possible that this is related to the locale or region settings of the computer, even if the culture is specifically specified?

Test result:

  String lengths are both 7. Strings differ at index 1.
  Expected: "1'111 m"
  But was:  "1 111 m"

LinqPad:
11111111.122321m.ToString("#,0.##", System.Globalization.CultureInfo.CreateSpecificCulture("fr-CH"))

Outputs:
11 111 111,12

According to this SO thread it should be working as far as I can tell.
http://stackoverflow.com/a/11513242/134761

AutoUnitRecognizing

Hi
i am working with a lot of numeric data in engineering field and using UNITSNET in my code.
because of different units always i should be careful about units and it makes hard in coding.
BUT:
if there was an ability for this library that from two base unit (length and force) easily it can find out what other units are. i mean that imagine for a set of data length is in "m" (meter) and force is in "N" (Newton) so other units are:
Torque: N-m
Pressure: N/m^2
Area: m^2
Volume: m^3
Density: N/m^3
So I have a Suggestion For This:
In "unitsnet>units" name space , add functions for each unit that can be recognize by other units,
Example in VB.NET Language:

imports Unitsnet.units
Function Torqueunit (Length as units.length, force as units.force) as units.torque
Dim Result As Units.torque
if length=length.meter and force=force.Newton then
result=Torque.newtonmeter
elseif length=length.centimetermeter and force=force.Newton then
result=Torque.newtoncentimeter
elseif . . .
endif
Return Result
End Function

Add types to represent 2 and 3-dimensional data

Usecases:

  • Area can be represented with Length2
  • Volume can be represented with Length3
  • 3D/2D force vectors can be represented with Force3 and Force2

To consider:

  • Should all types have 2 and 3 dimensional overloads out of the box, or hand pick units where it is common to work with multiple dimensions?
  • Naming scheme: Length2, Length2d, Vector3, V3 etc..

Supporting non-standard specialty units

From issue #45 concerning the topic of supporting non-standard specialty units such as power ratio with units dBmW (decibels relative to 1 milliwatt) and dBW (decibels relative to 1 watt):

As for the domain specific units, I'm not sure whether they should be part of the main library or not. I can easily see a domain specific nuget with dependency on UnitsNet, such as UnitsNet.Audio. What do you think and if you agree, what naming would be natural? Setting up a new nuget would involve creating a new set of projects for Audio, setting the output path to a Audio subfolder of the current output path and modifying the build scripts to build, pack and publish both nugets.

On the other hand, it's still a small library and maybe we can postpone splitting up into multiple nugets until there is a demand for it and possibly many more domain specific units, and bump the major version to indicate breaking changes. At this point I'm happy with either way.

parsing all unit types

I have the need for a function like this:

double Convert(double value, string currentUnits, string finalUnits);

I cannot see how to do this with your library as the Parse method requires a strong type. I know that currentUnits and finalUnits are the same metric, but I don't know ahead of time if which metric they are. They could be length, angle, angular velocity, velocity, or one of several others.

Releases and Changes

Creating a thread for announcing releases.

v1.11 released.

Fixed bugs in Flow and RotationalSpeed units after refactoring to T4 templates (thanks George Zhuikov).
Added Temperature units.

JSON serialization/deserialization

The Problem

Currently, every type in this library will be deserialized to 0.0 which is default(double) since double is used as the backing type for every unit.

Since every type in this library is a custom value type (struct) Json.NET (the de facto JSON library for .NET) needs custom converters in the deserialization process.

The Cause

I'm pretty sure it's related to all the unit types having read-only properties calculated from a base unit with a single constructor for that base unit. Json.Net probably doesn't know how to reconstruct the type using the base unit.

To Reproduce

var jsonSerializerSettings = new JsonSerializerSettings()
    {
        TypeNameHandling = TypeNameHandling.Objects,
        Formatting = Formatting.Indented,
        ObjectCreationHandling = ObjectCreationHandling.Replace
    };

var freq = Frequency.FromMegahertz(55);
string serializedFreq = JsonConvert.SerializeObject(freq, jsonSerializerSettings);
Frequency deserializedFreq = JsonConvert.DeserializeObject<Frequency>(serializedFreq, jsonSerializerSettings);

Console.WriteLine(deserializedFreq.Megahertz); // 0.0

Possible Solution

I think the only solution is to write custom JsonConverters for each unit type. Hopefully this can be auto-generated using the code generator scripts (I haven't looked into this).

I think it's probably unecessary to serialize every unit for each type: only the base unit should be serialized. For example, this is what a serialized Mass value looks like currently and it's a bit of a mess:

{
  "$type": "UnitsNet.Mass, UnitsNet",
  "StonePounds": {
    "$type": "UnitsNet.StonePounds, UnitsNet",
    "Stone": 0.0,
    "Pounds": 3.3069339327731635
  },
  "Centigrams": 150000.0,
  "Decagrams": 150.0,
  "Decigrams": 15000.0,
  "Grams": 1500.0,
  "Hectograms": 15.0,
  "Kilograms": 1.5,
  "Kilotonnes": 1.5E-06,
  "LongTons": 0.001476309791416591,
  "Megatonnes": 1.5E-09,
  "Micrograms": 1500000000.0,
  "Milligrams": 1500000.0,
  "Nanograms": 1500000000000.0,
  "Ounces": 52.910942850000005,
  "Pounds": 3.3069339327731635,
  "ShortTons": 0.0016534669663865818,
  "Stone": 0.23620975930540469,
  "Tonnes": 0.0015
}

Parsing feet and inches ignores inches in results

Code to replicate:

string length = "60 ft 1 in";
Length l = Length.Parse(length);
string s = l.FeetInches.ToString();

l.Feet is now 60 instead of the actual value of 60.0833333333

s is "60 ft 0 in" instead of being equal to length.

Moved repository to new github account

I decided to move this repository out of the company's account after talking to my colleagues. Although inspired by a need for units at work, it started out as my personal hobby project and has been maintained outside work hours.

For all of you outside the company, it should not affect you much:

  • The old URL still works and redirects you here.
  • Git fetch, push and clone will still work against the old URL, however...
  • It's recommended to update your git remote to point here, or simply clone the project from scratch

For more info:
https://help.github.com/articles/transferring-a-repository/#redirects-and-git-remotes

Old URL: https://github.com/initialforce/unitsnet
New URL: https://github.com/anjdreas/unitsnet

ToString() truncates small values

Example:

Information info = Information.FromBits(1000);
string gigabits = info.ToString(InformationUnit.Gigabit);
// returns "0 Gb", but I would expect "1e-6 Gb" or "0.000001 Gb"

The string is being truncated due to the autogenerated ToString() code which only contains 2 decimal places:

public string ToString(InformationUnit unit, CultureInfo culture = null)
{
    return ToString(unit, culture, "{0:0.##} {1}");
}

I think forcing consumers to use the 4 parameter ToString() overload is too onerous and not very intuitive, plus they need to know beforehand whether their value is too small to be displayed properly so they can call the correct overload.


Possible solution: Check if the converted value is smaller than 0.001. Anything under 0.001 is auto-converted to scientific/exponential notation. Example implementation:

// Provides default behavour that works in every situation to correctly format a value. 
// If a consumer wants exact control over the formatting they can use the 4 parameter overload.
public string ToString(InformationUnit unit, CultureInfo culture = null)
{
    const string defaultFormat = "{0:0.###} {1}";
    double convertedValue = As(unit);
    string format = defaultFormat;
    if (convertedValue < 1e-3)
        format = "{0:0.###e-0} {1}";
    else if (convertedValue > 1e3)
        format = "{0:0.###e0} {1}";

    return string.Format(culture, format, BuildToStringArgs(unit, culture));
}

// This overload does not have its behavour changed.
public string ToString(InformationUnit unit, CultureInfo culture, string format, params object[] args)
{
    return string.Format(culture, format, BuildToStringArgs(unit, culture, args));
}

private object[] BuildToStringArgs(InformationUnit unit, CultureInfo culture, params object[] args)
{
    string abbreviation = UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit);

    return new object[] { As(unit), abbreviation }.Concat(args).ToArray();
}

Thread-safety issue

UnitSystem class is using static Dictionary here which makes the class not thread-safe.

UnitSystem.GetCached is used from the Parse() method which makes the Parse method also not thread-safe.

The result is NullReferenceException.

Sample stack trace:
at System.Collections.Generic.Dictionary.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary.set_Item(TKey key, TValue value)
at UnitsNet.UnitSystem.GetCached(IFormatProvider cultureInfo)
at UnitsNet.Mass.ParseUnit(String str, IFormatProvider formatProvider)
at UnitsNet.Mass.ParseWithRegex(String regexString, String str, IFormatProvider formatProvider)
...

Expand dimensionless unit support (in particular, ratios)

I'm writing a library of units and conversions in the area of well logging, an area of engineering (like many areas of engineering) with dozens of obscure units.

An area I'm having particular difficulty with is dimensionless units like ratios (including ratio, percentage, parts-per-million, parts-per-billion, grams per kilogram etc), counts (radiation ticks per second and so on), and obscure externally-defined dimensionless units (like the "Gamma Ray American Petroleum Institute Unit", a measure of the ratio of radiation ticks over a fixed time between two specific radiation sources stored at the University of Houston).

I don't want to add anything industry specific in UnitsNet, so I'd like enough support for things like the above-mentioned ratios (and a RatioAttribute to define percentage and parts per million etc?), counts or rates, and some form of unit like "Arbitrary" that I could use for the weird stuff, and which would be better than using the "Undefined" unit.

silverlight 5 support

Hi,

Trying to deploy via Nuget package manager, the following error pops up :

Successfully installed 'UnitsNet 3.12.0'.
Successfully uninstalled 'UnitsNet 3.12.0'.
Install failed. Rolling back...
Could not install package 'UnitsNet 3.12.0'. You are trying to install this package into a project that targets 'Silverlight,Version=v5.0', but the package does not contain any assembly references that are compatible with that framework. For more information, contact the package author.

The readme lists silverlight 5 as one of the target environments, can you direct me towards any previous release that supports it?

EnumUtils missing

I noticed that EnumUtils.GetEnumValues has gone missing since v3.0. Is there an equivalent/replacement?

Json.NET conversion

Hello - I tried persisting the Area type with Newtonsoft's Json.NET but by default it makes a big nested object with all the internal types like this

{
    SquareCentimeters: 200000.0,
    SquareDecimeters: 2000.0,
    SquareFeet: 215.27830102364831,
    SquareInches: 31000.062000124002,
    SquareKilometers: 2E-05,
    SquareMeters: 20.0,
    SquareMiles: 7.7220077220077222E-06,
    SquareMillimeters: 20000000.0,
    SquareYards: 23.919811224849816
}

when what I need is just the simple m^2 value of 20.0 (Neo4j database can't persist the nested object).

I wrote a custom converter and it works nicely
https://github.com/neutmute/Neo4jClient.Extension/blob/cskardon-T-3/Neo4jClient.Extension.Test/CustomConverters/AreaJsonConverter.cs

This looks like it could be generated with some magical powershell scripts.
I'm not sure if my problem is an edge case or of wider value.

Would you consider a PR with an extra project added: UnitsNet.JsonConverters say?

Generate test code

I think it is a good idea to manually enter constants in the test code as a way of double checking that the output of conversions behave as expected, but there is a lot of test code that is not directly related to constants but rather the behavior, such as testing IComparable is implemented and that TryConvert does not throw exception etc. This part makes sense to generate test code for to reduce the (significant) work required when adding new units or new unit classes.

Parse quantity and unit from string

Add Parse(string) to unit classes. Should handle integers, decimals and different variations of whitespace and multiple case-sensitive abbreviations per unit.

Examples:

  • 1kg, 1 kg => 1 kilogram
  • 1l, 1L, 1 l, 1 L => 1 liter
Volume.Parse("1L") == Volume.FromLiters(1)

R# warning: impure method on ToString()

The same warning for all unit classes.

public string ToString(ForceUnit unit, CultureInfo culture, string format, params object[] args){}

If you call ToString() on a read-only field, R# will warn you about impure method called on read-only field. Not sure, but could be due to calling As() method internally.

Investigate if this should/can be fixed.

Unit tests for non Norwegians

Not a real issue but in your unit tests (UnitsNet/UnitsNet.Tests/UnitSystemTests.cs) you assume the current ui culture to be always for Norway. While this might hold true for you, it probably will not for others.

   [Test]
    public void AllUnitsImplementToStringForNorwegian()
    {
        CultureInfo originalCulture = Thread.CurrentThread.CurrentUICulture;
        try
        {
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; // <-- here

Represent rate of change more generically

Similar to discussion on dimensions in #73, I speculate if there is a need for a more generic way of expressing rate of change for any type of unit. Currently we have the following rate of change units:

Flow (volume over time)
Speed (distance change over time)
Acceleration (speed change over time)
RotationalSpeed (angle change over time)

In #88 there are some further suggestions to units, such as
PressureChangeRate (pressure change over time)
RotationalSpeedChangeRate (angular speed change over time)
ValveDriveSpeed (fraction change over time)

Delete tags in your local repo

I just did a Christmas cleanup on the tags unifying to the same format:

  • 1.5
  • 3.0
  • 3.0-beta
  • 3.0.1 and so on

This means everyone who is actively contributing should remove your local tags and fetch new ones from the server, or else the old tags will spread like the plague in Egypt when I checkout your pull request locally.

http://stackoverflow.com/a/5373319/134761

git tag -l | xargs git tag -d
git fetch

Ratio.PartsPerTrillions is wrong

Values is probably too small to be represented properly.

public static Ratio FromPartsPerTrillions(double partspertrillions)
{
  return new Ratio(0.0 / 1.0 * partspertrillions);
}

public double PartsPerTrillions
{
  get
  {
    return this.DecimalFractions / (0.0 / 1.0);
  }
}

Missing abbreviations for many units

The invariant, English and Norwegian cultures are missing abbreviations for several units that have been added lately. Write a unit test to ensure all units have abbreviations in all cultures.

[Idea] GUI controls

Hello again!

I'm thinking about creating some GUI controls specifically tailored for this project. The idea is a combination numeric spinner and combobox. The spinner portion is for entering the value and the combobox chooses the unit.

The Value property would be the actual unit type instead of a raw decimal. Changing the unit will automatically recalculate the previous value (e.g. if you enter 500 MHz initially and then change to GHz, the value would be updated to 0.5 GHz)

unitnet_gui_control

I'll probably create a WinForms and WPF version of the control.

Do you think this would be useful?

UnitsNet.2013.sln, UnitsNet.2015.sln

Are UnitsNet.2013.sln, UnitsNet.2015.sln really necessary?
VS 2013 can open VS 2015 projects.
Having the two solutions means keeping them in sync.
I'd suggest

  • deleting UnitsNet.2013.sln
  • renaming UnitsNet.2015.sln to UnitsNet.sln

thoughts?

Reverting back to github flow branching style

After a period of time using gitflow branching style, I am reverting back to github flow. For small projects, the github flow just gets in the way of rapid releases.

The main difference is:

  • Added a master branch that is now the main branch
  • Removed develop and stable branches
  • Any open pull requests based on develop should be rebased onto master
  • You should delete your local develop and stable branches, but it is not necessary
  • Stabilization and release tagging happens directly on master branch, instead of going branching out release/x.x.x branches from develop and merging in to master/develop. Release branches can still be used when it makes sense, such as for extensive beta testing.

Unit Definition Name Convention for Acre Units (USSurvey and International)?

I am realizing that I need to make a distinction between the 2 acre units, USSurvey and International.

I am not seeing a unit naming convention in the existing code--is there one?

I first went with "SingularName": "InternationalAcre", but a "SingularName": "AcreInternational" and "SingularName": "AcreUSSurvey" produces intuitive intellisense.

Or are unqualified units assumed to be international (like in the Mile unit definition in Length.json)?

Thoughts?

Support non-linear unit conversions

Currently the unit attributes support either a constant factor or a linear expression of the form y = ax + b. The latter was needed for conversion between temperature units. All other units so far use only a conversion factor.

However, there are non-linear units and unit conversions and there is currently no way of adding those using the current T4 templates.

Examples of non-linear units and unit conversions:
http://en.wikipedia.org/wiki/Sound_pressure
http://www.sengpielaudio.com/calculator-soundlevel.htm

Possible solution:
Use Expression to describe the conversion function, such as

[Length(x => 1000x)] Kilometer,
[SoundPressureLevel(x => 10_Math.Log(x_x/Math.Pow(20e-6, 2))] Decibel

The generated code will then call the expression to calculate the value. Note that this may(?) have significant performance impact, need to investigate. In that case, we should only use this for units that need it and keep the linear function for all other units since the compiler can reduce that to simple multiplication by and addition of constants.


Side note on sound pressure level as an example of non-linear unit:

  • Decibel is a generic unit, not just for sound.
  • Decibel in in this case is defined as sound pressure relative to a reference sound pressure, typically 20 micropascals in air, but wikipedia also states that underwater 1 micropascal is used. So this expression might need to take a second parameter, the reference value. Might become complicated to use. Need a real application or usage scenario for this unit to make sure it gets implemented right.

Add a wiki page for ToString() formatting

There's quite a bit of information scattered throughout the comments of #40, a lot of which is fairly important for consumers of this package.

@anjdreas, do you want me to create a wiki page with that information, or should I create a draft of the information and post it in this issue so that you can create the wiki page?

Can't serialize and deserialize units

I'm use these units in my project and I need to serialize and deserialize these values into xml, but I get empty xml tag, so there's no way to do this automatically.

Uses Units.Net with Entity Framework

I would like to use Units.Net in entity classes for Entity Framework. For example:

public class Box {
    public int Id { get; set; }
    public string Color { get; set; }
    public Length Width { get; set; }
    public Length Height { get; set; }
}

I found that EF ignored the Width and Height property (so I have only 2 columns left in the table) I don't sure that because of Length is struct or not.

Id Color
1 Yellow
2 Orange

It could be possible if in this case Length is a ComplexType class then it will be created with multiple embedded columns in database table such as Width_Amount and Width_Unit.

Id Color Width_Amount Width_Unit Height_Amount Height_Unit
1 Yellow 50 cm 90 cm
2 Orange 600 mm 120 mm

Please give me suggestion or your opinion on this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.