{"id":23540990,"url":"https://github.com/point85/caliper","last_synced_at":"2025-04-23T19:16:30.758Z","repository":{"id":13915551,"uuid":"73320257","full_name":"point85/caliper","owner":"point85","description":"Caliper is a project for managing units of measure and the conversions between them.","archived":false,"fork":false,"pushed_at":"2024-12-22T21:25:43.000Z","size":4376,"stargazers_count":16,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-22T22:23:07.295Z","etag":null,"topics":["java","jsr-363","measure-conversion","measurement-units","unit-of-measure","units","units-of-measure","units-of-measurement","uom"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/point85.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-09T20:51:10.000Z","updated_at":"2024-12-22T21:25:46.000Z","dependencies_parsed_at":"2024-12-04T02:32:29.991Z","dependency_job_id":"c367bdaa-a1c0-46ce-a782-79aec4d54c70","html_url":"https://github.com/point85/caliper","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/point85%2Fcaliper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/point85%2Fcaliper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/point85%2Fcaliper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/point85%2Fcaliper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/point85","download_url":"https://codeload.github.com/point85/caliper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231311646,"owners_count":18356593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","jsr-363","measure-conversion","measurement-units","unit-of-measure","units","units-of-measure","units-of-measurement","uom"],"created_at":"2024-12-26T05:13:29.224Z","updated_at":"2024-12-26T05:13:29.998Z","avatar_url":"https://github.com/point85.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Caliper\nThe Caliper library project manages units of measure and conversions between them.  Caliper is designed to be lightweight and simple to use, yet comprehensive.  It includes a large number of pre-defined units of measure commonly found in science, engineering, technology, finance and the household.  These recognized systems of measurement include the International System of Units (SI), International Customary, United States and British Imperial.  Custom units of measure can also be created in the Caliper unified measurement system.  Custom units are specific to a trade or industry such as industrial packaging where units of can, bottle, case and pallet are typical.  Custom units can be added to the unified system for units that are not pre-defined.  This java library is used in an OEE project that can be found at https://github.com/point85/OEE-Designer.\nThe Caliper library is also available in C# at https://github.com/point85/CaliperSharp.\n\nA Caliper measurement system is a collection of units of measure where each pair has a linear relationship, i.e. y = ax + b where 'x' is the abscissa unit to be converted, 'y' (the ordinate) is the converted unit, 'a' is the scaling factor and 'b' is the offset.  In the absence of a defined conversion, a unit will always have a conversion to itself.  A bridge unit conversion is defined to convert between the fundamental SI and International customary units of mass (i.e. kilogram to pound mass), length (i.e. metre to foot) and temperature (i.e. Kelvin to Rankine).  These three bridge conversions permit unit of measure conversions between the two systems.  A custom unit can define any bridge conversion such as a bottle to US fluid ounces or litres.\n \n## Concepts\n\nThe diagram below illustrates these concepts.\n![Caliper Diagram](https://github.com/point85/caliper/blob/master/doc/CaliperDiagram.png)\n \nAll units are owned by the unified measurement system. Units 'x' and 'y' belong to a relational system (such as SI or International Customary).  Units 'w' and 'z' belong to a second relational system.  Unit 'y' has a linear conversion to unit 'x'; therefore 'x' must be defined before 'y' can be defined.  Unit 'x' is also related to 'y' by x = (y - b)/a.  Unit 'w' has a conversion to unit 'z'.  Unit 'z' is related to itself by z = z + 0. Unit 'x' has a bridge conversion defined to unit 'z' (for example a foot to a metre).  Note that a bridge conversion from 'z' to 'x' is not necessary since it is the inverse of the conversion from 'x' to 'z'.\n \n*Scalar Unit* \n\nA simple unit, for example a metre, is defined as a scalar UOM.  A special scalar unit of measure is unity or dimensionless \"1\".  \n\n*Product Unit*\n\nA unit of measure that is the product of two other units is defined as a product UOM.  An example is a Joule which is a Newton-metre.  \n\n*Quotient Unit*  \n\nA unit of measure that is the quotient of two other units is defined as a quotient UOM. An example is a velocity, e.g. metre/second.  \n\n*Power Unit*\n\nA unit of measure that has an exponent on a base unit is defined as a power UOM. An example is area in metre^2. Note that an exponent of 0 is unity, and an exponent of 1 is the base unit itself. An exponent of 2 is a product unit where the multiplier and multiplicand are the base unit.  A power of -1 is a quotient unit of measure where the dividend is 1 and the divisor is the base unit.  \n\n*Type*\n\nUnits are classified by type, e.g. length, mass, time and temperature.  Only units of the same type can be converted to one another. Pre-defined units of measure are also enumerated, e.g. kilogram, Newton, metre, etc.  Custom units (e.g. a 1 litre bottle) do not have a pre-defined type or enumeration and are referred to by a unique base symbol.\n\n*Base Symbol*\n \nAll units have a base symbol that is the most reduced form of the unit.  For example, a Newton is kilogram-metre/second^2.  The base symbol is used in the measurement system to register each unit and to discern the result of arithmetic operations on quantities.  For example, dividing a quantity of Newton-metres by a quantity of metres results in a quantity of Newtons. \n\n*Quantity*\n\nA quantity is an amount (implemented as a double precision number) together with a unit of measure.  When arithmetic operations are performed on quantities, the original units can be transformed.  For example, multiplying a length quantity in metres by a force quantity in Newtons results in a quantity of energy in Joules (or Newton-metres).\n\n*Product of Powers*\n\nA unit of measure is represented internally as a product of two other power units of measure:\n\n![Caliper Diagram](https://github.com/point85/caliper/blob/master/doc/PowerProduct.png)\n\nFor a simple scalar UOM (e.g. kilogram), both of the UOMs are null with the exponents defaulted to 0.  For a product UOM (e.g. Newton), the first UOM is the multiplier and the second is the multiplicand with both exponents set to 1.  For a quotient UOM (e.g. kilograms/hour), the first UOM is the dividend and the second is the divisor.  The dividend has an exponent of 1 and the divisor an exponent of -1.  For a power UOM (e.g. square metres), the first UOM is the base and the exponent is the power.  In this case, the second UOM is null with the exponent defaulted to 0.\n\nFrom the two power products, a unit of measure can then be recursively reduced to a map of base units of measure and corresponding exponents along with a scaling factor.  For example, a Newton reduces to (kg, 1), (m, 1), (s, -2) in the SI system.  Multiplying, dividing and converting a unit of measure is accomplished by merging the two maps (i.e. \"cancelling out\" units) and then computing the overall scaling factor.  The base symbol is obtained directly from the final map.\n \n## Code Examples\nThe singleton unified MeasurementSystem is obtained by calling:\n```java\nMeasurementSystem sys = MeasurementSystem.getSystem();\n```\nThe Unit.properties file defines the name, symbol, description and UCUM symbol for each of the predefined units in the following code examples.  The Unit.properties file is localizable.  For example, 'metres' can be changed to use the US spelling 'meters' or descriptions can be translated to another language.\n\nThe metre scalar UOM is created by the MeasurementSystem as follows:\n```java\nUnitOfMeasure uom = createScalarUOM(UnitType.LENGTH, Unit.METRE, symbols.getString(\"m.name\"),\n\tsymbols.getString(\"m.symbol\"), symbols.getString(\"m.desc\"));\n``` \n\nThe square metre power UOM is created by the MeasurementSystem as follows: \n```java\nUnitOfMeasure uom = createPowerUOM(UnitType.AREA, Unit.SQUARE_METRE, symbols.getString(\"m2.name\"),\n\tsymbols.getString(\"m2.symbol\"), symbols.getString(\"m2.desc\"), getUOM(Unit.METRE), 2);\n```\n\nThe metre per second quotient UOM is created by the MeasurementSystem as follows: \n```java\nUnitOfMeasure uom = createQuotientUOM(UnitType.VELOCITY, Unit.METRE_PER_SEC, \n\tsymbols.getString(\"mps.name\"), symbols.getString(\"mps.symbol\"), symbols.getString(\"mps.desc\"),  \n\tgetUOM(Unit.METRE), getSecond());\n```\n\nThe Newton product UOM is created by the MeasurementSystem as follows: \n```java\nUnitOfMeasure uom = createProductUOM(UnitType.FORCE, Unit.NEWTON, symbols.getString(\"newton.name\"),\n\tsymbols.getString(\"newton.symbol\"), symbols.getString(\"newton.desc\"),\n\tgetUOM(Unit.KILOGRAM), getUOM(Unit.METRE_PER_SECOND_SQUARED));\n```\n\nA millisecond is 1/1000th of a second with a defined prefix and created as:\n\n```java\nUnitOfMeasure second = sys.getSecond();\nUnitOfMeasure msec = sys.getUOM(Prefix.MILLI, second);\n```\n\nFor a second example, a US gallon = 231 cubic inches:\n```java\t\t\t\nUnitOfMeasure uom = createScalarUOM(UnitType.VOLUME, Unit.US_GALLON, symbols.getString(\"us_gallon.name\"),\n\tsymbols.getString(\"us_gallon.symbol\"), symbols.getString(\"us_gallon.desc\"));\nuom.setConversion(231d, getUOM(Unit.CUBIC_INCH));\n```\n\nWhen creating the foot unit of measure in the unified measurement system, a bridge conversion to metre is defined (1 foot = 0.3048m):\n```java\nUnitOfMeasure uom = createScalarUOM(UnitType.LENGTH, Unit.FOOT, symbols.getString(\"foot.name\"),\n\tsymbols.getString(\"foot.symbol\"), symbols.getString(\"foot.desc\"));\n\n// bridge to SI\nuom.setBridgeConversion(0.3048, getUOM(Unit.METRE), 0);\n```\n\nCustom units and conversions can also be created:\n```java\n// gallons per hour\nUnitOfMeasure gph = sys.createQuotientUOM(UnitType.VOLUMETRIC_FLOW, \"gph\", \"gal/hr\", \"gallons per hour\", \n\tsys.getUOM(Unit.US_GALLON), sys.getHour());\n\n// 1 16 oz can = 16 fl. oz.\nUnitOfMeasure one16ozCan = sys.createScalarUOM(UnitType.VOLUME, \"16 oz can\", \"16ozCan\", \"16 oz can\");\none16ozCan.setConversion(16d, sys.getUOM(Unit.US_FLUID_OUNCE));\n\n// 400 cans = 50 US gallons\nQuantity q400 = new Quantity(400d, one16ozCan);\nQuantity q50 = q400.convert(sys.getUOM(Unit.US_GALLON));\n\n// 1 12 oz can = 12 fl.oz.\nUnitOfMeasure one12ozCan = sys.createScalarUOM(UnitType.VOLUME, \"12 oz can\", \"12ozCan\", \"12 oz can\");\none12ozCan.setConversion(12d, sys.getUOM(Unit.US_FLUID_OUNCE));\n\n// 48 12 oz cans = 36 16 oz cans\nQuantity q48 = new Quantity(48d, one12ozCan);\nQuantity q36 = q48.convert(one16ozCan);\n\n// 6 12 oz cans = 1 6-pack of 12 oz cans\nUnitOfMeasure sixPackCan = sys.createScalarUOM(UnitType.VOLUME, \"6-pack\", \"6PCan\", \"6-pack of 12 oz cans\");\nsixPackCan.setConversion(6d, one12ozCan);\t\n\n// 1 case = 4 6-packs\nUnitOfMeasure fourPackCase = sys.createScalarUOM(UnitType.VOLUME, \"6-pack case\", \"4PCase\", \"four 6-packs\");\nfourPackCase.setConversion(4d, sixPackCan);\n\t\t\n// A beer bottling line is rated at 2000 12 ounce cans/hour (US) at the\n// filler. The case packer packs four 6-packs of cans into a case.\n// Assuming no losses, what should be the rating of the case packer in\n// cases per hour? And, what is the draw-down rate on the holding tank\n// in gallons/minute?\nUnitOfMeasure canph = sys.createQuotientUOM(one12ozCan, sys.getHour());\nUnitOfMeasure caseph = sys.createQuotientUOM(fourPackCase, sys.getHour());\nUnitOfMeasure gpm = sys.createQuotientUOM(sys.getUOM(Unit.US_GALLON), sys.getMinute());\n\t\t\n// filler production rate\nQuantity filler = new Quantity(2000d, canph);\n\n// tank draw-down\nQuantity draw = filler.convert(gpm);\n\n// case packer production\nQuantity packer = filler.convert(caseph);\n```\n\nQuantities can be added, subtracted and converted:\n```java\nUnitOfMeasure m = sys.getUOM(Unit.METRE);\nUnitOfMeasure cm = sys.getUOM(Prefix.CENTI, m);\n\t\t\nQuantity q1 = new Quantity(2d, m);\nQuantity q2 = new Quantity(2d, cm);\n\t\t\n// add two quantities.  q3 is 2.02 metre\nQuantity q3 = q1.add(q2);\n\t\t\n// q4 is 202 cm\nQuantity q4 = q3.convert(cm);\n\t\t\n// subtract q1 from q3 to get 0.02 metre\nq3 = q3.subtract(q1);\n```\n\nas well as multiplied and divided:\n```java\nQuantity q1 = new Quantity(50d, cm);\nQuantity q2 = new Quantity(50d, cm);\n\t\t\n// q3 = 2500 cm^2\nQuantity q3 = q1.multiply(q2);\n\t\t\n// q4 = 50 cm\nQuantity q4 = q3.divide(q1);\n```\n\nand inverted:\n```java\nUnitOfMeasure mps = sys.getUOM(Unit.METRE_PER_SECOND); \nQuantity q1 = new Quantity(10d, mps);\n\t\t\n// q2 = 0.1 sec/m\nQuantity q2 = q1.invert();\n```\n\nTo make working with linearly scaled units of measure (with no offset) easier, the MeasurementSystem's getUOM() using a Prefix can be used.  This method accepts a Prefix enum and the unit of measure that it is scaled against.  The resulting unit of measure has a name concatented with the Prefix's name and target unit name.  The symbol is formed similarly.  For example, a centilitre (cL) is created from the pre-defined litre by:\n```java\nUnitOfMeasure litre = sys.getUOM(Unit.LITRE);\nUnitOfMeasure cL = sys.getUOM(Prefix.CENTI, litre);\n```\nand, a megabyte (MB = 2^20 bytes) is created by:\n```java\nUnitOfMeasure mB = sys.getUOM(Prefix.MEBI, Unit.BYTE);\n```\n\n*Implicit Conversions*\n\nA quantity can be converted to another unit of measure without requiring the target UOM to first be created.  If the quantity has a product or quotient UOM, use the convertToPowerProduct() method.  For example:\n\n```java\n// convert 1 newton-metre to pound force-inches\nQuantity nmQ = new Quantity(1.0, sys.getUOM(Unit.NEWTON_METRE));\nQuantity lbfinQ = nmQ.convertToPowerProduct(sys.getUOM(Unit.POUND_FORCE), sys.getUOM(Unit.INCH));\n```\n\nIf the quantity has power UOM, use the convertToPower() method.  For example:\n\n```java\n// convert 1 square metre to square inches\nQuantity m2Q = new Quantity(1.0, sys.getUOM(Unit.SQUARE_METRE));\nQuantity in2Q = m2Q.convertToPower(sys.getUOM(Unit.INCH));\n```\n\nOther UOMs can be converted using the convert() method.\n\n*Classification*\n\nDuring arithmetic operations, the final type of the unit may not be known.  In this case, invoking the classify() method will attempt to find a matching unit type.  For example, the calculated unit of measure below has a type of UnitType.ELECTRIC_CAPACITANCE:\n\n```java\nUnitOfMeasure s = sys.getSecond();\nUnitOfMeasure m = sys.getUOM(Unit.METRE);\nUnitOfMeasure kg = sys.getUOM(Unit.KILOGRAM);\nUnitOfMeasure amp = sys.getUOM(Unit.AMPERE);\n\t\t\nUnitOfMeasure cap = s.power(-3).multiply(amp.power(-2)).multiply(m.power(2)).divide(kg).classify();\n```\n\nA quantity resulting from an arithmetic operation can also be classified.  For example, the \"density\" quantity has UnitType.DENSITY:\n\n```java\nQuantity mass = new Quantity(1035, Unit.KILOGRAM);\nQuantity volume = new Quantity(1000, Unit.LITRE);\nQuantity density = mass.divide(volume).classify();\n```\n\n## Physical Unit Examples\n\nWater boils at 100 degrees Celcius.  What is this temperature in Fahrenheit?\n```java\nQuantity qC = new Quantity(100.0, Unit.CELSIUS);\nQuantity qF = qC.convert(Unit.FAHRENHEIT);\n```\n\nA nutrition label states the energy content is 1718 KJ.  What is this amount in kilo-calories?\n```java\nQuantity kcal = new Quantity(1718, Prefix.KILO, Unit.JOULE).convert(Prefix.KILO, Unit.CALORIE);\n```\n\nOne's Body Mass Index (BMI) can be calculated as:\n```java\nQuantity height = new Quantity(2d, Unit.METRE);\nQuantity mass = new Quantity(100d, Unit.KILOGRAM);\nQuantity bmi = mass.divide(height.multiply(height));\n```\n\nEinstein's famous E = mc^2:\n```java\nQuantity c = sys.getQuantity(Constant.LIGHT_VELOCITY);\nQuantity m = new Quantity(1.0, Unit.KILOGRAM);\nQuantity e = m.multiply(c).multiply(c);\n```\n\n```java\n// A Tesla Model S battery has a capacity of 100 KwH.  \n// When fully charged, how many electrons are in the battery?\nQuantity c = sys.getQuantity(Constant.LIGHT_VELOCITY);\nQuantity me = sys.getQuantity(Constant.ELECTRON_MASS);\t\nQuantity kwh = new Quantity(100, Prefix.KILO, Unit.WATT_HOUR);\nQuantity electrons = kwh.divide(c).divide(c).divide(me);\n```\n\nIdeal Gas Law, PV = nRT.  A cylinder of argon gas contains 50.0 L of Ar at 18.4 atm and 127 -C.  How many moles of argon are in the cylinder?\n```java\nQuantity p = new Quantity(18.4, Unit.ATMOSPHERE).convert(Unit.PASCAL);\nQuantity v = new Quantity(50d, Unit.LITRE).convert(Unit.CUBIC_METRE);\nQuantity t = new Quantity(127d, Unit.CELSIUS).convert(Unit.KELVIN);\nQuantity n = p.multiply(v).divide(sys.getQuantity(Constant.GAS_CONSTANT).multiply(t));\n```\n\nPhoton energy using Planck's constant:\n```java\n// energy of red light photon = Planck's constant times the frequency\nQuantity frequency = new Quantity(400d, sys.getUOM(Prefix.TERA, Unit.HERTZ));\nQuantity ev = sys.getQuantity(Constant.PLANCK_CONSTANT).multiply(frequency).convert(Unit.ELECTRON_VOLT);\n\n// and wavelength of red light in nanometres (approx 749.48)\nQuantity wavelength = sys.getQuantity(Constant.LIGHT_VELOCITY).divide(frequency).convert(sys.getUOM(Prefix.NANO, Unit.METRE));\n```\n\nNewton's second law of motion (F = ma). Weight of 1 kg in lbf:\n```java\nQuantity mkg = new Quantity(1d, Unit.KILOGRAM);\nQuantity f = mkg.multiply(sys.getQuantity(Constant.GRAVITY)).convert(Unit.POUND_FORCE);\n```\nUnits per volume of solution, C = A x (m/V)\n```java\n// create the \"A\" unit of measure\nUnitOfMeasure activityUnit = sys.createQuotientUOM(UnitType.UNCLASSIFIED, \"activity\", \"act\",\n\t\"activity of material\", sys.getUOM(Unit.UNIT), sys.getUOM(Prefix.MILLI, Unit.GRAM));\n\n// calculate concentration\nQuantity activity = new Quantity(1d, activityUnit);\nQuantity grams = new Quantity(1d, Unit.GRAM).convert(Prefix.MILLI, Unit.GRAM);\nQuantity volume = new Quantity(1d, sys.getUOM(Prefix.MILLI, Unit.LITRE));\nQuantity concentration = activity.multiply(grams.divide(volume));\nQuantity katals = concentration.multiply(new Quantity(1d, Unit.LITRE)).convert(Unit.KATAL);\n```\nBlack body radiation:\n\n```java\n// The Stefan-Boltzmann law states that the power emitted per unit area\n// of the surface of a black body is directly proportional to the fourth\n// power of its absolute temperature: sigma * T^4\n// calculate at 1000 Kelvin\nQuantity temp = new Quantity(1000.0, Unit.KELVIN);\nQuantity intensity = sys.getQuantity(Constant.STEFAN_BOLTZMANN).multiply(temp.power(4));\n```\n\nExpansion of the universe:\n\n```java\n// Hubble's law, v = H0 x D. Let D = 10 Mpc\nQuantity d = new Quantity(10d, sys.getUOM(Prefix.MEGA, sys.getUOM(Unit.PARSEC)));\nQuantity h0 = sys.getQuantity(Constant.HUBBLE_CONSTANT);\nQuantity velocity = h0.multiply(d);\n```\n\nDevice Characteristic Life\n\n```java\n// A device has an activation energy of 0.5 and a characteristic life of\n// 2,750 hours at an accelerated temperature of 150 degrees Celsius.\n// Calculate the characteristic life at an expected use temperature of\n// 85 degrees Celsius.\n\n// Convert the Boltzman constant from J/K to eV/K for the Arrhenius equation\nQuantity j = new Quantity(1d, Unit.JOULE);\nQuantity eV = j.convert(Unit.ELECTRON_VOLT);\n// Boltzmann constant\nQuantity Kb = sys.getQuantity(Constant.BOLTZMANN_CONSTANT).multiply(eV.getAmount());\n// accelerated temperature\nQuantity Ta = new Quantity(150d, Unit.CELSIUS);\n// expected use temperature\nQuantity Tu = new Quantity(85d, Unit.CELSIUS);\n// calculate the acceleration factor\nQuantity factor1 = Tu.convert(Unit.KELVIN).invert().subtract(Ta.convert(Unit.KELVIN).invert());\nQuantity factor2 = Kb.invert().multiply(0.5);\nQuantity factor3 = factor1.multiply(factor2);\ndouble AF = Math.exp(factor3.getAmount());\n// calculate longer life at expected use temperature\nQuantity life85 = new Quantity(2750d, Unit.HOUR);\nQuantity life150 = life85.multiply(AF);\n```\n\n## Financial Examples\n\nValue of a stock portfolio:\n\n```java\n// John has 100 shares of Alphabet Class A stock. How much is his\n// portfolio worth in euros when the last trade was $838.96 and a US\n// dollar is worth 0.94 euros?\nUnitOfMeasure euro = sys.getUOM(Unit.EURO);\nUnitOfMeasure usd = sys.getUOM(Unit.US_DOLLAR);\nusd.setConversion(0.94, euro);\n\nUnitOfMeasure googl = sys.createScalarUOM(UnitType.CURRENCY, \"Alphabet A\", \"GOOGL\",\n\t\"Alphabet (formerly Google) Class A shares\");\ngoogl.setConversion(838.96, usd);\nQuantity portfolio = new Quantity(100, googl);\nQuantity value = portfolio.convert(euro);\n```\n\n## Medical Examples\n\n```java\n// convert Unit to nanokatal\nUnitOfMeasure u = sys.getUOM(Unit.UNIT);\nUnitOfMeasure katal = sys.getUOM(Unit.KATAL);\nQuantity q1 = new Quantity(1.0, u);\nQuantity q2 = q1.convert(sys.getUOM(Prefix.NANO, katal));\n\n// test result Equivalent\nUnitOfMeasure eq = sys.getUOM(Unit.EQUIVALENT);\nUnitOfMeasure litre = sys.getUOM(Unit.LITRE);\nUnitOfMeasure mEqPerL = sys.createQuotientUOM(UnitType.MOLAR_CONCENTRATION, \"milliNormal\", \"mEq/L\",\n\t\"solute per litre of solvent \", sys.getUOM(Prefix.MILLI, eq), litre);\nQuantity testResult = new Quantity(5.0, mEqPerL);\n\n// blood cell count test results\nUnitOfMeasure k = sys.getUOM(Prefix.KILO, sys.getOne());\nUnitOfMeasure uL = sys.getUOM(Prefix.MICRO, Unit.LITRE);\nUnitOfMeasure kul = sys.createQuotientUOM(UnitType.MOLAR_CONCENTRATION, \"K/uL\", \"K/uL\",\n\t\"thousands per microlitre\", k, uL);\ntestResult = new Quantity(7.0, kul);\n\nUnitOfMeasure fL = sys.getUOM(Prefix.FEMTO, Unit.LITRE);\ntestResult = new Quantity(90d, fL);\n\n// TSH test result\nUnitOfMeasure uIU = sys.getUOM(Prefix.MICRO, Unit.INTERNATIONAL_UNIT);\nUnitOfMeasure mL = sys.getUOM(Prefix.MILLI, Unit.LITRE);\nUnitOfMeasure uiuPerml = sys.createQuotientUOM(UnitType.MOLAR_CONCENTRATION, \"uIU/mL\", \"uIU/mL\",\n\t\"micro IU per millilitre\", uIU, mL);\ntestResult = new Quantity(2.0, uiuPerml);\n```\n\n## Multi-unit Conversions\n\n```java\n// convert 74 inches to feet and inches\nQuantity qHeight = new Quantity(74, Unit.INCH);\nList\u003cUnitOfMeasure\u003e uoms = new ArrayList\u003c\u003e();\nuoms.add(sys.getUOM(Unit.FOOT));\nuoms.add(sys.getUOM(Unit.INCH));\nList\u003cQuantity\u003e converted = qHeight.convert(uoms);\n```\n\n## Converting Mixed Units of Measure\n\nIn general, Caliper does not support conversion of mixed units of measure.  For example, if customary and SI units appear together in either a quotient or product unit of measurement (e.g. density in kilogram/cubic foot), \nconversion to another consistent unit of measure (e.g. density in lbm/litre) requires a case-by-case solution.  The practical case below from the mining and precious metals industry illustrates this approach.\n\nCaliper defines a troy ounce (troyOz) as 0.06857142857 pound-mass.  Now define the pennyweight based on a troy ounce where sys = MeasurementSystem.instance():\n```java\nUnitOfMeasure pennyweight = sys.createScalarUOM(UnitType.MASS, \"pennyweight\", \"dwt\", \"Pennyweight\");\npennyweight.setConversion(0.05, troyOz);\n```\nNow create a unitless quotient UOM for metal grade:\n```java\nUnitOfMeasure pennyweightPerShortTon = sys.createQuotientUOM(pennyweight, sys.getUOM(Unit.US_TON)); \n```\nLet's convert a precious metal grade defined in SI units to pennyweight customary units:\n```java\nUnitOfMeasure gramsPerTonne = sys.createQuotientUOM(sys.getUOM(Unit.GRAM), sys.getUOM(Unit.TONNE));\nQuantity qGrade = new Quantity(0.95, gramsPerTonne);\t\nQuantity qGradeConverted = qGrade.convert(pennyweightPerShortTon);\n```\nThe converted grade is about 0.554167.  These conversions work since the quotient units are defined within a consistent system (SI and Customary in this example).\n\nNow suppose we want to convert a mixed unit grade in grams per metric tonne to troy ounces per metric tonne.  This will require defining another troy ounce based on grams:\n```java\nUnitOfMeasure troyOzSI = sys.createScalarUOM(UnitType.MASS, \"troy ounce SI\", \"troy oz\", \"Troy ounce SI conversion\");\ntroyOzSI.setConversion(31.1034768, sys.getUOM(Unit.GRAM));\n\nUnitOfMeasure troyOzPerTonne = sys.createQuotientUOM(troyOzSI, sys.getUOM(Unit.TONNE));\nQuantity qGradeConverted = qGrade.convert(troyOzPerTonne);\n```\nThe grade when converted to troyOzPerTonne is about 0.0305432.\n\n## The Kilogram and Planck's Constant\nThe new kilogram is defined based on Planck's constan.  It can be understood as the mass difference of the number of cesium-133  atoms in the ground state versus the same number in the excited hyperfine state.\nOr,  or as the mass of the number of photons at the Cesium-133 hyperfine frequency trapped in a microwave cavity. \n\nWhat is this number?\n\nThis number can be calculated from Plancks' constant (h), the definition of a second in terms of ∆νCs: the hyperfine transition frequency of cesium-133 and the speed of light in a vacuum, and the speed of light in a vacuum (c):\n\ncount/kg = c^2 / (h * ∆νCs)\n\nThe Java calculation for 1.475521E40/kg is \n\n```java\nMeasurementSystem sys = MeasurementSystem.getSystem();\n\n// Planck's constant\nQuantity planck = sys.getQuantity(Constant.PLANCK_CONSTANT);\nSystem.out.println(planck);\n\n// cesium-133 hyperfine transition frequency\nQuantity vCs = new Quantity(9.192631770E+09, Unit.HERTZ);\nSystem.out.println(vCs);\n\n// speed of light\nQuantity c = sys.getQuantity(Constant.LIGHT_VELOCITY);\nSystem.out.println(c);\n\n// number of cesium 133 atoms in a kilogram\nQuantity kgCount = c.power(2).divide(planck.multiply(vCs));\nSystem.out.println(kgCount);\n```\n\nwith output:\n```java\n6.62607015E-34, [Type: UNCLASSIFIED, Symbol: J·s, Conversion: J·s, Base Symbol: kg·m²/s]  (hc, Planck's constant, Planck's constant)\n9.19263177E9, [Type: FREQUENCY, Enumeration: HERTZ, Symbol: Hz, Conversion: Hz, Base Symbol: 1/s] \n2.99792458E8, [Type: VELOCITY, Enumeration: METRE_PER_SEC, Symbol: m/s, Conversion: m/s, Base Symbol: m/s]  (c, Vc, velocity of light in a vacuum)\n1.475521399735271E40, [Type: UNCLASSIFIED, Symbol: m/s^2/J·s·Hz, Conversion: m/s^2/J·s·Hz, Base Symbol: 1/kg] \n```\n\n### Caching\nA unit of measure once created is registered in two hashmaps, one by its base symbol key and the second one by its enumeration key.  Caching greatly increases performance since the unit of measure is created only once.  Methods are provided to clear the cache of all instances as well as to unregister a particular instance.\n\nThe double value of a unit of measure conversion is also cached.  This performance optimization eliminates the need to calculate the conversion multiple times if many quantities are being converted at once; for example, operations upon a vector or matrix of quantities all with the same unit of measure.\n\n## Localization\nAll externally visible text is defined in two resource bundle .properties files.  The Unit.properties file has the name (.name), symbol (.symbol) and description (.desc) for a unit of measure as well as toString() method text.  The Message.properties file has the text for an exception.  A default English file for each is included in the project.  The files can be translated to another language by following the Java locale naming conventions for the properties file, or the English version can be edited, e.g. to change \"metre\" to \"meter\".  For example, a metre's text is:\n\n```java\n# metre\nm.name = metre\nm.symbol = m\nm.desc = The length of the path travelled by light in vacuum during a time interval of 1/299792458 of a second.\n```\n\nand for an exception:\n```java\nalready.created = The unit of measure with symbol {0} has already been created by {1}.  Did you intend to scale this unit with a linear conversion?\n```\n\n\n## Project Structure\nThe Caliper library depends on Java 11+.  The unit tests depend on JUnit (http://junit.org/junit4/), Hamcrest (http://hamcrest.org/), Gson (https://github.com/google/gson) and HTTP Request (https://github.com/kevinsawicki/http-request).\n\nThe Maven repository is:\n```java\n\u003cdependency\u003e\n\u003cgroupId\u003eio.github.point85\u003c/groupId\u003e\n\u003cartifactId\u003ecaliper\u003c/artifactId\u003e\n\u003cversion\u003e1.2.7\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## JSR 363\nJSR 363 \"proposes to establish safe and useful methods for modeling physical quantities\" (https://java.net/downloads/unitsofmeasurement/JSR363Specification_EDR.pdf).  Caliper shares many of the underlying aspects of JSR 363.  Caliper however does not use Java generics, and there is only one system of units.  Caliper performs math using double amounts whereas JSR 363 uses Numbers.\n\nThe tables below compare the JSR 363 specification in the first column to Point85 in the second column.\n\n![Caliper Diagram](https://github.com/point85/caliper/blob/master/doc/jsr363_type.png)\n\n![Caliper Diagram](https://github.com/point85/caliper/blob/master/doc/jsr363_uom.png)\n\n![Caliper Diagram](https://github.com/point85/caliper/blob/master/doc/jsr363_quantity.png)\n\n![Caliper Diagram](https://github.com/point85/caliper/blob/master/doc/jsr363_rest.png)\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoint85%2Fcaliper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpoint85%2Fcaliper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoint85%2Fcaliper/lists"}