PHPackages                             kolaybi/unit-converter - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. kolaybi/unit-converter

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

kolaybi/unit-converter
======================

A PHP 8.4+ unit conversion package compatible with UN/CEFACT Recommendation 20

v1.0.0(2mo ago)00MITPHPPHP ^8.4CI passing

Since Mar 4Pushed 2mo agoCompare

[ Source](https://github.com/kolaybi/unit-converter)[ Packagist](https://packagist.org/packages/kolaybi/unit-converter)[ RSS](/packages/kolaybi-unit-converter/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (5)Used By (0)

Unit Converter
==============

[](#unit-converter)

A PHP 8.4+ framework-agnostic package for converting between 2,216 units of measurement based on [UN/CEFACT Recommendation 20](https://unece.org/trade/uncefact/cl-recommendations), [Recommendation 21](https://unece.org/trade/uncefact/cl-recommendations) (package types), and the [GS1 unit conversion model](https://www.gs1.org/).

Uses arbitrary-precision math (bcmath) with the GS1 multiplier + offset formula to handle both linear conversions (mass, length, volume, etc.) and non-linear ones (temperature).

Requirements
------------

[](#requirements)

- PHP 8.4+
- ext-bcmath

Installation
------------

[](#installation)

```
composer require kolaybi/unit-converter
```

Quick Start
-----------

[](#quick-start)

```
use KolayBi\UnitConverter\Converter;
use KolayBi\UnitConverter\Units\Mass;
use KolayBi\UnitConverter\Units\Temperature;

// Using enum cases
$result = Converter::convert(10)->from(Mass::Kilogram)->to(Mass::Pound);
echo $result->round(2); // "22.05"

// Using UN/CEFACT codes
$result = Converter::convert(1)->from('KGM')->to('LBR');
echo $result->toFloat(); // 2.20462262...

// Using symbols
$result = Converter::convert(100)->from('°C')->to('°F');
echo $result->round(1); // "212.0"

// Using labels
$result = Converter::convert(1)->from('kilogram')->to('gram');
echo $result->value; // "1000.00000000000000000000"

// Default value is 1 — handy for conversion factors
$result = Converter::convert()->from(Mass::Kilogram)->to(Mass::Pound);
echo $result->round(6); // "2.204623"
```

API
---

[](#api)

### `Converter::convert(int|float|string $value = 1): PendingConversion`

[](#converterconvertintfloatstring-value--1-pendingconversion)

Entry point. Accepts any numeric value. Defaults to `1`, useful for looking up conversion factors.

### `PendingConversion::from(Unit|string $unit): self`

[](#pendingconversionfromunitstring-unit-self)

Set the source unit. Accepts an enum case, UN/CEFACT code, symbol, or label.

### `PendingConversion::to(Unit|string $unit): ConversionResult`

[](#pendingconversiontounitstring-unit-conversionresult)

Convert to the target unit and return the result.

### `Converter::unit(string $input): Unit`

[](#converterunitstring-input-unit)

Resolve a unit by UN/CEFACT code, symbol, or label. Returns the `Unit` enum case.

```
$unit = Converter::unit('kg');
$unit->code();   // 'KGM'
$unit->symbol(); // 'kg'
$unit->label();  // 'kilogram'
```

### `PendingConversion::toAll(): array`

[](#pendingconversiontoall-arraystring-string)

Convert to all other units in the same category. Returns an array keyed by UN/CEFACT code.

### `ConversionResult`

[](#conversionresult)

```
$result->value;              // Full-precision string
$result->toFloat();          // PHP float
$result->round(2);           // "22.05"
$result->format(2, ',', '.'); // "1.234,57"
(string) $result;            // Same as ->value
$result->from;               // Source Unit enum
$result->to;                 // Target Unit enum
```

Unit Categories
---------------

[](#unit-categories)

58 categories covering 2,216 units (780 convertible + 1,436 non-convertible):

CategoryUnitsCategoryUnitsAbsorbed Dose4Kinematic Viscosity7Absorbed Dose Rate11Length34Acceleration11Luminous Intensity3Amount of Substance4Magnetic Flux3Angle9Magnetic Flux Density6Angular Impulse3Magnetic Vector Potential3Angular Velocity4Mass34Area20Memory Capacity15Capacitance7Molar Concentration5Charge13Molar Mass2Conductance7Molar Thermodynamic Energy2Counting14Molar Volume4Current9Package Type ⊘406Data Rate12Packaging ⊘52Density28Power44Dimensionless Concentration24Pressure42Dynamic Viscosity19Radioactivity9Effective Dose4Resistance8Effective Dose Rate13Signal Rate3Energy34Specific Volume7Energy Density7Speed23Exposure2Temperature4Flow Rate93Textile Density3Force15Time18Frequency10Torque16Illuminance6Trade ⊘978Impulse6Voltage6Inductance6Volume66Irradiance14Wavenumber4⊘ = non-convertible (code resolution only)

Package Types (Rec 21)
----------------------

[](#package-types-rec-21)

406 package types from [UNECE Recommendation 21](https://unece.org/trade/uncefact/cl-recommendations) (Rev. 12) are available via the `PackageType` enum.

Per Rec 20 guidance, each 2-character Rec 21 code is prefixed with `X` to form a 3-character unit-of-measure code (reserved range `X00`–`XZZ`). The native Rec 21 code is also available as an alias.

```
use KolayBi\UnitConverter\Converter;
use KolayBi\UnitConverter\Units\PackageType;

// Using X-prefixed code
$unit = Converter::unit('XBG');  // PackageType::Bag
$unit->code();                   // 'XBG'
$unit->rec21Code();              // 'BG'
$unit->label();                  // 'bag'

// Using label
$unit = Converter::unit('aerosol'); // PackageType::Aerosol (code: XAE)

// Using enum case directly
$unit = PackageType::DrumSteel;     // code: X1A
```

> **Resolution priority:** When a Rec 21 native code conflicts with a Rec 20 code (23 shared codes like `BG`, `DR`, `TU`), Rec 20 takes priority. Use the X-prefixed code to explicitly target the Rec 21 entry.

Unit Resolution
---------------

[](#unit-resolution)

Units can be resolved by:

- **Enum case**: `Mass::Kilogram`
- **UN/CEFACT code**: `'KGM'` (case-sensitive)
- **Symbol**: `'kg'` (case-insensitive)
- **Label**: `'kilogram'` (case-insensitive)

```
// All equivalent
Converter::convert(1)->from(Mass::Kilogram)->to(Mass::Pound);
Converter::convert(1)->from('KGM')->to('LBR');
Converter::convert(1)->from('kg')->to('lb');
Converter::convert(1)->from('kilogram')->to('pound');
```

Error Handling
--------------

[](#error-handling)

```
use KolayBi\UnitConverter\Exceptions\IncompatibleUnitsException;
use KolayBi\UnitConverter\Exceptions\NonConvertibleUnitException;
use KolayBi\UnitConverter\Exceptions\UnitNotFoundException;

// Incompatible categories
Converter::convert(1)->from(Mass::Kilogram)->to(Temperature::Celsius);
// throws IncompatibleUnitsException

// Non-convertible units (packaging)
Converter::convert(1)->from(Packaging::Box)->to(Packaging::Bag);
// throws NonConvertibleUnitException

// Unknown unit string
Converter::convert(1)->from('not_a_real_unit')->to('abc');
// throws UnitNotFoundException
```

How It Works
------------

[](#how-it-works)

All convertible units use the GS1 multiplier + offset model relative to a base unit per category:

```
base_value = input_value × multiplier + offset
output_value = (base_value - target_offset) ÷ target_multiplier

```

For most categories (mass, length, volume, etc.), the offset is 0, making it a simple ratio. Temperature uses non-zero offsets to handle Celsius (offset 273.15) and Fahrenheit (multiplier 5/9, offset 255.37).

All math uses `bcmath` with a scale of 20 decimal places.

Code Generation
---------------

[](#code-generation)

The convertible unit enums are generated from the GS1 datatable:

```
php bin/generate-enums.php [path-to-json]
```

Development
-----------

[](#development)

```
composer install
vendor/bin/phpunit           # Run tests
vendor/bin/phpstan analyse   # Static analysis (level 9)
vendor/bin/pint              # Code style
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/kolaybi/.github/blob/master/CONTRIBUTING.md) for details.

License
-------

[](#license)

Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 87% of packages

Maintenance93

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

66d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/55d848a38c4172de8d020b7ebe2a586b41c9924a2d048670a67ddd6c53268fb5?d=identicon)[kolaybi](/maintainers/kolaybi)

---

Top Contributors

[![uguurozkan](https://avatars.githubusercontent.com/u/6731054?v=4)](https://github.com/uguurozkan "uguurozkan (44 commits)")

---

Tags

cefactconversionedocumentsi-unitsuneceunit-converter

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/kolaybi-unit-converter/health.svg)

```
[![Health](https://phpackages.com/badges/kolaybi-unit-converter/health.svg)](https://phpackages.com/packages/kolaybi-unit-converter)
```

###  Alternatives

[tga/simhash-php

SimHash similarities algorithm implementation for PHP 5.3

15243.5k1](/packages/tga-simhash-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
